#include "cmainwnd.h"

#include <unistd.h>
#include <ukuistylehelper/ukuistylehelper.h>
#include <windowmanager/windowmanager.h>
#include <QShowEvent>
#include <QDir>
#include <KWindowSystem>

#include "global/kaglobal.h"
#include "startuptools.h"
#include "textselect/selection.h"

CMainWnd::CMainWnd(QWidget *parent) : KWidget(parent)
{
    connect(kdk::WindowManager::self(), &kdk::WindowManager::windowAdded, this, [=](const kdk::WindowId& window_id){
        if (getpid() == kdk::WindowManager::getPid(window_id) && m_window_id == 0)
        {
            m_window_id = window_id.toULongLong();
        }
    });
    createAllChildWnd();
    initCtrl();
    initTrayIcon();
    initSolts();
    relayout();
    StartUpTools::getInstance()->initConfig(); // 初始化配置文件

    initScribeWords();

    monitorDesktopFile();
    initSideBarSize();

    initXeventMonitor();

    initPosition();

    initScribeWordsSetting();
}

CMainWnd::~CMainWnd()
{
    if (m_xeventMonitor) {
       m_xeventMonitor->freeXres();
       m_xeventMonitor->quit();
       m_xeventMonitor->wait();
    }
}

void CMainWnd::createAllChildWnd()
{
#define NEW_OBJECT(pObj, TYPE) \
    if (NULL == pObj) { pObj = new TYPE(this); }

    // NEW_OBJECT(m_btnWnd, CPushButtonEx);
    NEW_OBJECT(m_btnBack, QPushButton);
    NEW_OBJECT(m_btnStick, QPushButton);
    connect(m_btnStick, &QPushButton::clicked, this, &CMainWnd::slotToTop);

    NEW_OBJECT(m_msgPane, CMsgPane);
    NEW_OBJECT(m_dbusOperator, KADBusOperator);
    NEW_OBJECT(m_sideBar, SideBarWidget);
    NEW_OBJECT(m_addModelDialog, KASettingDialog);
    NEW_OBJECT(m_btnOccupiedMode, QPushButton);

    return;
}

void CMainWnd::initCtrl()
{
    QDesktopWidget *desktopWidget = QApplication::desktop();
    QRect screenRect = desktopWidget->screenGeometry();

    setAttribute(Qt::WA_StyledBackground);  // 禁止父窗口样式影响子控件样式

    // 按照设计稿设计，窗口按钮大小为 32x32
    // m_btnWnd->setFixedSize(32, 32);
    // m_btnWnd->setIcon(QIcon(QString(":/icon/icon/window.svg")));
    // m_btnWnd->setIconSize(QSize(16, 16));
    // m_btnWnd->setProperty("wndbtn", "true");
    // m_btnWnd->setProperty("useIconHighlightEffect", true);
    // m_btnWnd->setProperty("iconHighlightEffectMode", 1);
    // m_btnWnd->setFlat(true);

    m_btnBack->setFixedSize(32, 32);
    m_btnBack->setIcon(QIcon(QString(":/icon/icon/back.svg")));
    m_btnBack->setIconSize(QSize(16, 16));
    m_btnBack->setProperty("useIconHighlightEffect", true);
    m_btnBack->setProperty("iconHighlightEffectMode", 1);
    m_btnBack->setFlat(true);
    m_btnBack->setVisible(false);

    // 按照设计稿设计，置顶按钮大小为 32x32
    m_btnStick->setFixedSize(32, 32);
    m_btnStick->setProperty("isWindowButton", 0x1);
    m_btnStick->setProperty("useIconHighlightEffect", 0x2);
    m_btnStick->setFlat(true);
    m_btnStick->setIcon(QIcon::fromTheme("ukui-fixed-symbolic"));
    m_btnStick->setToolTip(tr("fixed"));
    m_btnStick->setFocusPolicy(Qt::NoFocus);
    // 固定按钮先隐藏，后续小窗口会用到这个按钮。
    m_btnStick->setVisible(false);

    m_btnOccupiedMode->setFixedSize(32, 32);
    m_btnOccupiedMode->setProperty("isWindowButton", 0x1);
    m_btnOccupiedMode->setProperty("useIconHighlightEffect", 0x2);
    m_btnOccupiedMode->setProperty("windowMode", WINDOW_MODE_NORMAL);
    m_btnOccupiedMode->setFlat(true);
    m_btnOccupiedMode->setIcon(QIcon(QString(":/icon/icon/sideBySideDisplay.svg")));
    m_btnOccupiedMode->setToolTip(tr("Parallel display"));
    m_btnOccupiedMode->setFocusPolicy(Qt::NoFocus);

    QMenu* menuConfig = new QMenu(this);
    windowButtonBar()->menuButton()->setMenu(menuConfig);

    confAction = new QAction(tr("Setting"), this);
    menuConfig->addAction(confAction);

    QAction *act_exit = new QAction(tr("Exit"), this);
    menuConfig->addAction(act_exit);
    connect(act_exit, &QAction::triggered, this, &CMainWnd::onExitActionTriggled);

    this->setObjectName("mainwnd");
    this->setStyleSheet("#mainwnd{background-color:#F5F5F5}");
}

