#include "maindialog.h"
#include "ui_maindialog.h"

#include <QMenu>
#include <QProcess>
#include <QMessageBox>
#include <KWindowSystem>
#include <KWindowEffects>
#include <ukuistylehelper/ukuistylehelper.h>
#include <windowmanager/windowmanager.h>
#include <unistd.h>
#include "../common/mydefine.h"
#include "../common/dynamiccreator.h"
#include "backup_manager_interface.h"
#include "globalbackupinfo.h"
#include "messageboxutils.h"
#include "aboutdialog.h"
#include "gsettingswrapper.h"
#include "component/mywidget.h"

MainDialog::MainDialog(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainDialog)
{
    ui->setupUi(this);
    // 主窗口
    this->setWindowTitle(tr("Backup & Restore"));
    // 窗口背景透明化；setWindowOpacity可使得窗口及其上控件都透明或半透明-w.setWindowOpacity(0.7);
    this->setAttribute(Qt::WA_TranslucentBackground);
    // 使得窗口无边框
    // w.setWindowFlag(Qt::FramelessWindowHint);
    // 指示窗口管理器模糊给定窗口后面指定区域的背景(毛玻璃化背景)
    // KWindowEffects::enableBlurBehind(this->winId(), true);
    // 或使用设置毛玻璃属性的方式实现毛玻璃背景（两者都行，可使用其一）
    this->setProperty("useSystemStyleBlur", true);
    this->setAutoFillBackground(true);
    connect(kdk::WindowManager::self(), &kdk::WindowManager::windowAdded, this, [=](const kdk::WindowId& window_id){
        if (getpid() == kdk::WindowManager::getPid(window_id) && m_window_id.isNull())
        {
            m_window_id = window_id.toString();
        }
    });

    // 去除窗管标题栏，传入参数为QWidget *
    kdk::UkuiStyleHelper::self()->removeHeader(this);

    GlobelBackupInfo::instance().setMainWidget(this);

    // 注册BackupWrapper类型，之后qdbus接口才能使用
    BackupWrapper::registerMetaType();
    mountBackupPartition();

    initUI();
    initConnect();
}

MainDialog::~MainDialog()
{
    delete ui;
}

void MainDialog::initUI()
{
    // 总体布局为横向布局，分为左侧和右侧
    m_totalHLayout = new QHBoxLayout;
    m_totalHLayout->setSpacing(0);
    m_totalHLayout->setObjectName(QString::fromUtf8("m_totalHLayout"));
    m_totalHLayout->setContentsMargins(0, 0, 0, 0);
    m_totalHLayout->setSpacing(0);
    ui->centralwidget->setLayout(m_totalHLayout);

    // 左栏窗口
    if (GlobelBackupInfo::instance().isCasper())  // 试安装模式中只能使用系统还原
        m_leftSiderBarWidget = new LeftsiderbarWidget(ui->centralwidget, LeftsiderbarWidget::StartMode::casper);
    else if (GlobelBackupInfo::instance().isManager())  // 管理员可以使用全部功能
        m_leftSiderBarWidget = new LeftsiderbarWidget(ui->centralwidget);
    else  // 标准用户可以使用数据备份、数据还原
        m_leftSiderBarWidget = new LeftsiderbarWidget(ui->centralwidget, LeftsiderbarWidget::StartMode::stdUser);
    m_leftSiderBarWidget->setObjectName(QString::fromUtf8("m_leftSiderBarWidget"));
    m_leftSiderBarWidget->setFixedWidth(200);
    m_leftSiderBarWidget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);

    m_totalHLayout->addWidget(m_leftSiderBarWidget);

    // 右侧窗口
    m_rightWidget = new MyWidget;
    m_totalHLayout->addWidget(m_rightWidget);

    m_rightVLayout = new QVBoxLayout;
    m_rightVLayout->setObjectName(QString::fromUtf8("m_rightVLayout"));
    m_rightVLayout->setContentsMargins(0, 0, 0, 0);
    m_rightVLayout->setSpacing(0);

    // 右侧窗口：标题栏
    m_titleWidget = new DoubleClickWidget;
    m_titleWidget->setObjectName(QString::fromUtf8("m_titleWidget"));
    m_titleWidget->setFixedHeight(40);
    m_rightVLayout->addWidget(m_titleWidget);

    // 右侧窗口：工作区
    m_workWidget = new QWidget;
    m_workWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    m_rightVLayout->addWidget(m_workWidget);
    m_rightWidget->setLayout(m_rightVLayout);

    // 工作区随左边框功能切换界面
    m_workVLayout = new QVBoxLayout;
    if (GlobelBackupInfo::instance().isCasper())
        selected(FuncTypeConverter::FunType::RESTORE_SYSTEM);
    else if (GlobelBackupInfo::instance().isManager() && GlobelBackupInfo::instance().hasArgRestore())
        selected(FuncTypeConverter::FunType::RESTORE_SYSTEM);
    else if (!GlobelBackupInfo::instance().isManager()  && GlobelBackupInfo::instance().hasArgRestore())
        selected(FuncTypeConverter::FunType::RESTORE_DATA);
    else if (!GlobelBackupInfo::instance().isManager())
        selected(FuncTypeConverter::FunType::BACKUP_DATA);
    else
        selected(FuncTypeConverter::FunType::BACKUP_SYSTEM);
    m_workWidget->setLayout(m_workVLayout);

    initTileBar();
}

