/*
 * Copyright (C) 2023, KylinSoft Co., Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 *
**/
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "interface/ukcccommon.h"
using namespace ukcc;
#include "imageutil.h"
#include "ukccabout.h"

#include <QLabel>
#include <QLocale>
#include <QPushButton>
#include <QButtonGroup>
#include <QHBoxLayout>
#include <QPluginLoader>
#include <QPainter>
#include <QPainterPath>
#include <QProcess>
#include <QDebug>
#include <QMessageBox>
#include <QGSettings>
#include <QMenu>
#include <QShortcut>
#include <QMouseEvent>
#include <QScrollBar>
#include <KWindowSystem>
#include "component/leftwidgetitem.h"
#include "iconbutton.h"
#include "lightlabel.h"
#include "../../shell/customstyle.h"
#include "utils/modulefactory.h"
#include "utils/functionselect.h"

#define THEME_QT_SCHEMA "org.ukui.style"

#ifdef WITHKYSEC
#include <kysec/libkysec.h>
#include <kysec/status.h>
#endif

const QByteArray kVinoSchemas    = "org.gnome.Vino";

#define KYLIN_USER_GUIDE_PATH              "/"
#define KYLIN_USER_GUIDE_SERVICE           "com.kylinUserGuide.hotel"
#define KYLIN_USER_GUIDE_INTERFACE         "com.guide.hotel"

/* qt会将glib里的signals成员识别为宏，所以取消该宏
 * 后面如果用到signals时，使用Q_SIGNALS代替即可
 **/
#ifdef signals
#undef signals
#endif

extern "C" {
#include <glib.h>
#include <gio/gio.h>
}

const int dbWitdth = 50;
extern void qt_blurImage(QImage &blurImage, qreal radius, bool quality, int transposed);

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    m_searchWidget(nullptr)
{
    qApp->installEventFilter(this);
    qApp->setStyle(new InternalStyle("ukui"));
    is_ExitPower = isExitsPower();
    pluginPathList = FunctionSelect::listExistsCustomNoticePath(PLUGINS_PATH);
    if (UkccCommon::isOpenkylin()) {
        connect(WindowManager::self(),&WindowManager::windowAdded,this,[=](const WindowId& windowId){
            if (getpid() == WindowManager::getPid(windowId)) {
                m_listWinIds.append(windowId);
            }
        });
        connect(WindowManager::self(),&WindowManager::windowRemoved,this,[=](const WindowId& windowId){
            if (m_listWinIds.contains(windowId)) {
                m_listWinIds.removeOne(windowId);
            }
        });
    }
    isLoad = false;
    loadWidget = false;
    preInit();
}

MainWindow::~MainWindow()
{
    //执行插件的析构函数
    ModulesFactory::pluginDelete();
    qInfo()<<"~exit ukui-control-center";
    delete ui;
    ui = nullptr;
}

void MainWindow::preInit() {
    m_searchWidget = new SearchWidget(this);
    m_searchWidget->setContextMenuPolicy(Qt::NoContextMenu);
    connect(m_searchWidget, &SearchWidget::notifyModuleSearch, this, &MainWindow::switchPage);
    m_searchWidget->setFixedWidth(240);
    m_ModuleMap = UkccCommon::getModuleHideStatus();
}

void MainWindow::bootOptionsFilter(QString opt, bool firstIn) {
    PluginInfo* pluginInfo = ModulesFactory::getPluginInfoByName(opt);
    if (pluginInfo == nullptr) {
        //避免无限循环的风险
        if (UkccCommon::isTablet()) {
            if (firstIn) {
                bootOptionsFilter("userinfointel", false);
            }
            backBtn->hide();
        }
        return ;
    }
    QString pluginName = pluginInfo->nameString;
    QString moduleName = ModulesFactory::getModuleNamebyName(pluginName);
    QObject* pluginObj = ModulesFactory::getPluginObjectByName(pluginInfo->namei18nString);
    if (pluginObj != nullptr) {
        if (m_ModuleMap.isEmpty()) {
            //开始跳转
            functionBtnClicked(pluginObj);
            return ;
        } else {
            qDebug() << "module:" << pluginName.toLower() << ";superordinate:" << moduleName;
            // 若跳转节点或跳转节点父节点不存在直接跳转，不受管控文件控制，若存在，则根据管控文件判断是否被禁用
            if (!m_ModuleMap.contains(pluginName.toLower()) || !m_ModuleMap.contains(moduleName)
                 || (m_ModuleMap[pluginName.toLower()].toBool() && m_ModuleMap[moduleName].toBool())) {
                //开始跳转
                functionBtnClicked(pluginObj);
                return ;
            }
        }

        QMessageBox::information(this, tr("Warnning"), tr("This function has been controlled"));
    }
}

