#include "taskbarwindow.h"
#include <QApplication>
#include <QScreen>
#include <QQuickItem>
#include <QDBusConnection>
#include <QTimer>
#include <QDBusInterface>
#include <QDBusReply>
#include <QDebug>
#include <kwindowsystem.h>
#include <KWayland/Client/connection_thread.h>
#include <KWayland/Client/plasmashell.h>
#include <KWayland/Client/registry.h>
#include <KWayland/Client/surface.h>
#include <windowmanager/windowmanager.h>

TaskBarWindow::TaskBarWindow(QWindow *parent)
    : PlatformWindow(parent, true, KWayland::Client::PlasmaShellSurface::Role::Panel)
    , m_isTabletMode(false)
    , m_isShowingTabletDesktop(false)
    , m_statusMgrInterface(new QDBusInterface("com.kylin.statusmanager.interface",
                           "/", "com.kylin.statusmanager.interface"))
{
    if (m_isWayland) {
        setFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
    } else {
        setFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::BypassWindowManagerHint);
    }

    setModality(Qt::WindowModal);
    setTitle("tablet-taskbar");

    QTimer::singleShot(1, Qt::PreciseTimer, this, [this] {
        QDBusReply<bool> reply = m_statusMgrInterface->call("get_current_tabletmode");
        if (reply.isValid()) {
            m_isTabletMode = reply.value();
        }
        setColor(Qt::transparent);
    });
    initConnections();
    updateGeometry();
}

void TaskBarWindow::moveEvent(QMoveEvent *ev)
{
    if (ev->pos().x() < 100 || ev->pos().y() < 100) {
        if (m_isWayland) {
            kdk::WindowManager::setGeometry(this, m_preGeometry);
        } else {
            setGeometry(m_preGeometry);
        }
    }
}

void TaskBarWindow::show()
{
    QQuickView::show();
    initWindow();
    updateGeometry();
}

void TaskBarWindow::setTabletDesktopWindow(QWindow *window)
{
    m_desktopWindow = window;
}

void TaskBarWindow::updateGeometry()
{
    if (!screen() || !rootObject()) {
        return;
    }

    int x = (screen()->geometry().width() - width()) / 2;
    int y = screen()->geometry().height() - height();
    QRect geometry(x, y, width(), height());
    m_preGeometry = geometry;
    if (m_isWayland) {
        kdk::WindowManager::setGeometry(this, geometry);
    } else {
        setGeometry(geometry);
    }
}

void TaskBarWindow::onActiveChanged()
{
    if (!rootObject()) {
        return;
    }
    if (!isActive()) {
        rootObject()->setState("Hide");
        QTimer::singleShot(200, this, [this] { this->hide(); });
    }
}

void TaskBarWindow::onShowingDesktopChanged(bool showing)
{
    if (!rootObject()) {
        return;
    }
    if (showing) {
        this->hide();
        this->rootObject()->setState("Hide");
        updateGeometry();
    }
}

void TaskBarWindow::onEdgeGestureToggled(QString type, int fingers)
{
    if (!this->rootObject() || m_isShowingTabletDesktop || !m_isTabletMode) {
        return;
    }

    if (type == "Up" && fingers == 1) {
        this->show();
        this->rootObject()->setState("Show");
        updateGeometry();
    }
}

void TaskBarWindow::tabletModeChanged(bool tabletMode)
{
    m_isTabletMode = tabletMode;
    if (!tabletMode) {
        this->hide();
    }
}

void TaskBarWindow::initConnections()
{
    QDBusConnection kwinConn = QDBusConnection::connectToBus(QDBusConnection::SessionBus, "org.ukui.KWin");
    QDBusConnection statusMgrConn = QDBusConnection::connectToBus(QDBusConnection::SessionBus, "com.kylin.statusmanager.interface");

    kwinConn.connect("org.ukui.KWin",
                 "/TouchGestureManager",
                 "org.ukui.KWin.TouchGestureManager",
                 "edgeSwipeGesture",
                 this,
                 SLOT(onEdgeGestureToggled(QString, int)));

    statusMgrConn.connect("com.kylin.statusmanager.interface",
                          "/",
                          "com.kylin.statusmanager.interface",
                          "mode_change_signal",
                          this,
                          SLOT(tabletModeChanged(bool)));

    connect(this, &TaskBarWindow::widthChanged, this, &TaskBarWindow::updateGeometry);
    connect(this, &TaskBarWindow::activeChanged, this, &TaskBarWindow::onActiveChanged);
    connect(KWindowSystem::self(), &KWindowSystem::showingDesktopChanged,
            this, &TaskBarWindow::onShowingDesktopChanged);
    connect(kdk::WindowManager::self(), &kdk::WindowManager::activeWindowChanged, this, [this](const kdk::WindowId& wid) {
        if (!m_desktopWindow) {
            return;
        }
        if (m_isWayland && m_desktopWindow->isActive()) {
            m_isShowingTabletDesktop = true;
        } else if (!m_isWayland && m_desktopWindow->winId() == wid) {
            m_isShowingTabletDesktop = true;
        } else {
            m_isShowingTabletDesktop = false;
        }
    });
}