void MainDialog::initTileBar()
{
    m_titleLayout = new QHBoxLayout;
    m_titleLayout->setContentsMargins(8, 4, 4, 0);
    m_titleLayout->setSpacing(4);

    m_menuOptionBtn  = new QToolButton;
    m_minBtn      = new QPushButton;
    m_maxBtn      = new QPushButton;
    m_closeBtn    = new QPushButton;

    m_menuOptionBtn->setToolTip(tr("Options"));
    m_minBtn->setToolTip(tr("Minimize"));
    m_maxBtn->setToolTip(tr("Maximize"));
    m_closeBtn->setToolTip(tr("Close"));

    m_menuOptionBtn->setProperty("isWindowButton", 0x1);
    m_menuOptionBtn->setProperty("useIconHighlightEffect", 0x2);
    m_menuOptionBtn->setIcon(QIcon::fromTheme("open-menu-symbolic"));
    m_menuOptionBtn->setFixedSize(PC_TITLE_BAR_SIZE, PC_TITLE_BAR_SIZE);
    m_menuOptionBtn->setAutoRaise(true);
    m_menuOptionBtn->setPopupMode(QToolButton::InstantPopup);

    m_minBtn->setProperty("isWindowButton", 0x1);
    m_minBtn->setProperty("useIconHighlightEffect", 0x2);
    m_minBtn->setFixedSize(PC_TITLE_BAR_SIZE, PC_TITLE_BAR_SIZE);
    m_minBtn->setFlat(true);
    m_minBtn->setIcon(QIcon::fromTheme("window-minimize-symbolic"));

    m_maxBtn->setProperty("isWindowButton", 0x1);
    m_maxBtn->setProperty("useIconHighlightEffect", 0x2);
    m_maxBtn->setFixedSize(PC_TITLE_BAR_SIZE, PC_TITLE_BAR_SIZE);
    m_maxBtn->setFlat(true);
    m_maxBtn->setIcon(QIcon::fromTheme("window-maximize-symbolic"));

    m_closeBtn->setProperty("isWindowButton", 0x2);
    m_closeBtn->setProperty("useIconHighlightEffect", 0x8);
    m_closeBtn->setFixedSize(PC_TITLE_BAR_SIZE, PC_TITLE_BAR_SIZE);
    m_closeBtn->setFlat(true);
    m_closeBtn->setIcon(QIcon::fromTheme("window-close-symbolic"));

    QMenu* backupMain = new QMenu(m_titleWidget);
    backupMain->setObjectName("mainMenu");
    m_menuOptionBtn->setMenu(backupMain);

    // 暂时只需跟随主题，浅色主题和深色主题后续可能会独立出来
//    QAction* backupTheme = new QAction(tr("Theme"), m_titleWidget);
//    backupMain->addAction(backupTheme);
//    QMenu* selectTheme = new QMenu( m_titleWidget);
//    selectTheme->setObjectName("selectTheme");
//    backupTheme->setMenu(selectTheme);
//    QAction* defaultTheme = new QAction(tr("Auto"), m_titleWidget);
//    selectTheme->addAction(defaultTheme);
//    QAction* lightTheme = new QAction(tr("Light"), m_titleWidget);
//    selectTheme->addAction(lightTheme);
//    QAction* darkTheme = new QAction(tr("Dark"), m_titleWidget);
//    selectTheme->addAction(darkTheme);

    m_backupHelp = new QAction(tr("Help"), m_titleWidget);
    // 设计竟然让快捷键标记不能在页面中提示出来，要悄默默的快捷，奇葩。需要重定义键盘事件代替通用快捷键设置方法。
    // m_backupHelp->setShortcut(QKeySequence::HelpContents);
    backupMain->addAction(m_backupHelp);
    m_backupAbout = new QAction(tr("About"), m_titleWidget);
    backupMain->addAction(m_backupAbout);
    m_backupExit = new QAction(tr("Quit"), m_titleWidget);
    backupMain->addAction(m_backupExit);

    m_titleLayout->addStretch();
    m_titleLayout->addWidget(m_menuOptionBtn);
    m_titleLayout->addWidget(m_minBtn);
    m_titleLayout->addWidget(m_maxBtn);
    m_titleLayout->addWidget(m_closeBtn);
    m_titleWidget->setLayout(m_titleLayout);
}