bool MainWindow::eventFilter(QObject *watched, QEvent *event)
{
    if (watched == scrollArea) {
        if (!UkccCommon::isTablet()) {
            if (event->type() == QEvent::Enter) {
                scrollArea->verticalScrollBar()->setVisible(true);
            } else if (event->type() == QEvent::Leave) {
                scrollArea->verticalScrollBar()->setVisible(false);
            }
        }
    } else if (watched == this) {
        if (event->type() == QEvent::WindowStateChange) {
            if (this->windowState() == Qt::WindowMaximized) {
                maxBtn->setIcon(QIcon::fromTheme("window-restore-symbolic"));
                maxBtn->setToolTip(tr("Restore"));
            } else {
                maxBtn->setIcon(QIcon::fromTheme("window-maximize-symbolic"));
                maxBtn->setToolTip(tr("Maximize"));
            }
        } else if (event->type() == QEvent::MouseButtonDblClick) {
            QMouseEvent * mouseEvent = static_cast<QMouseEvent *>(event);
            if (mouseEvent->button() == Qt::LeftButton ){
                bool res = dblOnEdge(dynamic_cast<QMouseEvent*>(event));
                if (res) {
                    if (this->windowState() == Qt::WindowMaximized) {
                        this->showNormal();
                    } else {
                        this->showMaximized();
                    }
                }
            }
        }
    } else if (watched == homepageWidget) {
        if (event->type() == QEvent::Paint) {
            QTimer::singleShot(1, this, [=]() {
                if (!UkccCommon::isTablet()) {
                    m_searchWidget->setFixedWidth(240 > mOptionBtn->x() - titleLabel->x() - titleLabel->width() ? (mOptionBtn->x() - m_searchWidget->x() - 16) : 240);
                }
            });
        }
    }
    return QObject::eventFilter(watched, event);
}

void MainWindow::keyReleaseEvent(QKeyEvent *event)
{
    mFirstKey = 0;
}

void MainWindow::keyPressEvent(QKeyEvent *event)
{
    if (event->key() == Qt::Key_F1) {
        if (!event->isAutoRepeat()) //避免重复触发该事件
            onF1ButtonClicked();
    }

    if (mFirstKey == 0 && event->key() == Qt::Key_Control) {
        mFirstKey = Qt::Key_Control;
    } else if (mFirstKey == Qt::Key_Control && event->key() == Qt::Key_E) {
#ifdef Nile
        m_searchWidget->setFocus();
#endif
    } else {
        mFirstKey = 0;
    }
}

void MainWindow::loadAllModules() {
    // 一级菜单配置加载
    QtConcurrent::run([=]{
        ModulesFactory::loadConfig();
    });

    //加载插件
    loadPlugins();
}

void MainWindow::initPageWidget() {
    if (loadWidget) {
        return;
    }
    loadWidget = true;
    initUI();
    hideComponent();

    //加载首页Widget
    homepageWidget = new HomePageWidget(this, vecGsettins);
    homepageWidget->installEventFilter(this);
    ui->stackedWidget->addWidget(homepageWidget);
    ui->stackedWidget->setFocusPolicy(Qt::ClickFocus);

    //加载左侧边栏一级菜单
    initLeftsideBar();

    //加载功能页Widget
    modulepageWidget = new ModulePageWidget(this);
    ui->stackedWidget->addWidget(modulepageWidget);

    connect(ui->stackedWidget, &QStackedWidget::currentChanged, this, [=] (int id){
        if (id == 0) {
            modulepageWidget->mCurrentPluName =  "";
        }
    });
    connect(modulepageWidget, &ModulePageWidget::hScrollBarHide, this, [=]() {
        m_searchWidget->setFixedWidth(240);
    });
    connect(modulepageWidget, &ModulePageWidget::hScrollBarShow, this, [=]() {
        QTimer::singleShot(1, this, [=]() {
            if (!UkccCommon::isTablet()) {
                if (m_searchWidget->width() > backBtn->x() - mOptionBtn->x()) {
                    m_searchWidget->setFixedWidth(mOptionBtn->x() - backBtn->x() - mOptionBtn->width() - 16);
                }
            }
        });
    });
}

