#include "multitaskviewmanager.h"

#include <KF5/KGlobalAccel/KGlobalAccel>
#include <KF5/KWindowSystem/KWindowSystem>

#include <ukuisdk/kylin-com4c.h>
#include <ukuisdk/kylin-com4cxx.h>

#include <QAction>
#include <QApplication>
#include <QQmlContext>
#include <QtDBus>

#include "desktopbackground.h"
#include "icontheme.h"

namespace MultitaskView {

MultitaskViewManager::MultitaskViewManager()
{
    setProjectType();

    setQmlUrl();

    registerQmlTypes();

    registerShortcut();

    initDBusService();
}

MultitaskViewManager::~MultitaskViewManager()
{
    dbusService_.reset();

    close();
}

void MultitaskViewManager::grabbedKeyboardEvent(QKeyEvent *e)
{
    QApplication::sendEvent(view_->rootObject(), e);
}

void MultitaskViewManager::open()
{
    if (isOpen)
    {
        return;
    }

    //可旋转的机器，多任务视图打开的时候，禁用旋转
    if(projectType_ == MultitaskViewManager::TABLET && model_->isTabletMode())
    {
        if(getRotationModeStatus())
        {
            setRotationModeStatus(!isOpenRotationMode);
        }
    }

    initView();

    KWin::effects->grabKeyboard(this);

    isOpen = true;
}

bool MultitaskViewManager::getRotationModeStatus()
{
    QDBusMessage message = QDBusMessage::createMethodCall("com.kylin.statusmanager.interface",
                                                          "/",
                                                          "com.kylin.statusmanager.interface",
                                                          "get_auto_rotation");

    QDBusMessage response = QDBusConnection::sessionBus().call(message);

    if (response.type() == QDBusMessage::ReplyMessage)
    {
        isOpenRotationMode = response.arguments().takeFirst().toBool();
    }
    else
    {
        // invalid response, keep default.
    }
    return isOpenRotationMode;
}

void MultitaskViewManager::setRotationModeStatus(bool rotationModeStatus)
{
    QDBusInterface iface("com.kylin.statusmanager.interface",
                         "/",
                         "com.kylin.statusmanager.interface");

    if (!iface.isValid()) {
        qDebug() << QDBusConnection::sessionBus().lastError().message();
    }

    QDBusReply<void> reply = iface.call("set_auto_rotation",rotationModeStatus,"","");

    if (reply.isValid()) {
        qDebug() << "set Rotation mode success";
        return;
    }

    qDebug() << "set Rotation mode failed" << reply.error();
}

void MultitaskViewManager::close()
{
    if (!isOpen)
    {
        return;
    }

    //可旋转的机器，多任务视图打开前 是打开了旋转的 那么关闭多任务视图的同时  打开旋转
    if(projectType_ == MultitaskViewManager::TABLET && model_->isTabletMode())
    {
        if(isOpenRotationMode)
        {
            setRotationModeStatus(isOpenRotationMode);
        }
    }

    KWin::effects->ungrabKeyboard();

    destroyView();

    isOpen = false;
}

void MultitaskViewManager::showDesktop(bool show)
{
    KWin::effects->setShowingDesktop(show);
}

void MultitaskViewManager::initModel()
{
    model_.reset(new MultitaskViewModel());
}

void MultitaskViewManager::setProjectType()
{
    if ("V10SP1-edu" == getProjectCodeName()          ||
        "V10SPX-mavis-edu" == getProjectCodeName()    ||
        "3" == getOSReleaseValue("PRODUCT_FEATURES")  ||
        "2" == getOSReleaseValue("PRODUCT_FEATURES"))
    {
        projectType_ = MultitaskViewManager::TABLET;
    }
}

void MultitaskViewManager::setQmlUrl()
{
    if (projectType_ == MultitaskViewManager::TABLET)
    {
        qmlUrl_ = QUrl("qrc:/qml/TabletViewMain.qml");
    }
    else if (projectType_ == MultitaskViewManager::PC)
    {
        qmlUrl_ = QUrl("qrc:/qml/multitaskview.qml");
    }
}

void MultitaskViewManager::registerQmlTypes()
{
    qmlRegisterType<DesktopBackground>("org.kde.kwin", 3, 0, "DesktopBackground");
    qmlRegisterType<IconTheme>("IconTheme", 1, 0, "IconTheme");
}

void MultitaskViewManager::registerShortcut()
{
    auto* action = new QAction(this);
    action->setObjectName("ShowMultitaskView");
    action->setText("Show Multitask View");

    QKeySequence keySeq(Qt::META + Qt::Key_Tab);
    KGlobalAccel::self()->setDefaultShortcut(action, QList<QKeySequence>() << keySeq);
    KGlobalAccel::self()->setShortcut(action, QList<QKeySequence>() << keySeq);

    QObject::connect(action, &QAction::triggered, this, &MultitaskViewManager::open);
}

void MultitaskViewManager::initDBusService()
{
    dbusService_.reset(new DBusService(this));
}

void MultitaskViewManager::initView()
{
    view_.reset(new QQuickView());

    view_->setFlag(Qt::WindowType::BypassWindowManagerHint);

    KWindowSystem::setType(view_->winId(), NET::Dock);

    qDebug() << "[DEBUG]: multitask view uses " << view_->sceneGraphBackend();
    if (view_->rendererInterface()->graphicsApi() < 2)
    {
        useOpenGL_ = false;
    }

    initModel();

    view_->rootContext()->setContextProperty("multitaskViewManager", this);
    view_->rootContext()->setContextProperty("multitaskViewModel", model_.get());

    view_->setSource(qmlUrl_);

    // 必须在加载了QML之后才能设置view_对象的大小
    view_->setGeometry(KWin::effects->virtualScreenGeometry());

    connectSignals();

    view_->show();

    view_->requestActivate();
}

void MultitaskViewManager::destroyView()
{
    if (view_ == nullptr)
    {
        return;
    }

    if (view_->isVisible())
    {
        view_->hide();
    }

    // 1. 由于可以在QML中通过JS调用到close函数，
    // 因此，不能直接销毁view_对象；必须延迟
    // 销毁该对象。
    // 2. model_对象可以立刻销毁。但是，为了对称
    // 和简化逻辑，需要保证view_对象和model_对象的
    // 互相依赖的关系。因此，同时延迟销毁model_对象。
    // 3. MultitaskViewManager的析构函数需要确保
    // view_对象和model_对象完成销毁。为了简化逻辑，
    // MultitaskViewManager的析构函数选择直接调用
    // destroyView函数，即采用了延迟销毁的做法。
    view_.release()->deleteLater();

    model_.release()->deleteLater();
}

void MultitaskViewManager::connectSignals()
{
    const auto* model = model_.get();
    const auto* rootObject = view_->rootObject();
    connect(model, SIGNAL(appWindowCreated(int)),
            rootObject, SIGNAL(qmlAppWindowCreated(int)));
    connect(model, SIGNAL(appWindowActivated()),
            rootObject, SIGNAL(qmlAppWindowActivated()));
    connect(model, SIGNAL(appWindowRemoved(int)),
            rootObject, SIGNAL(qmlAppWindowRemoved(int)));
    if (projectType_ == MultitaskViewManager::PC)
    {
        connect(model, SIGNAL(appWindowDesktopChanged(int, int, int)),
                rootObject, SIGNAL(qmlAppWindowDesktopChanged(int, int, int)));
        connect(model, SIGNAL(desktopRemoved(int)),
                rootObject, SIGNAL(qmlDesktopRemoved(int)));
        connect(model, SIGNAL(desktopAppended(int)),
                rootObject, SIGNAL(qmlDesktopAppended(int)));
        connect(model, SIGNAL(desktopMoved(int, int)),
                rootObject, SIGNAL(qmlDesktopMoved(int, int)));
        connect(model, SIGNAL(currentDesktopChanged(int, int)),
                rootObject, SIGNAL(qmlCurrentDesktopChanged(int, int)));
        connect(model, SIGNAL(screenCountChanged(int, int)),
                rootObject, SIGNAL(qmlScreenCountChanged(int, int)));
        connect(model, SIGNAL(screenSizeChanged()),
                rootObject, SIGNAL(qmlScreenSizeChanged()));
    }
    else if (projectType_ == MultitaskViewManager::TABLET)
    {
        connect(model, SIGNAL(tabletModeChanged(bool)),
                rootObject, SIGNAL(qmlDeviceModeChanged(bool)));
        connect(model, SIGNAL(rotationModeChanged(QString)),
                rootObject, SIGNAL(qmlOrientationChanged(QString)));
    }
}

QString MultitaskViewManager::getProjectCodeName()
{
    QString projectCodeName = KDKGetPrjCodeName().c_str();

    return projectCodeName;
}

QString MultitaskViewManager::getOSReleaseValue(const QString key)
{
    int value_length = 256;

    char os_release_value[value_length];

    if (kdk_get_osrelease(key.toStdString().c_str(), os_release_value, value_length) > 0)
    {
        return os_release_value;
    }

    return "";
}

} // namespace MultitaskView