void MainDialog::initConnect()
{
    // 左侧功能选择栏
    connect(m_leftSiderBarWidget, &LeftsiderbarWidget::selected, this, &MainDialog::selected);
    connect(GlobelBackupInfo::instance().getGlobalSignals(), &GlobalSignals::busy, m_leftSiderBarWidget, &LeftsiderbarWidget::setBusy);

    // 标题栏右侧按钮区域
    // 退出
    connect(m_backupExit, &QAction::triggered, this, &MainDialog::closeBtn);

    // 关于
    connect(m_backupAbout, &QAction::triggered, this, [=] {
        AboutDialog *about = new AboutDialog(this);
        kdk::UkuiStyleHelper::self()->removeHeader(about);
        if(!GlobelBackupInfo::instance().isWayland()){
            about->setModal(true);
            about->show();
            about->move(width()/2-about->width()/2+x(),height()/2-about->height()/2+y());
            kdk::WindowManager::setGeometry(about->windowHandle(),about->geometry());
        }
        about->exec();
        about->deleteLater();
    });

    // 用户手册
    connect(m_backupHelp, &QAction::triggered, this, [=] {
        QProcess process(this);
        process.startDetached("kylin-user-guide -A yhkylin-backup-tools");
    });

    //最小化按钮
    connect(m_minBtn, &QPushButton::clicked, this, &MainDialog::showMinimized);
    //最大化按钮
    connect(m_maxBtn, &QPushButton::clicked, this, [=] {
        if (isMaximized()) {
            showNormal();
        } else {
            showMaximized();
        }
    });
    connect(m_titleWidget, &DoubleClickWidget::doubleClicked, m_maxBtn, &QPushButton::click);
    connect(m_leftSiderBarWidget, &LeftsiderbarWidget::doubleClicked, m_maxBtn, &QPushButton::click);

    //关闭按钮
    connect(m_closeBtn, &QPushButton::clicked, this, &MainDialog::closeBtn);

    //监听平板模式切换
    m_statusSessionDbus = new QDBusInterface("com.kylin.statusmanager.interface",
                                             "/",
                                             "com.kylin.statusmanager.interface",
                                             QDBusConnection::sessionBus(),
                                             this);
    if (m_statusSessionDbus->isValid()) {
        QDBusReply<bool> isTabletMode = m_statusSessionDbus->call("get_current_tabletmode");
        GlobelBackupInfo::instance().setIsTabletMode(isTabletMode);
        tabletModeChange(isTabletMode);
        connect(m_statusSessionDbus, SIGNAL(mode_change_signal(bool)), this, SLOT(tabletModeChange(bool)));
    } else {
        GlobelBackupInfo::instance().setIsTabletMode(false);
        m_maxBtn->setVisible(true);
    }
}