void MainWindow::initUI() {
    ui->setupUi(this);
    QRect screenSize = UkccCommon::sizeOnCursor();
    this->setMinimumSize(978, 630);
    if (screenSize.width() > 1440)
        this->resize(1160,720);

    const QByteArray id("org.ukui.style");
    m_fontSetting = new QGSettings(id, QByteArray(), this);
    connect(m_fontSetting, &QGSettings::changed, this, [=](QString key) {
        if ("systemFont" == key || "systemFontSize" == key) {
            QFont font = this->font();
            int width = font.pointSize();
            for (auto widget : qApp->allWidgets()) {
                QString className(widget->metaObject()->className());
                if (widget->objectName() == "timeClockLable") {
                    QFont fontTime;
                    fontTime.setWeight(QFont::Medium);
                    fontTime.setBold(true);
                    if (QLocale::system().amText() == "སྔ་དྲོ་") {
                        fontTime.setPixelSize(m_fontSetting->get("systemFontSize").toInt() * 20 / 11);
                    } else {
                        fontTime.setPixelSize(font.pointSize() * 28 / 11);
                    }
                    widget->setFont(fontTime);
                } else if(widget->objectName() == "DateTime_Info") {
                    QFont fontTitle;
                    fontTitle.setPixelSize(font.pointSize() * 18 / 11);
                    fontTitle.setWeight(QFont::Medium);
                    widget->setFont(fontTitle);
                } else {
                    font.setWeight(QFont::Normal);
                    widget->setFont(font);
                }
            }
        }
    });

    initTileBar();
    initStyleSheet();

    connect(minBtn, SIGNAL(clicked()), this, SLOT(showMinimized()));
    connect(maxBtn, &QPushButton::clicked, this, [=] {
        if (isMaximized()) {
            showNormal();
            maxBtn->setIcon(QIcon::fromTheme("window-maximize-symbolic"));
        } else {
            showMaximized();
            maxBtn->setIcon(QIcon::fromTheme("window-restore-symbolic"));
        }
    });
    connect(closeBtn, &QPushButton::clicked, this, [=] {
        qApp->quit();
    });

    connect(ui->stackedWidget, &QStackedWidget::currentChanged, this, [=](int index){
        ui->centralWidget->setVisible(false);    //避免出现明显的卡顿现象，在选择进入屏保界面之后这个问题比较明显，这种做法只是优化
        if (index){ //次页部分组件样式
            titleLabel->setHidden(true);
            mTitleIcon->setHidden(true);
              ui->leftsidebarWidget->setVisible(true);
            //左上角显示字符/返回按钮
            if (!is_tabletmode) {
                backBtn->setVisible(true);
            }
            ui->stackedWidget->status = false;
            ui->titleWidget->status = false;
        } else { //首页部分组件样式
            //左侧边栏显示/不显示
            ui->leftsidebarWidget->setHidden(true);
            titleLabel->setVisible(true);
            mTitleIcon->setVisible(true);
            //左上角显示字符/返回按钮
            backBtn->setHidden(true);
            if (modulepageWidget) {
                modulepageWidget->pluginLeave();
            }
            ui->stackedWidget->status = true;
            ui->titleWidget->status = true;
        }
        ui->centralWidget->setVisible(true);
    });

    //top left return button
    connect(backBtn, &QPushButton::clicked, this, [=]{
        ui->stackedWidget->setCurrentIndex(0);
        UkccCommon::buriedSettings(backBtn->objectName(), nullptr, QString("clicked"));
    });

    // 快捷参数
    if (QApplication::arguments().length() > 2) {
        if (QApplication::arguments().at(1) == "-p") {
            QString fileFullName = "";
            QString fileName = QApplication::arguments().at(2);
            if (!fileName.startsWith("/")) { //非绝对路径
                char *path = get_current_dir_name();
                QString currentPath = QString(path);
                if (!currentPath.endsWith("/")) {
                    currentPath = currentPath + "/";
                }
                fileFullName = currentPath + fileName;
                g_free(path);
            } else {
                fileFullName = fileName;
            }
            loadSpecifiedPlugin(fileFullName);
        } else if (QApplication::arguments().at(1) == "-m") {
            QTimer::singleShot(2, this, [=](){  //延时保证菜单栏选中插件居中，控件未画出来，无法准确居中
                bootOptionsFilter(QApplication::arguments().at(2));
            });
        }
    }

    //监听平板模式切换
    m_statusSessionDbus = new QDBusInterface("com.kylin.statusmanager.interface",
                                              "/",
                                              "com.kylin.statusmanager.interface",
                                              QDBusConnection::sessionBus(),this);
    if (m_statusSessionDbus->isValid()) {
        QDBusReply<bool> tabletmode = m_statusSessionDbus->call("get_current_tabletmode");
        is_tabletmode = tabletmode;
        mainWindow_statusDbusSlot(is_tabletmode);
        connect(m_statusSessionDbus, SIGNAL(mode_change_signal(bool)), this, SLOT(mainWindow_statusDbusSlot(bool)));

    } else {
        qDebug() << "Create statusmanager Interface Failed When : " << QDBusConnection::systemBus().lastError();
    }
}

void MainWindow::initTileBar() {

    mLogoSetLabel  = new QLabel(this);
    QLabel  *textSetLable  = new QLabel(this);
    ui->leftTopWidget->layout()->addWidget(mLogoSetLabel);
    ui->leftTopWidget->layout()->addWidget(textSetLable);
    mLogoSetLabel->setFixedSize(24,24);
    mLogoSetLabel->setPixmap(QPixmap::fromImage(QIcon::fromTheme("ukui-control-center").pixmap(24,24).toImage()));
    const QByteArray id(THEME_QT_SCHEMA);
    QGSettings *mQtSettings = new QGSettings(id, QByteArray(), this);

    textSetLable->setText(tr("Settings"));
    textSetLable->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);

    titleLayout = new QHBoxLayout(ui->titleWidget);
    ui->titleWidget->setLayout(titleLayout);
    ui->titleWidget->setObjectName("titleWidget");
    titleLayout->setContentsMargins(8, 2, 4, 2);
    titleLayout->setSpacing(0);
    titleLayout->addWidget(m_searchWidget,Qt::AlignCenter);

    backBtn     = new QPushButton(this);
    backBtn->setObjectName("go-home");
    backBtn->setToolTip(tr("Back home"));
    mOptionBtn  = new QToolButton(this);
    minBtn      = new QPushButton(this);
    maxBtn      = new QPushButton(this);
    closeBtn    = new QPushButton(this);
    mTitleIcon  = new QLabel(this);
    titleLabel  = new QLabel(tr("Settings"), this);

    backBtn->setFixedSize(36, 36);
    mOptionBtn->setFixedSize(30, 30);
    if (UkccCommon::isTablet()) {
        minBtn->setFixedSize(48, 48);
        maxBtn->setFixedSize(48, 48);
        closeBtn->setFixedSize(48, 48);
        ui->titleWidget->setFixedHeight(48);
        titleLayout->setContentsMargins(8, 0, 0, 0);
        mOptionBtn->hide();
    } else {
        minBtn->setFixedSize(30, 30);
        maxBtn->setFixedSize(30, 30);
        closeBtn->setFixedSize(30, 30);
        mOptionBtn->show();
    }

    mTitleIcon->setFixedSize(24, 24);

    mOptionBtn->setToolTip(tr("Option"));
    minBtn->setToolTip(tr("Minimize"));
    maxBtn->setToolTip(tr("Maximize"));
    closeBtn->setToolTip(tr("Close"));
    m_titleIcon = QIcon::fromTheme("ukui-control-center");
    mTitleIcon->setPixmap(m_titleIcon.pixmap(m_titleIcon.actualSize(QSize(24, 24))));

    connect(mQtSettings, &QGSettings::changed, this, [=](QString key) {
        if (key == "iconThemeName") {
            mLogoSetLabel->setPixmap(QPixmap::fromImage(QIcon::fromTheme("ukui-control-center").pixmap(24,24).toImage()));
            mTitleIcon->setPixmap(QPixmap::fromImage(QIcon::fromTheme("ukui-control-center").pixmap(24,24).toImage()));
        }
        if (key == "styleName") {
            qApp->setStyle(new InternalStyle("ukui"));
        }
    });

    titleLayout->addWidget(mTitleIcon);
    titleLayout->addSpacing(8);
    titleLayout->addWidget(titleLabel);
    titleLayout->addWidget(backBtn);
    titleLayout->addStretch();
    titleLayout->addWidget(m_searchWidget);
    titleLayout->addStretch();
    titleLayout->addWidget(mOptionBtn);
    titleLayout->addSpacing(4);
    titleLayout->addWidget(minBtn);
    titleLayout->addSpacing(4);
    titleLayout->addWidget(maxBtn);
    titleLayout->addSpacing(4);
    titleLayout->addWidget(closeBtn);

    initUkccAbout();
}