void CMainWnd::initSolts()
{
    connect(confAction, SIGNAL(triggered()), this, SLOT(onConfActionTriggered()));

    connect(m_dbusOperator, &KADBusOperator::sigSetup, [this]{onConfActionTriggered();});
    connect(m_msgPane, &CMsgPane::sigSetup, [this]{onConfActionTriggered();});

    // connect(m_btnWnd, &QPushButton::clicked, this, &CMainWnd::onWndBtnClicked);

    connect(m_btnBack, &QPushButton::clicked, m_msgPane, &CMsgPane::onBackBtnClicked);

    connect(m_msgPane, &CMsgPane::sigUrlChanged, this, &CMainWnd::onPageChanged);

    connect(m_sideBar, SIGNAL(sigCreateButtonClicked()), this, SLOT(onCreateDialog()));

    // 当聊天界面保存了历史会话到文件，则需要通知历史会话界面更新。
    connect(m_msgPane, SIGNAL(sigSaveDialog(QString)), m_sideBar, SLOT(onSaveDialog(QString)));

    // 点击插件的时候需要加载对应插件的历史会话界面。
    connect(m_sideBar, SIGNAL(sigPluginItemClicked(QString)), m_msgPane, SLOT(loadPlugin(QString)));

    connect(m_btnOccupiedMode, &QPushButton::clicked, this, &CMainWnd::onWindowModeButtonClicked);
}

void CMainWnd::monitorDesktopFile()
{
    //监控.desktop文件目录
    m_fileWatcher = new QFileSystemWatcher(this);
    QDir dir(QString(QDir::homePath() + "/.local/share/applications/"));
    if (!dir.exists()) {
        qDebug() << "创建.local应用文件目录";
        dir.mkpath(QString(QDir::homePath() + "/.local/share/applications/"));
    }

    m_fileWatcher->addPaths(QStringList() << QString("/usr/share/applications")
                            << QString(QDir::homePath() + "/.local/share/applications/")
                            << QString("/var/lib/snapd/desktop/applications/")
                            << QString("/var/lib/flatpak/exports/share/applications/"));
    connect(m_fileWatcher, &QFileSystemWatcher::directoryChanged, this, &CMainWnd::onDirectoryChanged);
}

void CMainWnd::onDirectoryChanged()
{
    StartUpTools::getInstance()->initConfig();
}

void CMainWnd::relayout()
{
    QVBoxLayout *layoutRMain = new QVBoxLayout(baseBar());
    layoutRMain->addWidget(m_msgPane);
    layoutRMain->setSpacing(0);
    layoutRMain->setMargin(0);
    layoutRMain->setContentsMargins(0, 0, 0, 0);

    KWindowButtonBar* button_bar = windowButtonBar();
    button_bar->minimumButton()->hide();
    button_bar->maximumButton()->hide();
    ((QHBoxLayout*)button_bar->layout())->insertWidget(1, m_btnOccupiedMode);
    KIconBar *iconbar = iconBar();
    ((QHBoxLayout*)iconbar->layout())->insertWidget(0, m_btnBack);
}