/**
 * @brief 平板模式切换
 * @param isTabletMode  true-平板模式；false-PC模式
 */
void MainDialog::tabletModeChange(bool isTabletMode)
{
    GlobelBackupInfo::instance().setIsTabletMode(isTabletMode);
    if(isTabletMode){
        m_menuOptionBtn->setFixedSize(TABLET_TITLE_BAR_SIZE, TABLET_TITLE_BAR_SIZE);
        m_minBtn->setFixedSize(TABLET_TITLE_BAR_SIZE, TABLET_TITLE_BAR_SIZE);
        m_maxBtn->setFixedSize(TABLET_TITLE_BAR_SIZE, TABLET_TITLE_BAR_SIZE);
        m_closeBtn->setFixedSize(TABLET_TITLE_BAR_SIZE, TABLET_TITLE_BAR_SIZE);
        m_titleWidget->setFixedHeight(56);
        m_maxBtn->setVisible(false);
    } else {
        m_menuOptionBtn->setFixedSize(PC_TITLE_BAR_SIZE, PC_TITLE_BAR_SIZE);
        m_minBtn->setFixedSize(PC_TITLE_BAR_SIZE, PC_TITLE_BAR_SIZE);
        m_maxBtn->setFixedSize(PC_TITLE_BAR_SIZE, PC_TITLE_BAR_SIZE);
        m_closeBtn->setFixedSize(PC_TITLE_BAR_SIZE, PC_TITLE_BAR_SIZE);
        m_titleWidget->setFixedHeight(40);
        m_maxBtn->setVisible(true);
    }
}

void MainDialog::changeEvent(QEvent *event)
{
    if (QEvent::WindowStateChange == event->type()) {
        Qt::WindowStates state = this->windowState();
        switch (state) {
        case Qt::WindowMaximized:
        case Qt::WindowFullScreen:
            m_maxBtn->setIcon(QIcon::fromTheme("window-restore-symbolic"));
            m_maxBtn->setToolTip(tr("Normal"));

            break;
        case Qt::WindowNoState:
            m_maxBtn->setIcon(QIcon::fromTheme("window-maximize-symbolic"));
            m_maxBtn->setToolTip(tr("Maximize"));

            break;
        default:
            break;
        }
    }

    QMainWindow::changeEvent(event);
}

void MainDialog::keyPressEvent(QKeyEvent *event)
{
    if (event->key() == Qt::Key_F1)
        emit m_backupHelp->triggered();

    QMainWindow::keyPressEvent(event);
}

/**
 * @brief 左侧功能选择栏响应槽
 * @param func_type，功能类型
 */
void MainDialog::selected(int funcType)
{
    if (GlobelBackupInfo::instance().getFuncType() == funcType)
        return ;

    if (m_stackedWidget) {
        m_workVLayout->removeWidget(m_stackedWidget);
        delete m_stackedWidget;
    }

    m_stackedWidget = createWidgetFactory(funcType, m_workWidget);
    if (!m_stackedWidget)
        m_stackedWidget = new QStackedWidget(m_workWidget);
    GlobelBackupInfo::instance().setFuncType((FuncTypeConverter::FunType)funcType);
    m_stackedWidget->setObjectName(QString::fromUtf8("m_stackedWidget"));
    // m_stackedWidget->setMinimumSize(760, 600);
    m_workVLayout->addWidget(m_stackedWidget);

    m_leftSiderBarWidget->setCheckedFunc(funcType);
}

