/*
    SPDX-FileCopyrightText: 2005 Christoph Cullmann <cullmann@kde.org>

    SPDX-License-Identifier: LGPL-2.0-or-later
*/

#include "katesessionsaction.h"
#include "katesessionmanager.h"

#include <KConfig>
#include <QActionGroup>
#include <QMenu>
#include <algorithm>

KateSessionsAction::KateSessionsAction(const QIcon &icon, const QString &text, QObject *parent, KateSessionManager *manager, bool allSessions)
    : KActionMenu(icon, text, parent)
    , m_manager(manager)
    , m_allSessions(allSessions)
{
    connect(menu(), &QMenu::aboutToShow, this, &KateSessionsAction::slotAboutToShow);
    setPopupMode(QToolButton::InstantPopup);

    sessionsGroup = new QActionGroup(menu());

    // reason for Qt::QueuedConnection: when switching session with N mainwindows
    // to e.g. 1 mainwindow, the last N - 1 mainwindows are deleted. Invoking
    // a session switch without queued connection deletes a mainwindow in which
    // the current code path is executed ---> crash. See bug #227008.
    connect(sessionsGroup, &QActionGroup::triggered, this, &KateSessionsAction::openSession, Qt::QueuedConnection);

    connect(m_manager, &KateSessionManager::sessionListChanged, this, &KateSessionsAction::slotSessionChanged);

    setDisabled(m_manager->sessionList().empty());
}

void KateSessionsAction::slotAboutToShow()
{
    qDeleteAll(sessionsGroup->actions());

    KateSessionList slist = m_manager->sessionList();

    // only show first 10 sessions for recent session menu?
    if (!m_allSessions) {
        std::sort(slist.begin(), slist.end(), KateSession::compareByTimeDesc);
        slist = slist.mid(0, 10); // take first 10
    }

    // sort the reduced list alphabetically (#364089)
    std::sort(slist.begin(), slist.end(), KateSession::compareByName);

    for (const KateSession::Ptr &session : std::as_const(slist)) {
        QString sessionName = session->name();
        sessionName.replace(QStringLiteral("&"), QStringLiteral("&&"));
        auto *action = new QAction(sessionName, sessionsGroup);
        action->setData(QVariant(session->name()));
        action->setCheckable(true);
        action->setChecked(session == m_manager->activeSession());
        menu()->addAction(action);
    }
}

void KateSessionsAction::openSession(QAction *action)
{
    const QString name = action->data().toString();
    m_manager->activateSession(name);
}

void KateSessionsAction::slotSessionChanged()
{
    setDisabled(m_manager->sessionList().empty());
}