void MainWindow::mainWindow_statusDbusSlot(bool tablet_mode)
{
    is_tabletmode =  tablet_mode;
    if (tablet_mode) {

        ui->leftTopWidget->layout()->setContentsMargins(16, 0, 0, 0);
        ui->leftTopWidget->setFixedHeight(64);
        ui->titleWidget->setFixedHeight(64);
        mLogoSetLabel->setFixedSize(32,32);
        mLogoSetLabel->setPixmap(QPixmap::fromImage(QIcon::fromTheme("ukui-control-center").pixmap(32,32).toImage()));

        mTitleIcon->setFixedSize(32, 32);
        mTitleIcon->setPixmap(m_titleIcon.pixmap(m_titleIcon.actualSize(QSize(32, 32))));

        titleLayout->setContentsMargins(16, 0, 8, 0);

        if (ui->stackedWidget->currentIndex() == -1 || ui->stackedWidget->currentIndex() == 0) {
            this->bootOptionsFilter("userinfo", true);
        }
        backBtn->hide();

        mOptionBtn->setFixedSize(48, 48);
        minBtn->setFixedSize(48, 48);
        maxBtn->hide();
        closeBtn->setFixedSize(48, 48);

        m_searchWidget->setFixedHeight(40);
    } else {
        ui->leftTopWidget->layout()->setContentsMargins(8, 0, 0, 0);
        ui->leftTopWidget->setFixedHeight(40);
        ui->titleWidget->setFixedHeight(40);
        mLogoSetLabel->setFixedSize(24,24);
        mLogoSetLabel->setPixmap(QPixmap::fromImage(QIcon::fromTheme("ukui-control-center").pixmap(24,24).toImage()));

        mTitleIcon->setFixedSize(24, 24);
        mTitleIcon->setPixmap(m_titleIcon.pixmap(m_titleIcon.actualSize(QSize(24, 24))));

        titleLayout->setContentsMargins(8, 2, 5, 2);
        if (ui->stackedWidget->currentIndex() == 1) {
            backBtn->show();
        }

        mOptionBtn->setFixedSize(30, 30);
        minBtn->setFixedSize(30, 30);
        maxBtn->show();
        closeBtn->setFixedSize(30, 30);

        m_searchWidget->setFixedHeight(36);
    }
    emit tabletModeChanged(tablet_mode);
    qApp->setStyle(new InternalStyle("ukui"));
}

void MainWindow::onF1ButtonClicked() {
    QString pluName = "ukui-control-center";
    if (!modulepageWidget->mCurrentPluName.isEmpty()) {
        pluName = QString("%1%2%3").arg(pluName).arg("/").arg(modulepageWidget->mCurrentPluName);
    }
    qDebug()<<pluName;
    showGuide(pluName);
}

void MainWindow::initUkccAbout() {
    mOptionBtn->setPopupMode(QToolButton::InstantPopup);
    QMenu* ukccMain = new QMenu(this);
    ukccMain->setObjectName("mainMenu");
    mOptionBtn->setMenu(ukccMain);

    QAction* ukccHelp = new QAction(tr("Help"),this);
    ukccMain->addAction(ukccHelp);
    QAction* ukccAbout = new QAction(tr("About"),this);
    ukccMain->addAction(ukccAbout);
    QAction* ukccExit = new QAction(tr("Exit"),this);
    ukccMain->addAction(ukccExit);

    connect(ukccExit, SIGNAL(triggered()), this, SLOT(close()));

    connect(ukccAbout, &QAction::triggered, this, [=] {
        KAboutDialog *ukcc = new KAboutDialog(this);
        ukcc->setAppIcon(QIcon::fromTheme("ukui-control-center"));
        ukcc->setAppName(tr("Settings"));
        ukcc->setAppVersion(tr("Version: ") + UkccCommon::getUkccVersion());
        ukcc->setAppSupport(UkccCommon::isOpenkylin() ? "" : ukcc->appSupport());
        ukcc->exec();
    });

     connect(ukccHelp, &QAction::triggered, this, &MainWindow::onF1ButtonClicked);
}
void MainWindow::setBtnLayout(QPushButton * &pBtn) {
    QLabel * imgLabel = new QLabel(pBtn);
    QSizePolicy imgLabelPolicy = imgLabel->sizePolicy();
    imgLabelPolicy.setHorizontalPolicy(QSizePolicy::Fixed);
    imgLabelPolicy.setVerticalPolicy(QSizePolicy::Fixed);
    imgLabel->setSizePolicy(imgLabelPolicy);
    imgLabel->setScaledContents(true);

    QVBoxLayout * baseVerLayout = new QVBoxLayout(pBtn);

    QHBoxLayout * contentHorLayout = new QHBoxLayout();
    contentHorLayout->addStretch();
    contentHorLayout->addWidget(imgLabel);
    contentHorLayout->addStretch();

    baseVerLayout->addStretch();
    baseVerLayout->addLayout(contentHorLayout);
    baseVerLayout->addStretch();

    pBtn->setLayout(baseVerLayout);
}

