// SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later

#include "shortcutlogging.h"

#include "shortcutmanager.h"
#include "keybindingmanager.h"
#include "gesturemanager.h"
#include "actionexecutor.h"
#include "serviceactionexecutor.h"
#include "translationmanager.h"
#include "sessionactivemonitor.h"
#include "config/configloader.h"
#include "backend/x11/x11keyhandler.h"
#include "backend/x11/x11gesturehandler.h"
#include "backend/x11/x11gestureactionexecutor.h"
#include "backend/wayland/waylandkeyhandler.h"
#include "backend/wayland/waylandgesturehandler.h"
#include "backend/wayland/treelandshortcutwrapper.h"

#include <DGuiApplicationHelper>

#include <QDBusConnection>
#include <QDebug>
#include <qobjectdefs.h>

DGUI_USE_NAMESPACE

ShortcutManager::ShortcutManager(QObject *parent)
    : QObject(parent)
    , m_loader(new ConfigLoader(this))
    , m_executor(new ActionExecutor(this))
    , m_translationManager(new TranslationManager(this))
    , m_serviceActionExecutor(new ServiceActionExecutor(m_executor, this))
    , m_sessionMonitor(new SessionActiveMonitor(this))
{
    m_isWayland = DGuiApplicationHelper::testAttribute(DGuiApplicationHelper::IsWaylandPlatform);
}

ShortcutManager::~ShortcutManager()
{
}

bool ShortcutManager::init()
{
    m_loader->scanForConfigs();
    m_translationManager->init();

    // create Handler
    if (m_isWayland) {
        m_treelandShortcutWrapper = new TreelandShortcutWrapper(this);
        m_keyHandler = new WaylandKeyHandler(m_treelandShortcutWrapper, this);
        m_gestureHandler = new WaylandGestureHandler(m_treelandShortcutWrapper, this);
    } else {
        m_keyHandler = new X11KeyHandler(this);
        m_x11GestureActionExecutor = new X11GestureActionExecutor(this);
        m_gestureHandler = new X11GestureHandler(m_x11GestureActionExecutor,
                                                 m_sessionMonitor, this);
    }

    if (!m_keyHandler || !m_keyHandler->isAvailable()) {
        qCCritical(logShortcut) << "ShortcutManager: Key handler backend not available";
        return false;
    }

    m_keybindingManager = new KeybindingManager(m_loader, m_executor, m_translationManager,
                                                m_keyHandler, m_sessionMonitor,
                                                m_x11GestureActionExecutor, this);

    m_gestureManager = new GestureManager(m_loader, m_executor, m_translationManager, m_gestureHandler,
                                          m_x11GestureActionExecutor, m_serviceActionExecutor, this);

    // Note: In plugin mode, DBus registration is handled by PluginShortcutManager
    // Uncomment the following lines for standalone application mode
    // if (!registerDBusService()) {
    //     return false;
    // }

    // 5. Handle protocol lifecycle
    if (m_isWayland) {
        // Connect signals first to ensure we don't miss the ready signal
        connect(m_treelandShortcutWrapper, &TreelandShortcutWrapper::ready,
                this, &ShortcutManager::registerAll);
        connect(m_treelandShortcutWrapper, &TreelandShortcutWrapper::protocolInactive,
                this, &ShortcutManager::onProtocolInactive);
        
        // Then initialize protocol (signals are connected, ready will only trigger once)
        m_treelandShortcutWrapper->initProtocol();
    } else {
        // X11: Register all directly
        registerAll();
    }

    return true;
}

bool ShortcutManager::registerDBusService()
{
    QDBusConnection connection = QDBusConnection::sessionBus();

    // Register Keybinding service
    if (!connection.registerService("org.deepin.dde.Keybinding1")) {
        qCCritical(logShortcut) << "Failed to register DBus service org.deepin.dde.Keybinding1";
        return false;
    }

    if (!connection.registerObject("/org/deepin/dde/Keybinding1", m_keybindingManager,
                                   QDBusConnection::ExportAllSlots | 
                                   QDBusConnection::ExportAllSignals |
                                   QDBusConnection::ExportAllProperties)) {
        qCCritical(logShortcut) << "Failed to register DBus object for Keybinding1";
        return false;
    }

    qCInfo(logShortcut) << "Deepin Keybinding Service started.";

    // Register Gesture service
    if (m_gestureManager) {
        if (!connection.registerService("org.deepin.dde.Gesture1")) {
            qCCritical(logShortcut) << "Failed to register DBus service org.deepin.dde.Gesture1";
            return false;
        }

        if (!connection.registerObject("/org/deepin/dde/Gesture1", m_gestureManager,
                                    QDBusConnection::ExportAllSlots | QDBusConnection::ExportAllSignals)) {
            qCCritical(logShortcut) << "Failed to register DBus object for Gesture1";
            return false;
        }

        qCInfo(logShortcut) << "Deepin Gesture Service started.";
    }

    return true;
}

void ShortcutManager::registerAll()
{
    qCInfo(logShortcut) << "ShortcutManager: Protocol ready, registering all shortcuts and gestures...";
    // Register all shortcuts
    m_keybindingManager->registerAllShortcuts();

    if (m_gestureManager) {
        // only for wayland
        m_gestureManager->registerAllGestures();
    }

    if (m_isWayland) {
        bool success = m_treelandShortcutWrapper->commitAndWait();
        if (success) {
            qCInfo(logShortcut) << "ShortcutManager: All shortcuts and gestures registered successfully";
        } else {
            qCWarning(logShortcut) << "ShortcutManager: Commit failed";
        }
    }
}

void ShortcutManager::onProtocolInactive()
{
    qCWarning(logShortcut) << "ShortcutManager: Protocol inactive, clearing state...";
    
    // Clear state in both managers
    if (m_keybindingManager) {
        m_keybindingManager->clearState();
    }
    
    if (m_gestureManager) {
        m_gestureManager->clearState();
    }
}