/**
 * @brief 功能界面工厂，根据功能类型动态创建对应的功能界面
 * @param funcType，功能类型
 * @param parent，父窗口
 * @return 功能界面的QStackedWidget*指针
 * @note  调用方控制返回指针的释放
 */
QStackedWidget * MainDialog::createWidgetFactory(int funcType, QWidget *parent/* = nullptr*/)
{
    FuncTypeConverter converter;
    QString className = converter.funcTypeToWidgetClassName(funcType);
    return DynamicCreator<QStackedWidget*,QWidget*>::createInstance(className, parent);
}

/**
 * @brief 多例启动信息槽
 * @param msg 信息，里面存放新启动实例的账户id
 */
void MainDialog::sltMessageReceived(const QString &msg)
{
    QString user = QString::number(getuid());
    if (msg == user) {
//        this->setWindowFlag(Qt::WindowStaysOnTopHint,true);
        KWindowSystem::forceActiveWindow(this->winId());
        this->show();
    }
}

/**
 * @brief 挂载备份分区
 * @note 程序开启时挂载备份分区
 */
void MainDialog::mountBackupPartition()
{
    // 挂载/backup分区
    ComKylinBackupManagerInterface intf("com.kylin.backup", "/", QDBusConnection::systemBus());
    QDBusPendingReply<int> reply = intf.Mount_backup_partition();
    reply.waitForFinished();
    if (reply.isError()) {
        // 挂载分区时出现异常
        MessageBoxUtils::QMESSAGE_BOX_CRITICAL(this, QObject::tr("Warning"),
                                              QObject::tr("An exception occurred when mounting backup partition."),
                                              QObject::tr("OK"));

        // 此时还未进入应用的事件循环中，故不能使用qApp->quit();
        exit(1);
    } else if (int(MountResult::CANNOT_GET_BACKUPUUID) == reply.value()) {
        // 没有找到备份分区不再报错，改为只能备份到移动设备中
//        MessageBoxUtils::QMESSAGE_BOX_WARNING(this, QObject::tr("Information"),
//                                              QObject::tr("Please check if the backup partition exists which can be created when you install the Operating System."),
//                                              QObject::tr("OK"));
//        // 此时还未进入应用的事件循环中，故不能使用qApp->quit();
//        exit(1);
        GlobelBackupInfo::instance().setHasBackupPartition(false);
    } else if (int(MountResult::MOUNTED) != reply.value()) {
        // 挂载备份分区失败
        MessageBoxUtils::QMESSAGE_BOX_CRITICAL(this, QObject::tr("Warning"),
                                              QObject::tr("Failed to mount backup partition."),
                                              QObject::tr("OK"));

        // 此时还未进入应用的事件循环中，故不能使用qApp->quit();
        exit(1);
    }
}

/**
 * @brief 卸载备份分区
 * @note 应用关闭时卸载备份分区，以隐藏保护以防误删除
 */
void MainDialog::umountBackupPartition()
{
    // 卸载/backup分区
    ComKylinBackupManagerInterface intf("com.kylin.backup", "/", QDBusConnection::systemBus());
    intf.umountBackupPartition();
}

void MainDialog::closeEvent(QCloseEvent *e)
{
    if (GlobelBackupInfo::instance().isBusy()) {
        // 系统正忙，请稍等
        MessageBoxUtils::QMESSAGE_BOX_WARNING(this, QObject::tr("Warning"),
                                              QObject::tr("It's busy, please wait"),
                                              QObject::tr("OK"));

        e->ignore();
        return;
    }

    if (GlobelBackupInfo::instance().hasBackupPartition())
        umountBackupPartition();

    e->accept();
}

void MainDialog::resizeEvent(QResizeEvent *event) {
    emit GlobelBackupInfo::instance().getGlobalSignals()->widthChanged();
    QMainWindow::resizeEvent(event);
}

void MainDialog::closeBtn()
{
    if (this->close()) {
        qApp->quit();
    }
}