void CMainWnd::initTrayIcon()
{
    // 系统托盘
    m_trayIcon = new QSystemTrayIcon(this);
    m_trayIcon->setToolTip(QString(tr("Ai assistant")));
    m_trayIcon->setIcon(QIcon(":/icon/icon/AI-Writing.svg"));

    connect(m_trayIcon, &QSystemTrayIcon::activated, this, &CMainWnd::onTrayIconActivated);
    m_trayIcon->show();
}

void CMainWnd::initScribeWords()
{
    m_selectwid = new SelectWidget;
    m_selectclip = new Clipboard;
    connect(m_selectclip, &Clipboard::selectWords, m_selectwid, &SelectWidget::showScribeWordsAtCursorPosition);
    connect(m_selectwid, &SelectWidget::sigbuttontext, this, &CMainWnd::handleClicpText);
    connect(m_selectwid, &SelectWidget::signalSendClicpText, this, &CMainWnd::handleClicpText);
    connect(m_selectwid, &SelectWidget::sigHomePageShow, this, [=]() {
        this->activateWindow();
        m_selectwid->hide();
    });
    connect(m_selectwid, &SelectWidget::sigSettingShow, this, [=]() {
        onConfActionTriggered();
        m_selectwid->hide();
    });
    connect(m_selectwid, &SelectWidget::sigDisableScribe, this, [=]() {
        m_selectclip->onScribeWordsDisabled();
        m_selectwid->hide();
        m_addModelDialog->scribeWordsDisabled();
    });
}

void CMainWnd::initScribeWordsSetting()
{
    // 点击是否禁用划词按钮
    connect(m_addModelDialog, &KASettingDialog::sigShowScribeWords, m_selectclip, &Clipboard::onScribeWordsIsabled);
    connect(m_addModelDialog, &KASettingDialog::sigCloseScribeWords, this, [=]() {
        m_selectclip->onScribeWordsDisabled();
        m_selectwid->hide();
        m_addModelDialog->scribeWordsDisabled();
    });
}

void CMainWnd::handleClicpText()
{
    QString buttonText = m_selectwid->getButtonText();
    clipText = m_selectclip->getClipText();
    if(buttonText == tr("Translation") && clipText != ""){
        buttonText =tr("Chinese English Translation");
        m_msgPane->onSendMsg(buttonText,clipText);
    }else if(buttonText != "" && clipText != "")    {
        m_msgPane->onSendMsg(buttonText,clipText);
    }else{
        m_msgPane->onSendMsg("",clipText);
    }
    this->activateWindow();
    m_selectwid->hide();
}

void CMainWnd::onShotCutActionTriggled()
{

}

void CMainWnd::onAboutActionTriggled()
{

}

void CMainWnd::onExitActionTriggled()
{
    // QCoreApplication::quit();
    close();
}


void CMainWnd::onTrayIconActivated(QSystemTrayIcon::ActivationReason reason)
{
    if (isVisible()) {
        hideView();
    } else {
        showView();
        if(! g_gsettings->get("is-nlp-setup").toBool() && !g_gsettings->get("is-vision-setup").toBool()){
            this->onConfActionTriggered();
        }
    }

    return;
}

void CMainWnd::onAppRestarted()
{
    kdk::WindowManager::activateWindow(m_window_id);
    show();
    if(! g_gsettings->get("is-nlp-setup").toBool() && !g_gsettings->get("is-vision-setup").toBool()){
        this->onConfActionTriggered();
    }
}

void CMainWnd::closeEvent(QCloseEvent *e)
{
    e->ignore();
    hide();
}

void CMainWnd::showView()
{
    kdk::WindowManager::activateWindow(m_window_id);
    show();

    if (m_addModelDialog != nullptr && isSettingOpen == true)
    {
        m_addModelDialog->show();
    }

    if (m_isTop)
        QTimer::singleShot(500, [this]{
            kdk::WindowManager::keepWindowAbove(m_window_id);
        });
}