void MainWindow::loadPlugins()
{
    if (isLoad) {
        return;
    }
    isLoad = true;
    bool installed = (QCoreApplication::applicationDirPath() == QDir(("/usr/bin")).canonicalPath());
    if (installed) {
        pluginsDir = QDir(PLUGIN_INSTALL_DIRS);
    } else {
        pluginsDir = QDir(qApp->applicationDirPath() + "/plugins");
    }
    loadUpdatePlugins();

    foreach (QString fileName, pluginsDir.entryList(QDir::Files)) {
        if (!m_updatePlugins.contains(fileName)) {
            determinePlugin(fileName, pluginsDir);
        }
    }
    m_searchWidget->setLanguage(QLocale::system().name());
}

void MainWindow::loadUpdatePlugins()
{
    updatePluginDir = QDir(PLUGIN_INSTALL_UPDATE);
    foreach (QString fileName, updatePluginDir.entryList(QDir::Files)) {
        m_updatePlugins.append(fileName);
        determinePlugin(fileName, updatePluginDir);
    }
}

void MainWindow::determinePlugin(const QString &fileName, const QDir &dir)
{
    QString pluginPath = dir.absoluteFilePath(fileName);
    //三权分立开启
#ifdef WITHKYSEC
    if (!kysec_is_disabled() && kysec_get_3adm_status() && (getuid() || geteuid())){
        //时间和日期 | 用户帐户 | 电源管理 |网络连接 |网络代理
        if (fileName.contains("datetime") || fileName.contains("userinfo") || fileName.contains("power") || \
                fileName.contains("netconnect") || fileName.contains("proxy") || fileName.contains("update") || \
                fileName.contains("upgrade") || fileName.contains("backup") || fileName.contains("vino") ||
                fileName.contains("printer") || fileName.contains("bluetooth", Qt::CaseInsensitive) || fileName.contains("mobilehotspot", Qt::CaseInsensitive) ||
                fileName.contains("vpn") || fileName.contains("autoboot") || fileName.contains("wlanconnect") ||
                fileName.contains("projection") || fileName.contains("area"))
            return;
    }
#endif
    qDebug() << "Scan Plugin: " << fileName;
    if (!fileName.endsWith(".so") ||
            ("libpower.so" == fileName && !is_ExitPower)) {
        return;
    }

    QPluginLoader loader(pluginPath);
    QObject * plugin = loader.instance();
    if (plugin) {
        QtConcurrent::run([=]{
        CommonInterface * pluginInstance = qobject_cast<CommonInterface *>(plugin);
        // 插件是否启用
        if (!pluginInstance || !pluginInstance->isEnable() || !fileName.endsWith("so")) {
            return;
        }

        qDebug() << "Load Plugin :" << pluginInstance->plugini18nName();
        QGSettings *pluginSettings = setGsettingsPath(pluginPathList, pluginInstance->name());
        vecGsettins.insert(pluginInstance->name(), pluginSettings);

        ModulesFactory::loadPluginInfo(plugin);
        if (pluginInstance->isEnable() && pluginSettings->get(SHOW_KEY).toBool() &&
                (!m_ModuleMap.contains(pluginInstance->name().toLower()) ||
                 m_ModuleMap[pluginInstance->name().toLower()].toBool())) {
            m_searchWidget->addModulesName(pluginInstance->name(), pluginInstance->plugini18nName(), pluginInstance->translationPath());
        }
        connect(pluginSettings, &QGSettings::changed,[=](QString key){
            if (key == SHOW_KEY) {
                m_searchWidget->hiddenSearchItem(QLocale::system().name() == "zh_CN" ? pluginInstance->plugini18nName() : pluginInstance->name(), pluginSettings->get(SHOW_KEY).toBool());
            } else {
                m_searchWidget->hiddenSearchItem(QLocale::system().name() == "zh_CN" ? pluginInstance->plugini18nName() : pluginInstance->name(), pluginSettings->get(SHOW_KEY).toBool());
            }
        });
        });
    } else {
        //如果加载错误且文件后缀为so，输出错误
        if (fileName.endsWith(".so"))
            qDebug() << fileName << "Load Failed: " << loader.errorString() << "\n";
    }
}

void MainWindow::loadSpecifiedPlugin(QString pluginFullName)
{
    QPluginLoader loader(pluginFullName);
    QObject *plugin = loader.instance();
    if (plugin) {
        CommonInterface * pluginInstance = qobject_cast<CommonInterface *>(plugin);
        // 插件是否启用
        if (!pluginInstance || !pluginInstance->isEnable() || !pluginFullName.endsWith("so")) {
            qDebug()<<"plugin " <<pluginFullName<<" unavailable.";
            plugin->deleteLater();
            return;
        }
        Q_EMIT specifiedPluginLoaded(pluginInstance);
    } else {
        //如果加载错误且文件后缀为so，输出错误
        if (pluginFullName.endsWith(".so"))
            qDebug() << pluginFullName << "Load Failed: " << loader.errorString();
    }
}