void CMainWnd::hideView()
{
    hide();
    if (m_addModelDialog != nullptr && isSettingOpen == true)
    {
        m_addModelDialog->hide();
    }
}

void CMainWnd::slotToTop()
{
    kdk::WindowManager::keepWindowAbove(m_window_id);

    // 此处获取到的置顶是反的？？？
    m_isTop = !kdk::WindowManager::getwindowInfo(m_window_id).isKeepAbove();
    m_btnStick->setIcon(QIcon::fromTheme(m_isTop ? "ukui-unfixed-symbolic" : "ukui-fixed-symbolic"));
    m_btnStick->setToolTip(m_isTop ? tr("unfixed") : tr("fixed"));
    changeToOccupiedMode();
}

void CMainWnd::onWindowModeButtonClicked()
{
    int windowMode = WINDOW_MODE_NORMAL;
    QVariant value = m_btnOccupiedMode->property("windowMode");
    if (value.isValid() && value.type() == QVariant::Int) {
        windowMode = value.toInt();
    }

    if (windowMode == WINDOW_MODE_NORMAL) {
        changeToOccupiedMode();
        m_btnOccupiedMode->setIcon(QIcon(QString(":/icon/icon/overlayDisplay.svg")));
        m_btnOccupiedMode->setProperty("windowMode", WINDOW_MODE_OCCUPIED);
        m_btnOccupiedMode->setToolTip(tr("Overlay display"));
        return;
    }

    changeToNormalMode();
    m_btnOccupiedMode->setIcon(QIcon(QString(":/icon/icon/sideBySideDisplay.svg")));
    m_btnOccupiedMode->setProperty("windowMode", WINDOW_MODE_NORMAL);
    m_btnOccupiedMode->setToolTip(tr("Parallel display"));

    return;
}

void CMainWnd::onWndBtnClicked()
{
    m_sideBar->show();
    return;
}

void CMainWnd::onPageChanged(const QUrl &url)
{
    if (url == QUrl("qrc:/html/html/index1.html"))
        m_btnBack->setVisible(false);
    else
        m_btnBack->setVisible(true);
}

void CMainWnd::onConfActionTriggered()
{
    m_addModelDialog->show();
    isSettingOpen = true;
}

void CMainWnd::initSideBarSize()
{
    m_sideBar->setFixedSize(this->size());
    return;
}

void CMainWnd::onCreateDialog()
{
    // 先保存当前会话
    m_msgPane->saveDialog();

    // 然后清除当前会话
    m_msgPane->clearDialog();

    // 隐藏历史会话界面
    m_sideBar->hide();

    return;
}

void CMainWnd::initXeventMonitor()
{
    if (!m_xeventMonitor) {
        m_xeventMonitor = new xEventMonitor;
        connect(m_xeventMonitor, SIGNAL(mousePress(int, int)), this, SLOT(onX11GlobalMousePress(int, int)), Qt::QueuedConnection);
    }
}

void CMainWnd::onX11GlobalMousePress(int x, int y)
{
    QRect geoRect = m_selectwid->geometry();
    if (!geoRect.contains(x, y) && m_selectwid->isVisible()) {
        m_selectwid->closeWidgetAndinstructPage(x, y);
    }

    return;
}

void CMainWnd::initPosition()
{
    QRect screenRect = QGuiApplication::primaryScreen()->availableGeometry();
    setGeometry(screenRect.right() - 402, screenRect.top(), 402, screenRect.height());

    return;
}

void CMainWnd::changeToOccupiedMode()
{
    KWindowSystem::setExtendedStrut(winId(),
                                    /* Left   */  0, 0, 0,
                                    /* Right  */  width(), geometry().top(), geometry().bottom(),
                                    /* Top    */  0, 0, 0,
                                    /* Bottom */  0, 0, 0
                                    );

    return;
}

void CMainWnd::changeToNormalMode()
{
    KWindowSystem::setExtendedStrut(winId(),
                                    /* Left   */  0, 0, 0,
                                    /* Right  */  0, 0, 0,
                                    /* Top    */  0, 0, 0,
                                    /* Bottom */  0, 0, 0
                                    );

    return;
}