void MainWindow::initLeftsideBar()
{
    scrollArea = new KNavigationBar(ui->leftBotWidget);

    connect(this,&MainWindow::specifiedPluginLoaded,this,[=](CommonInterface * pluginInstance){
        int type = ModulesFactory::size();
        QString typeName = tr("Specified");

        QStandardItem *specifiedPlugin = new QStandardItem(pluginInstance->icon(), pluginInstance->plugini18nName());
        QList<QStandardItem *> secondList;
        secondList << specifiedPlugin;
        specifiedPlugin->setData(type, Qt::UserRole+1);
        specifiedPlugin->setData(pluginInstance->plugini18nName(), Qt::UserRole+2);
        scrollArea->addGroupItems(secondList, typeName);

        pluginInstance->pluginBtn = specifiedPlugin;
    });

    int totalModule = ModulesFactory::size();
    for(int index = 0; index < totalModule; index++) {
        //循环构建左侧边栏一级菜单按钮
        ModuleInfo *curModuleInfo = ModulesFactory::getModuleInfoByIndex(index);
        if (curModuleInfo == nullptr) {
            continue;
        }
        int type = curModuleInfo->moduleType;
        if (ModulesFactory::checkModuleType(type)){   // 一级菜单不会有多个
            QString mnameString = curModuleInfo->moduleName;
            const QString locale = QLocale::system().name();
            QString mnamei18nString = curModuleInfo->getModuleNameLocale(locale);
            if (m_ModuleMap.keys().contains(mnameString)) {
                if (!m_ModuleMap[mnameString].toBool()) {
                    continue;
                }
            }

            QList<QStandardItem *> secondList;
            QList<PluginInfo> functionStructList = curModuleInfo->pluginInfoList;
            if (functionStructList.size() <= 0) { // 下属无插件，不显示
                continue;
            }
            int showModuleCount = 0;
            for (int funcIndex = 0; funcIndex < functionStructList.size(); funcIndex++) {
                PluginInfo single = functionStructList.at(funcIndex);

                //跳过插件不存在的功能项
                if (!ModulesFactory::checkPluginExist(single.namei18nString) || !single.isEnable) {
                    continue;
                }

                bool plgIsVisiable = false;
                if (m_ModuleMap.keys().contains(single.nameString.toLower())) {
                    if (!m_ModuleMap[single.nameString.toLower()].toBool()) {
                        m_searchWidget->hiddenSearchItem(single.namei18nString, false);
                        continue;
                    }
                    else plgIsVisiable = true;
                } else {
                    plgIsVisiable = true;
                }

                // intel与sp1做区分
                if ((UkccCommon::isTablet() && single.nameString == "Userinfo")
                    || (!UkccCommon::isTablet() && single.nameString == "Userinfointel")) {
                    continue;
                }

                //填充左侧菜单
                QObject* pluginObj = ModulesFactory::getPluginObjectByName(single.namei18nString);
                if (pluginObj == nullptr) {
                    continue;
                }
                CommonInterface * pluginInstance = qobject_cast<CommonInterface *>(pluginObj);
                QStandardItem *pluginItem = new QStandardItem(pluginInstance->icon(), single.namei18nString);
                secondList << pluginItem;
                pluginItem->setData(type, Qt::UserRole+1);
                pluginItem->setData(single.namei18nString, Qt::UserRole+2);
                pluginInstance->pluginBtn = pluginItem;
                // 初始化插件状态
                QGSettings *msettings = nullptr;
                int row = scrollArea->model()->rowCount() + secondList.count();
                if (vecGsettins.contains(single.oriNameString)) {
                    msettings = vecGsettins[single.oriNameString];
                    if (msettings && plgIsVisiable) {
                        connect(msettings, &QGSettings::changed,[=](QString key){
                            bool visible = !pluginInstance->isEnable() ? false : msettings->get(SHOW_KEY).toBool();
                            qDebug() << "isEnable = " << pluginInstance->isEnable();
                            if (key == SHOW_KEY) {
                                if (!msettings->get(SHOW_KEY).toBool() && scrollArea->listview()->currentIndex().row() == row) {
                                    ui->stackedWidget->setCurrentIndex(0);
                                }
                                scrollArea->listview()->setRowHidden(row, !visible);
                                m_searchWidget->hiddenSearchItem(QLocale::system().name() == "zh_CN" ? single.namei18nString : single.oriNameString, visible);
                            }
                        });
                    }
                }
                ++showModuleCount;
            }
            // 下属无插件，不显示
            if (curModuleInfo->pluginInfoList.size() == 0 || showModuleCount == 0 || secondList.size() == 0) {
                continue;
            }
            scrollArea->addGroupItems(secondList, mnamei18nString);
            for (int funcIndex = 0; funcIndex < functionStructList.size(); funcIndex++) {
                PluginInfo single = functionStructList.at(funcIndex);
                if (!single.isEnable) {
                    QList<QStandardItem *> itemList = scrollArea->model()->findItems(single.namei18nString);
                    if (!itemList.isEmpty()) {
                        qDebug() << "row = " << scrollArea->model()->indexFromItem(itemList.at(0)).row() << ";" <<single.namei18nString;
                        scrollArea->listview()->setRowHidden(scrollArea->model()->indexFromItem(itemList.at(0)).row(), true);
                        m_searchWidget->hiddenSearchItem(QLocale::system().name() == "zh_CN" ? single.namei18nString : single.oriNameString, true);
                    }
                }
            }
        }
    }

    connect(scrollArea->listview(), &QListView::clicked, this, [=](const QModelIndex &index){
        qDebug() << "index = " << index.data(Qt::UserRole+2).toString();
        QString pluginil8Name =  index.data(Qt::UserRole+2).toString();
        QObject* pluginObj = ModulesFactory::getPluginObjectByName(pluginil8Name);
        if (pluginObj != nullptr) {
            CommonInterface * pluginInstance = qobject_cast<CommonInterface *>(pluginObj);
            if (pluginInstance) {
                modulepageWidget->refreshPluginWidget(pluginInstance);

                // 埋点点击左侧导航插件
                UkccCommon::buriedSettings(pluginInstance->name(), nullptr, QString("left clicked"));
            }
        }
    });
    ui->leftBotLayout->addWidget(scrollArea);
}

QGSettings *MainWindow::setGsettingsPath(QList<char *> list, QString name)
{
    // 为每个插件创建动态QGSettings对象，用于监听插件是否隐藏
    QByteArray ba;
    char *path;
    ba = (QString("%1%2").arg(name).arg("/")).toUtf8();
    path = ba.data();
    const QByteArray id(PLUGINS_SCHEMA);
    if (!QGSettings::isSchemaInstalled(id)) {
        return nullptr;
    }
    QGSettings *settings = nullptr;
    QString plugin = QString("%1%2%3").arg(PLUGINS_PATH).arg(name).arg("/");
    settings = new QGSettings(id, plugin.toUtf8().data(), this);

    //判断是否已存在该路径,不存在则赋初值
    for (int j = 0; j < list.count(); j++) {
        if (!qstrcmp(path, list.at(j))){
            return settings;
        }
    }
    settings->set(PLUGIN_NAME, name);
    settings->set(SHOW_KEY, true);
    return settings;
}

bool MainWindow::isExitsCloudAccount() {
    QProcess *wifiPro = new QProcess();
    QString shellOutput = "";
    wifiPro->start("dpkg -l  | grep kylin-sso-client");
    wifiPro->waitForFinished();
    QString output = wifiPro->readAll();
    shellOutput += output;
    QStringList slist = shellOutput.split("\n");

    for (QString res : slist) {
        if (res.contains("kylin-sso-client")) {
            return true;
        }
    }
    return false;
}

bool MainWindow::isExitsPower()
{
    QProcess *process = new QProcess;
    process->start("dpkg -l ukui-power-manager");
    process->waitForFinished();

    QByteArray ba = process->readAllStandardOutput();
    delete process;
    QString mOutput = QString(ba.data());

    return mOutput.contains("ii", Qt::CaseSensitive) ? true : false;
}

bool MainWindow::isExitWirelessDevice()
{
    QDBusInterface *interface = new QDBusInterface("com.kylin.network", "/com/kylin/network",
                                     "com.kylin.network",
                                     QDBusConnection::sessionBus());
    if (!interface->isValid()) {
        qDebug() << "/com/kylin/network is invalid";
        return false;
    }

    QDBusMessage result = interface->call(QStringLiteral("getDeviceListAndEnabled"),1);
    if(result.type() == QDBusMessage::ErrorMessage) {
        qWarning() << "getWirelessDeviceList error:" << result.errorMessage();
        return false;
    }

    auto dbusArg =  result.arguments().at(0).value<QDBusArgument>();
    QMap<QString, bool> deviceListMap;
    dbusArg >> deviceListMap;


    if (deviceListMap.isEmpty()) {
        qDebug() << "no wireless device";
        return false;
    }
    return true;
}

bool MainWindow::dblOnEdge(QMouseEvent *event) {
    QPoint pos = event->globalPos();
    int globalMouseY = pos.y();

    int frameY = this->y();

    bool onTopEdges = (globalMouseY >= frameY &&
                       globalMouseY <= frameY + dbWitdth);
    return onTopEdges;
}

void MainWindow::initStyleSheet() {
    // 设置panel图标
    QIcon panelicon;
    if (QIcon::hasThemeIcon("ukui-control-center"))
        panelicon = QIcon::fromTheme("ukui-control-center");

    qApp->setWindowIcon(panelicon);
    this->setWindowTitle(tr("Settings"));
    ui->stackedWidget->setAutoFillBackground(true);

    // 左上角返回按钮
    backBtn->setProperty("useIconHighlightEffect", true);
    backBtn->setProperty("iconHighlightEffectMode", 1);
    backBtn->setFlat(true);

    mOptionBtn->setProperty("useIconHighlightEffect", 0x2);
    mOptionBtn->setProperty("isWindowButton", 0x01);
    mOptionBtn->setAutoRaise(true);

    minBtn->setProperty("useIconHighlightEffect", 0x2);
    minBtn->setProperty("isWindowButton", 0x01);
    minBtn->setFlat(true);

    maxBtn->setProperty("useIconHighlightEffect", 0x2);
    maxBtn->setProperty("isWindowButton", 0x1);
    maxBtn->setFlat(true);

    closeBtn->setProperty("isWindowButton", 0x02);
    closeBtn->setProperty("useIconHighlightEffect", 0x08);
    closeBtn->setFlat(true);

    ui->centralWidget->setAttribute(Qt::WA_TranslucentBackground);
    ui->leftsidebarWidget->setFixedWidth(260); //一级菜单宽度

    // 设置左上角按钮图标
    backBtn->setIcon(QIcon::fromTheme("go-home-symbolic"));
    backBtn->setIconSize(QSize(16, 16));

    // 设置右上角按钮图标
    mOptionBtn->setIcon(QIcon::fromTheme("open-menu-symbolic"));
    minBtn->setIcon(QIcon::fromTheme("window-minimize-symbolic"));
    maxBtn->setIcon(QIcon::fromTheme("window-maximize-symbolic"));
    closeBtn->setIcon(QIcon::fromTheme("window-close-symbolic"));
}

void MainWindow::showGuide(QString pluName)
{
    QString service_name = "com.kylinUserGuide.hotel_" + QString::number(getuid());
    QDBusInterface *interface = new QDBusInterface(service_name,
                                                   KYLIN_USER_GUIDE_PATH,
                                                   KYLIN_USER_GUIDE_INTERFACE,
                                                   QDBusConnection::sessionBus(),
                                                   this);
    QDBusMessage msg = interface->call("showGuide" , pluName);
}

void MainWindow::hideComponent()
{
    QTimer::singleShot(100, this, [=]() {
        if(UkccCommon::isTablet()) {
            if (QApplication::arguments().length() < 2) {
                initPageWidget();
                bootOptionsFilter("userinfointel");
            }
            backBtn->hide();
        }
    });
}

void MainWindow::setModuleBtnHightLight(int id) {
    leftBtnGroup->button(id)->setChecked(true);
    leftMicBtnGroup->button(id)->setChecked(true);
}

void MainWindow::pluginBtnClicked(QObject *plugin) {

    CommonInterface * pluginInstance = qobject_cast<CommonInterface *>(plugin);
    UkccCommon::buriedSettings(pluginInstance->name(), nullptr, "home clicked");

    functionBtnClicked(plugin);
}

void MainWindow::functionBtnClicked(QObject *plugin, QString jumpText) {
    if (!scrollArea)
        return;

    ui->stackedWidget->setCurrentIndex(1);
    modulepageWidget->switchPage(plugin, true, jumpText);

    CommonInterface * pluginInstance = qobject_cast<CommonInterface *>(plugin);
    scrollArea->listview()->setCurrentIndex(pluginInstance->pluginBtn->index());
    QRect size = scrollArea->listview()->visualRect(scrollArea->listview()->currentIndex());
    qDebug() << "size.y() = " <<size.y() << "size.height() = " << size.height() << "step = " << scrollArea->height() << "scrollArea->height()/2" << scrollArea->height()/2;
    int value = size.y() + size.height() - scrollArea->height();
    value = value + scrollArea->height()/2; //尽量让选中的显示在中间位置
    if (value <= 0) {
        scrollArea->verticalScrollBar()->setValue(0);
    } else if (value > scrollArea->verticalScrollBar()->maximum()){
        scrollArea->verticalScrollBar()->setValue(scrollArea->verticalScrollBar()->maximum());
    } else {
        scrollArea->verticalScrollBar()->setValue(value);
    }
}

void MainWindow::sltMessageReceived(const QString &msg) {
    QString platform = QGuiApplication::platformName();
    if(platform.startsWith(QLatin1String("wayland"),Qt::CaseInsensitive)) {
        if (!m_listWinIds.isEmpty()) {
            WindowManager::activateWindow(m_listWinIds.back());
        }
    } else {
        KWindowSystem::forceActiveWindow(this->winId());
    }
    this->initPageWidget();
    this->show();
    bootOptionsFilter(msg, false);
}

QVariantMap MainWindow::getSearchItems() {
    return m_searchWidget->getSearchItems();
}

void MainWindow::switchPage(QString moduleName, QString jumpMoudle, QString jumpText) {
    //开始跳转
    QObject* pluginObj = ModulesFactory::getPluginObjectByName(moduleName);
    if (pluginObj != nullptr) {
        if (m_ModuleMap.isEmpty()) {
            functionBtnClicked(pluginObj);
            return;
        } else {
            QString superordinate = ModulesFactory::getModuleNamebyName(jumpMoudle);
            // 若跳转节点或跳转节点父节点不存在直接跳转，不受管控文件控制，若存在，则根据管控文件判断是否被禁用
            if (!m_ModuleMap.contains(jumpMoudle.toLower()) || !m_ModuleMap.contains(superordinate.toLower())
                    || (m_ModuleMap[jumpMoudle.toLower()].toBool() && m_ModuleMap[superordinate.toLower()].toBool())) {
                functionBtnClicked(pluginObj);
                return;
            }
        }
    }
    QMessageBox::information(this, tr("Warning"), tr("This function has been controlled"));
    return;
}

void MainWindow::moveEvent(QMoveEvent *event)
{
    Q_UNUSED(event);
    Q_EMIT posChanged();
}

void MainWindow::resizeEvent(QResizeEvent *event)
{
    QMainWindow::resizeEvent(event);
    Q_EMIT posChanged();
}

QString MainWindow::pluginBtnHoverColor(QString styleName, bool hoverFlag)
{
    QColor color1 = palette().color(QPalette::Active, QPalette::Button);
    QColor color2 = palette().color(QPalette::Active, QPalette::BrightText);
    QColor color;
    qreal r,g,b,a;
    QString hoverColor;
    if (((styleName.contains("dark") || styleName.contains("black")) && hoverFlag) ||
        ((!styleName.contains("dark") && !styleName.contains("black")) && !hoverFlag)) {
        r = color1.redF() * 0.8 + color2.redF() * 0.2;
        g = color1.greenF() * 0.8 + color2.greenF() * 0.2;
        b = color1.blueF() * 0.8 + color2.blueF() * 0.2;
        a = color1.alphaF() * 0.8 + color2.alphaF() * 0.2;
    } else {
        r = color1.redF() * 0.95 + color2.redF() * 0.05;
        g = color1.greenF() * 0.95 + color2.greenF() * 0.05;
        b = color1.blueF() * 0.95 + color2.blueF() * 0.05;
        a = color1.alphaF() * 0.95 + color2.alphaF() * 0.05;
    }
    color = QColor::fromRgbF(r, g, b, a);
    hoverColor = QString("rgba(%1, %2, %3, %4)").arg(color.red())
                                                .arg(color.green())
                                                .arg(color.blue())
                                                .arg(color.alpha());
    return hoverColor;
}
