//
// Created by 张雪明 <zhangxueming@uniontech.com> on 2024/11/18.
//
#include "MainWindowSnipe.h"
#include "utils/Utils.h"
#include "utils/errorCodes.h"
#include "utils/FsTab.h"
#include "utils/Device.h"
#include "common/NavigationListView.h"
#include "common/CommonFunc.h"
#include "common/ItemFrame.h"
#include "immutable/backup/ImmuBackupFrame.h"
#include <DPaletteHelper>
#include <DAnchors>
#include <DTitlebar>
#include <QTimer>
#include <DWindowManagerHelper>
#include <QStandardItemModel>
#include <selinux/selinux.h>
#include <DBlurEffectWidget>

const static QString MainWindowSnipeObjName = "uos-recovery-gui-MainWindowSnipe-obj-name";
const static QString MainWindowSnipeTitleBar = "uos-recovery-gui-MainWindowSnipe-TitleBar";
const static int IMMU_BACKUP_MODULE_ID = 0;
const static int IMMU_RESTORE_MODULE_ID = 1;
const static int IMMU_FACTORY_RESTORE_MODULE_ID = 2;

// DTK默认实现不满足多个DMainWindow的场景，需要自己实现
void MainWindowSnipe::onNewProcessInstance()
{
    for (QWidget *window : qApp->topLevelWidgets()) {
        DMainWindow *pDMainWindow = qobject_cast<DMainWindow*>(window);
        if (nullptr != pDMainWindow) {
            QString objName = pDMainWindow->objectName();
            QString mainTitleBarAccessibleName;
            DTitlebar * titleBar = pDMainWindow->titlebar();
            if (nullptr != titleBar) {
                mainTitleBarAccessibleName = titleBar->accessibleName();
            }
            //    qInfo()<<"objName = "<<objName<<", mainTitleBarAccessibleName = "<<mainTitleBarAccessibleName;
            // 避免其他DMainWindow类设置同名，加上titleBar的AccessibleName加强校验
            if (MainWindowSnipeObjName != objName && MainWindowSnipeTitleBar != mainTitleBarAccessibleName) {
                continue;
            }

            // 如果窗口最小化或者隐藏了，应当先将其show出來
            if (pDMainWindow->isMinimized() || pDMainWindow->isHidden()) {
                pDMainWindow->showNormal();
            }

            pDMainWindow->activateWindow();
            pDMainWindow->raise();
            break;
        }
    }
}

MainWindowSnipe::MainWindowSnipe(QWidget *parent)
    : DMainWindow(parent)
{
    registerALLMetaType();
    connect(DGuiApplicationHelper::instance(), SIGNAL(newProcessInstance(qint64, const QStringList &)),
            this, SLOT(onNewProcessInstance()));
    this->setObjectName(MainWindowSnipeObjName);

    QSettings versionFile("/etc/os-version", QSettings::IniFormat);
    versionFile.beginGroup("Version");
    m_osMajorVer = versionFile.value("MajorVersion").toInt();
    m_osMinorVer = versionFile.value("MinorVersion").toInt();
    versionFile.endGroup();

    m_isImmutable = Utils::isImmutableSystem();
  //  m_isCommunity = Utils::isCommunity();
    m_isDeepinBootKitExist = Utils::isDeepinBootKitExist();
    if (Utils::isGhostOnly()) {
        m_isGhostOnly = true;
    }

    m_rightWidget = new QWidget();

    DTitlebar *titleBar = this->titlebar();
    titleBar->setAccessibleName("MainWindowSnipeTitleBar");
   // titleBar->setAutoFillBackground(true);
    titleBar->setBackgroundTransparent(true);
    //titleBar->setBlurBackground(true);
    titleBar->setSeparatorVisible(false);

    // 隐藏title阴影,避免设置widget颜色会出现透明效果。
  //  setTitlebarShadowEnabled(false);

    //上一步按钮
    m_backwardBtn = new DIconButton(this); //上一步按钮
    m_backwardBtn->setAccessibleName("backwardButton");
    m_backwardBtn->setIcon(QStyle::SP_ArrowBack);
    m_backwardBtn->setFixedSize(30, 30);
    m_backwardBtn->setFlat(true);
    // m_backwardBtn->hide();

    titleBar->setContentsMargins(10, 0,0,0);
    titleBar->addWidget(m_backwardBtn, Qt::AlignLeft | Qt::AlignVCenter);
    connect(m_backwardBtn, &DIconButton::clicked, this, &MainWindowSnipe::onBackWardClick);
   // this->initUI();
    initNewUI();
    updateSidebarSeparator();

    connect(DGuiApplicationHelper::instance(), &DGuiApplicationHelper::themeTypeChanged,
            this, [this]() {
                updateTheme();
                updateSidebarSeparator();
            });

    QTimer::singleShot(0, this, &MainWindowSnipe::initAllModule); //初始化所有模块
}

MainWindowSnipe::~MainWindowSnipe()
{

}

void MainWindowSnipe::closeEvent(QCloseEvent *event)
{
    if (nullptr != m_logDialog) {
        m_logDialog->close();
        m_logDialog->deleteLater();
        m_logDialog = nullptr;
    }

    QMainWindow::closeEvent(event);
}

void MainWindowSnipe::updateTheme()
{
    QColor iconAreaColor;
    QColor rightAreaColor;
    if (DGuiApplicationHelper::instance()->themeType() == DGuiApplicationHelper::LightType) {
        iconAreaColor.setRgb(250, 255, 255);
        iconAreaColor.setAlphaF(0.8);

        rightAreaColor.setRgb(248, 248, 248);
        rightAreaColor.setAlphaF(1);
    } else {
        iconAreaColor.setRgb(16, 16, 16);
        iconAreaColor.setAlphaF(0.2);
        
        rightAreaColor.setRgb(28, 28, 28);
        rightAreaColor.setAlphaF(1);
    }

    m_leftNavFrame->setAttribute(Qt::WA_TranslucentBackground);
    m_leftNavView->setAttribute(Qt::WA_TranslucentBackground);

    // 创建 DBlurEffectWidget
    if (!m_leftNavFrameBlurWidget) {
        m_leftNavFrameBlurWidget = new DBlurEffectWidget(m_leftNavFrame);
    }
    m_leftNavFrameBlurWidget->setGeometry(m_leftNavFrame->rect());
    m_leftNavFrameBlurWidget->setMode(DBlurEffectWidget::GaussianBlur);
    m_leftNavFrameBlurWidget->setBlendMode(DBlurEffectWidget::BehindWindowBlend);
    m_leftNavFrameBlurWidget->setBlurRectXRadius(-1);
    m_leftNavFrameBlurWidget->setBlurEnabled(true);
    m_leftNavFrameBlurWidget->setMaskColor(iconAreaColor);
    m_leftNavFrameBlurWidget->setMaskAlpha(204);
    m_leftNavFrameBlurWidget->lower(); // 将模糊效果置于底层

    QPalette rightViewPalette;
    rightViewPalette.setBrush(QPalette::Window, QBrush(rightAreaColor));
    m_rightAreaFrame->setPalette(rightViewPalette);
    titlebar()->setPalette(rightViewPalette);
}

void MainWindowSnipe::updateSidebarSeparator()
{
    updateSideBarSeparatorStyle();
    updateSideBarSeparatorPosition();
}

void MainWindowSnipe::updateSideBarSeparatorStyle()
{
    if (!m_separator)
        return;

    // 设置颜色 - 仅在主题变化或初始化时需要
    QColor sepColor(0, 0, 0);
    QColor hSepColor(0, 0, 0);
    if (DGuiApplicationHelper::instance()->themeType() == DGuiApplicationHelper::LightType) {
        sepColor.setAlphaF(0.05);   // 浅色主题 5% 透明度
        hSepColor.setAlphaF(0.05);
    } else {
        sepColor.setAlphaF(0.5);   // 深色主题 50% 透明度
        hSepColor.setAlphaF(0.5);
    }

    // 使用setBrush而不是setColor以确保透明度正确应用
    QPalette palette;
    palette.setBrush(QPalette::Window, QBrush(sepColor));
    m_separator->setPalette(palette);

    QPalette hPalette;
    hPalette.setBrush(QPalette::Window, QBrush(hSepColor));
    m_hSeparator->setPalette(hPalette);

    // 确保分隔线能够正确显示透明效果
    m_separator->setAutoFillBackground(true);
    m_hSeparator->setAutoFillBackground(true);

    // 确保没有边框影响显示
    if (auto sidebarFrame = qobject_cast<QFrame *>(m_separator))
        sidebarFrame->setFrameShape(QFrame::NoFrame);
    if (auto sidebarFrame = qobject_cast<QFrame *>(m_hSeparator))
        sidebarFrame->setFrameShape(QFrame::NoFrame);
}

void MainWindowSnipe::updateSideBarSeparatorPosition()
{
    if (!m_leftNavFrame || !m_separator) {
        return;
    }

    // 确保分割线显示在侧边栏右侧边缘
    m_separator->setParent(m_leftNavFrame);
    m_separator->move(m_leftNavFrame->x() + m_leftNavFrame->width() - 1, m_leftNavFrame->y());
    m_separator->setFixedHeight(m_leftNavFrame->height());
    m_separator->raise();

    // 根据侧边栏实际可见性设置分割线可见性
    m_separator->setVisible(m_leftNavFrame->isVisible() && m_leftNavFrame->width() > 0 && m_leftNavFrame->height() > 0);
}

void MainWindowSnipe::initNewUI()
{
    setAttribute(Qt::WA_TranslucentBackground);
    //setAttribute(Qt::WA_OpaquePaintEvent);

    //标题栏
    DTitlebar *titleBar = this->titlebar();
    titleBar->setAccessibleName(MainWindowSnipeTitleBar);
    setTitlebarShadowEnabled(false);

    auto menu = titleBar->menu();
    if (!menu) {
        menu = new QMenu(this);
    }
    titleBar->setMenu(menu);

    //操作日志
    auto logAction = new QAction(tr("Logs"), this);
    menu->addAction(logAction);
    connect(logAction, &QAction::triggered, this, &MainWindowSnipe::showLogDialog);

    m_leftNavFrame = new QFrame(this);
    m_leftNavFrame->setContentsMargins(0,0,0,0);
    //m_leftNavFrame->setFixedHeight(650);
    m_leftNavView = new NavigationListView(this);
    m_leftNavView->setFixedWidth(156);
    m_leftNavView->setFixedHeight(620);
    m_leftNavView->setItemSize(QSize(80, 80));
    m_leftNavView->setItemSpacing(0);
    m_leftNavView->setSpacing(50);
    m_leftNavView->setIconSize(QSize(80, 80));
    m_leftNavView->setFrameShape(QFrame::Shape::NoFrame);
    m_leftNavView->setEditTriggers(QListView::NoEditTriggers);
    m_leftNavView->setAutoScroll(false); //滚动条
    m_leftNavView->setTabKeyNavigation(false); //tab按键是否有效
    m_leftNavView->setViewportMargins(QMargins(-30, 10, 10, 0)); //滚动区域边框大小
    m_leftNavView->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
    m_leftNavView->setSelectionMode(QAbstractItemView::SingleSelection);
    //m_leftNavView->setAutoFillBackground(true);
    //m_leftNavView->setBackgroundType(DStyledItemDelegate::BackgroundType(DStyledItemDelegate::RoundedBackground | DStyledItemDelegate::NoNormalState));

    m_separator = new DVerticalLine(this);
    m_separator->setVisible(true);
    m_separator->setAutoFillBackground(true);
    //m_separator->setFixedSize(1, 650);
    m_separator->setFixedWidth(1);

    m_iconArea = new QWidget(this);
    QHBoxLayout *leftAreaLayout = new QHBoxLayout(m_iconArea);
    m_iconArea->setWindowFlag(Qt::WindowTransparentForInput);
    m_iconArea->move(0, 0);
    leftAreaLayout->setContentsMargins(0, 0, 0, 0);
    leftAreaLayout->addSpacing(10);

    m_iconBtn = new DIconButton(this);
    m_iconBtn->setWindowFlags(Qt::WindowTransparentForInput);
    m_iconBtn->setAttribute(Qt::WA_TransparentForMouseEvents, true);
    m_iconBtn->setFocusPolicy(Qt::NoFocus);
    m_iconBtn->setFlat(true);

    auto icon = QIcon::fromTheme("uos-recovery");
    m_iconBtn->setIcon(icon);
    m_iconBtn->setIconSize(QSize(32,32));
    leftAreaLayout->addWidget(m_iconBtn, 0, Qt::AlignLeading | Qt::AlignVCenter);
    m_iconArea->show();
    m_iconArea->setFixedSize(m_leftNavView->width(), 50);
    m_iconArea->setAttribute(Qt::WA_TranslucentBackground);

    QVBoxLayout *leftLayout = new QVBoxLayout;
    leftLayout->setContentsMargins(0, 0, 0, 0);
    leftLayout->setSpacing(0);
    leftLayout->addWidget(m_iconArea);
    leftLayout->addWidget(m_leftNavView);
    m_leftNavFrame->setLayout(leftLayout);
    m_leftNavFrame->setFixedWidth(m_leftNavView->width());
    m_leftNavFrame->setFixedHeight(650);

    m_rightAreaFrame = new QFrame(this);
    m_rightAreaFrame->setFrameShape(QFrame::NoFrame);
    m_rightAreaFrame->setAutoFillBackground(true);
    m_rightAreaFrame->setMinimumWidth(this->width()- m_leftNavView->width());

    m_rightLayout = new QVBoxLayout;
    m_rightLayout->setContentsMargins(0, 0, 0, 0);
    m_rightLayout->setSpacing(0);
    m_rightLayout->addWidget(titleBar);

    m_hSeparator = new DHorizontalLine(this);
    m_hSeparator->setVisible(true);
    m_hSeparator->setAutoFillBackground(true);
    m_hSeparator->setFixedHeight(1);
    m_rightLayout->addWidget(m_hSeparator);

    m_splitter = new QSplitter(Qt::Orientation::Horizontal,this);
    m_splitter->setChildrenCollapsible(false);
    m_splitter->setHandleWidth(0);
    m_splitter->setContentsMargins(0, 0, 0, 0);
    m_splitter->addWidget(m_leftNavFrame);

    m_centralView = new QFrame(this);

    m_centralLayout = new QHBoxLayout();
    m_rightView = new QFrame(this);
    m_rightView->setLayout(m_centralLayout);
    m_rightView->setFrameShape(QFrame::NoFrame);
    m_rightView->setAccessibleName("contentWidget_rightWidget");
    m_rightView->setContentsMargins(0, 0, 0, 0);
    m_rightView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    m_rightLayout->addWidget(m_rightView);
    m_rightAreaFrame->setLayout(m_rightLayout);
    m_splitter->addWidget(m_rightAreaFrame);

    m_navModel = new QStandardItemModel(m_leftNavView);
    m_leftNavView->setModel(m_navModel);

    QVBoxLayout *mainLayout = new QVBoxLayout();
    mainLayout->setSpacing(0);
    mainLayout->setContentsMargins(0, 0, 0, 0);
    mainLayout->addWidget(m_splitter);
    m_centralView->setLayout(mainLayout);
    setCentralWidget(m_centralView);

    updateTheme();
}

void MainWindowSnipe::initUI()
{
#if 0
    setAttribute(Qt::WA_TranslucentBackground);
    setAttribute(Qt::WA_OpaquePaintEvent);

    QWidget *centralWidget = new QWidget(this);
    centralWidget->setAccessibleName("CentralWidget");
    //DPalette palette = DPaletteHelper::instance()->palette(centralWidget);
    //palette.setColor(QPalette::Window, Qt::white);
    //DPaletteHelper::instance()->setPalette(centralWidget, palette);
    centralWidget->setAutoFillBackground(true);
//    setCentralWidget(centralWidget);

    //标题栏
    DTitlebar *titleBar = this->titlebar();
  //  titleBar->setIcon(QIcon::fromTheme("uos-recovery"));
    titleBar->setAccessibleName(MainWindowSnipeTitleBar);

    auto menu = titleBar->menu();
    if (!menu) {
        menu = new QMenu(this);
    }
    titleBar->setMenu(menu);

    //操作日志
    auto logAction = new QAction(tr("Logs"), this);
    menu->addAction(logAction);
    connect(logAction, &QAction::triggered, this, &MainWindowSnipe::showLogDialog);

    m_mainLayout = new QHBoxLayout(centralWidget);
    m_mainLayout->setSpacing(0);
    m_mainLayout->setContentsMargins(0, 0, 0, 0);

    m_leftNavView->setFixedWidth(188);
    m_leftNavView->setItemSize(QSize(80, 80));
    m_leftNavView->setItemSpacing(0);
    m_leftNavView->setSpacing(50);
    m_leftNavView->setIconSize(QSize(80, 80));
    m_leftNavView->setFrameShape(QFrame::Shape::NoFrame);
    m_leftNavView->setEditTriggers(QListView::NoEditTriggers);
    m_leftNavView->setAutoScroll(true); //滚动条
    m_leftNavView->setTabKeyNavigation(false); //tab按键是否有效
    m_leftNavView->setViewportMargins(QMargins(-30, 10, 10, 0)); //滚动区域边框大小
    m_leftNavView->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
    m_leftNavView->setSelectionMode(QAbstractItemView::SingleSelection);
    m_leftNavView->setAutoFillBackground(true);
    m_leftNavView->setBackgroundType(DStyledItemDelegate::BackgroundType(DStyledItemDelegate::RoundedBackground | DStyledItemDelegate::NoNormalState));
  //  QPalette leftNavWidgetPalette;
 //   leftNavWidgetPalette.setColor(QPalette::BrightText, QColor(qRgba(0,0,0,0.8)));
  //  m_leftNavWidget->setPalette(leftNavWidgetPalette);
    m_mainLayout->addWidget(m_leftNavView, 0);
    //m_leftNavWidget->hide();

  //  m_separator->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
//    m_separator->setFixedWidth(1);
    m_separator->setLineWidth(1);
    m_separator->setVisible(true);
    m_separator->setAutoFillBackground(true);
  //  Dtk::Widget::DAnchorsBase::setAnchor(m_separator, Qt::AnchorRight, m_leftNavWidget, Qt::AnchorRight);
    //m_separator->hide();

    m_rightWidget->setAccessibleName("CentralWidgetChildWidget");
    QStackedLayout *layout = new QStackedLayout(m_rightWidget);
    layout->setContentsMargins(0, 0, 0, 0);
    layout->setStackingMode(QStackedLayout::StackAll);
//    m_hoverWidget = new MainWindowHoverWidget(m_rightWidget);
//    layout->addWidget(m_hoverWidget);
     //m_mainLayout->addWidget(m_rightWidget, 1);

    m_centralLayout = new QHBoxLayout;

    m_rightView = new DBackgroundGroup(m_centralLayout);
    m_rightView->setAccessibleName("contentWidget_rightWidget");
    m_rightView->setItemSpacing(2);
    m_rightView->setItemMargins(QMargins(0, 0, 0, 0));
    m_rightView->setContentsMargins(0, 0, 0, 0);
    m_rightView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    m_mainLayout->addWidget(m_rightView);

    m_navModel = new QStandardItemModel(m_leftNavView);
    m_leftNavView->setModel(m_navModel);
    // 连接按下信号与窗口切换槽函数
    //connect(m_leftNavView, &DListView::pressed, this, &MainWindow::onFirstItemClick);
#endif
}

void MainWindowSnipe::initAllModule()
{
    bool isInLiveCD = Common::isLiveCD();
    if (isInLiveCD) {
        DDialog dialog(this);
        dialog.setMessage(tr("The current environment is live system, can not use backup and restore tools."));
        dialog.addButton(tr("Cancel", "button"));
        dialog.setIcon(QIcon::fromTheme("dialog-warning"));
        QRect rect = geometry();
        dialog.move(rect.center());
        dialog.moveToCenter();

        int result = dialog.addButton(tr("Exit", "button"), true, DDialog::ButtonWarning);
        dialog.setAccessibleName("MainWindow_liveCDDialog");
        dialog.getButton(0)->setAccessibleName("MainWindow_liveCDDialogCancel");
        dialog.getButton(1)->setAccessibleName("MainWindow_liveCDDialogExit");
        int errCode = dialog.exec();
        if (errCode == result || -1 == errCode || 0 == errCode) {
            QApplication::exit(0);
        }
        QApplication::quit();
        return;
    }

    const QString RecoveryServiceName = "com.deepin.uosrecovery";
    const QString RecoveryServicePath = "/com/deepin/uosrecovery";

    m_interface = new ComDeepinDaemonUosrecoveryInterface(
            RecoveryServiceName,
            RecoveryServicePath,
            QDBusConnection::systemBus());
    m_interface->setTimeout(600000);

    //必须要获取rootUUID, 如果rootUUID为空则说明运行于live系统中，需要用户指定根分区
    auto rootReply = m_interface->GetRootUUID();
    rootReply.waitForFinished();
    if (!rootReply.isValid()) {
        qCritical() << Q_FUNC_INFO << rootReply.error()<<", exit now !";
        QApplication::exit(0);
        QApplication::quit();
        return;
    }
    m_rootUUID = rootReply.value();
    if (m_rootUUID.isEmpty()) {
        DDialog dialog(this);
        dialog.setMessage(tr("It is not recommended to run this tool in the live system"));
        dialog.addButton(tr("Cancel", "button"));
        dialog.setIcon(QIcon::fromTheme("dialog-warning"));
        QRect rect = geometry();
        dialog.move(rect.center());
        dialog.moveToCenter();

        int result = dialog.addButton(tr("Exit", "button"), true, DDialog::ButtonWarning);
        dialog.setAccessibleName("MainWindow_liveSysDialog");
        dialog.getButton(0)->setAccessibleName("MainWindow_liveSysDialogCancel");
        dialog.getButton(1)->setAccessibleName("MainWindow_liveSysDialogExit");
        if (dialog.exec() == result) {
            QApplication::exit(0);
        }
        QApplication::quit();
        return;
    }

    auto currDestReply = m_interface->GetBackupDeviceUUID(m_rootUUID);
    currDestReply.waitForFinished();
    if (!currDestReply.isValid()) {
        qCritical() << Q_FUNC_INFO << "GetBackupDeviceUUID failed!, error:"<<currDestReply.error();
        return;
    }
    m_destUUID = currDestReply.value();

    ErrorCode retCode = initRecoveryType();
    if (retCode != ErrorCode::OK && !m_isImmutable) {
        qCritical() << Q_FUNC_INFO << ", initRecoveryType failed, retCode = " << retCode;
        DDialog dialog(this);
        dialog.setMessage(tr("This app does not work for your system, as it only supports ext4, btrfs and xfs file systems."));
        dialog.setIcon(QIcon::fromTheme("dialog-warning"));
        QRect rect = geometry();
        dialog.move(rect.center());
        dialog.moveToCenter();

        int result = dialog.addButton(tr("Exit", "button"), true, DDialog::ButtonWarning);
        dialog.setAccessibleName("MainWindow_appNotSupportDialog");
        dialog.getButton(0)->setAccessibleName("MainWindow_appNotSupportDialogCancel");
        dialog.getButton(1)->setAccessibleName("MainWindow_appNotSupportDialogExit");
        int errCode = dialog.exec();
        if (errCode == result || -1 == errCode) {
            QApplication::exit(0);
        }
        return;
    }

    const int selinuxEnforcing = 1;
    int selinuxMode = -1;
    int seRetCode = selinux_getenforcemode(&selinuxMode);
    if (is_selinux_enabled() && (0 == seRetCode && selinuxEnforcing == selinuxMode)) {
        m_isSelinuxEnabled = true;
    }

    QSettings settings("/usr/lib/deepin/desktop-version", QSettings::IniFormat);
    settings.beginGroup("Release");
    const QString &osType = settings.value("Type", "Professional").toString();
    settings.endGroup();
    if ("Device" == osType) {
        m_isDevice = true;
    }

    QString fstabFile = "/etc/fstab";
    FSTabInfoList fstabList = FSTab::getFSTabFromFile(fstabFile);
    QStringList sysDeviceUuidList = FSTab::getUuidListFromFstab(fstabList);
    DeviceInfoList fileCryptDevList;
    m_isLVMOnly = Device::isLVM(sysDeviceUuidList, m_isEncrypted, m_isFileMgrEncrypted, fileCryptDevList);
    m_isSupportV20BackupRestore = Common::isSupportV20BackupAndRestore();

    m_backupModule = new ImmuBackupModule(this, m_interface);
    m_backupModule->setDevice(m_isDevice);
    m_backupModule->setSelinuxEnable(m_isSelinuxEnabled);
    m_backupModule->setEncrypted(m_isEncrypted);
    m_backupModule->setLVM(m_isLVMOnly);
    m_backupModule->setSupportV20BackupRestore(m_isSupportV20BackupRestore);
    m_backupModule->setFileMgrEncrypted(m_isFileMgrEncrypted);
    m_backupModule->setMajorVersion(m_osMajorVer);
    m_backupModule->setMinorVersion(m_osMinorVer);
    m_backupModule->setSystemSyncType(m_systemSyncType);
    m_backupModule->setUserDataSyncType(m_userDataSyncType);
    m_backupModule->setImmutable(m_isImmutable);
    m_backupModule->initialize();

    m_restoreModule = new ImmuRestoreModule(this, m_interface);
    m_restoreModule->setDevice(m_isDevice);
    m_restoreModule->setSelinuxEnable(m_isSelinuxEnabled);
    m_restoreModule->setEncrypted(m_isEncrypted);
    m_restoreModule->setLVM(m_isLVMOnly);
    m_restoreModule->setFileMgrEncrypted(m_isFileMgrEncrypted);
    m_restoreModule->setMajorVersion(m_osMajorVer);
    m_restoreModule->setMinorVersion(m_osMinorVer);
    m_restoreModule->setSystemSyncType(m_systemSyncType);
    m_restoreModule->setUserDataSyncType(m_userDataSyncType);
    m_restoreModule->initialize();

    m_factoryRestoreModule = new ImmuFactoryRestoreModule(this, m_interface);
    m_factoryRestoreModule->initialize();

    m_modules.append(m_backupModule);
    m_modules.append(m_restoreModule);
    m_modules.append(m_factoryRestoreModule);

    QStringList titles = {
            tr("Backup"),
            tr("Restore"),
            tr("Reset to factory settings"),
    };
    m_iconUnselectedList << ":/resources/icons/v25/backup_unselected.svg"
                         << ":/resources/icons/v25/restore_unselected.svg"
                         << ":/resources/icons/v25/init_unselected.svg";

    m_iconSelectedList << ":/resources/icons/v25/backup_selected.svg"
                       << ":/resources/icons/v25/restore_selected.svg"
                       << ":/resources/icons/v25/init_selected.svg";
    Q_ASSERT(titles.size() == m_iconUnselectedList.size());

    QStringList description = {
            tr("Back up the partitions and directories that store system files, to resist system breakdown."),
            tr("Specify files and directories to back up, so as to avoid data loss or damage."),
            tr("One click clone the system and data, and can be installed to other device.")
    };

    const int ITEM_FRAME_HEIGHT = 116;
    const int ITEM_FRAME_WIDTH = 116;
    const int ITEM_FRAME_HEIGHT_VERTICAL_LAYOUT = 85;
    const int ITEM_FRAME_WIDTH_VERTICAL_LAYOUT = 600;

    for (int i = 0; i < titles.size(); i++) {
        auto *item = new QStandardItem;
        if (titles.at(i) == tr("Restore")) {
            item->setAccessibleText("uos_Restore");
        } else if (titles.at(i) == tr("Backup")) {
            item->setAccessibleText("uos_Backup");
        } else if (titles.at(i) == tr("Reset to factory settings")) {
            item->setAccessibleText("uos_ResetToFactorySettings");
        }
        m_navModel->appendRow(item);
        ImmuBackupLeftFrame *itemFrame = new ImmuBackupLeftFrame(titles.at(i), "", m_iconUnselectedList.at(i), m_leftNavView);
        itemFrame->setFrameShape(QFrame::NoFrame);
        int uiLayout = UI::UI_LAYOUT_BACKUP_HORIZONTAL;
        itemFrame->setLayoutStype(uiLayout);
        if (UI::UI_LAYOUT_BACKUP_HORIZONTAL == uiLayout) {
            itemFrame->setFixedSize(ITEM_FRAME_WIDTH, ITEM_FRAME_HEIGHT);
            itemFrame->setIconPixmap(m_iconUnselectedList.at(i), QSize(80, 80));
            itemFrame->setSelectedPixmap(":/resources/icons/v25/selected_boarder.svg", QSize(85, 100));
            itemFrame->setSelectedHoverPixmap(":/resources/icons/v25/selected_boarder_hover.svg", QSize(85, 100));
            itemFrame->setSelectedDarkPixmap(":/resources/icons/v25/selected_boarder_dark.svg", QSize(85, 100));
            itemFrame->setSelectedDarkHoverPixmap(":/resources/icons/v25/selected_boarder_dark_hover.svg", QSize(85, 100));
        } else if (UI::UI_LAYOUT_BACKUP_VERTICAL == uiLayout) {
            itemFrame->setFixedSize(ITEM_FRAME_WIDTH_VERTICAL_LAYOUT, ITEM_FRAME_HEIGHT_VERTICAL_LAYOUT);
            itemFrame->setIconPixmap(m_iconUnselectedList.at(i), QSize(56, 56));
            itemFrame->setSelectedPixmap(":/resources/icons/v25/selected_boarder.svg", QSize(61, 76));
            itemFrame->setSelectedHoverPixmap(":/resources/icons/v25/selected_boarder_hover.svg", QSize(61, 76));
            itemFrame->setSelectedDarkPixmap(":/resources/icons/v25/selected_boarder_dark.svg", QSize(61, 76));
            itemFrame->setSelectedDarkHoverPixmap(":/resources/icons/v25/selected_boarder_dark_hover.svg", QSize(61, 76));
        }
        itemFrame->initLayout();
        m_leftNavView->setIndexWidget(m_navModel->index(i, 0), itemFrame);
        connect(itemFrame, &ImmuBackupLeftFrame::clicked, this, &MainWindowSnipe::onItemChanged);
    }

    if (!m_modules.isEmpty()) {
        m_modules.first()->active();
        auto item = dynamic_cast<ItemFrame *>(m_leftNavView->indexWidget(m_navModel->index(0, 0)));
        item->setIconPixmap(m_iconSelectedList.at(0), QSize(80, 80));
        item->setCheckState(false);
        item->setSelected(true);
        item->setSelectedBackground("selected");
    }

    connect(m_restoreModule, &ImmuRestoreModule::notifyShowBackupPage, this, &MainWindowSnipe::ShowBackupPage);
}

ErrorCode MainWindowSnipe::initRecoveryType()
{
    if (m_interface == nullptr) {
        qCritical() << Q_FUNC_INFO << ", m_interface is null";
        return ErrorCode::NullPointer;
    }

    auto initReply = m_interface->AutoInitSystemRecoveryType(m_rootUUID);
    initReply.waitForFinished();
    if (!initReply.isValid()) {
        qCritical() << Q_FUNC_INFO << initReply.error();
        return ErrorCode::DbusError;
    }

    int retCode = initReply.value();
    if (retCode != static_cast<int> (ErrorCode::OK)) {
        qCritical() << Q_FUNC_INFO << "AutoInitSystemRecoveryType failed, retCode = " << retCode;
        return static_cast<ErrorCode> (retCode);
    }

    auto systemSyncTypeReply = m_interface->GetSystemSyncType();
    systemSyncTypeReply.waitForFinished();
    if (!systemSyncTypeReply.isValid()) {
        qCritical() << Q_FUNC_INFO << ", GetSystemSyncType failed: "<< systemSyncTypeReply.error();
        return ErrorCode::DbusError;
    }

    m_systemSyncType = systemSyncTypeReply.value();

    auto userDataSyncTypeReply = m_interface->GetUserDataSyncType();
    userDataSyncTypeReply.waitForFinished();
    if (!userDataSyncTypeReply.isValid()) {
        qCritical() << Q_FUNC_INFO << ", GetUserDataSyncType failed: "<< userDataSyncTypeReply.error();
        return ErrorCode::DbusError;
    }
    m_userDataSyncType = userDataSyncTypeReply.value();

    return ErrorCode::OK;
}

void MainWindowSnipe::onItemChanged(bool checked)
{
    int moduleSize = m_modules.size();
    if (checked) {
        auto *itemFrame = dynamic_cast<ItemFrame *>(sender());
        int rowCount = m_navModel->rowCount();
        for (int i = 0; i < rowCount; ++i) {
            auto item = dynamic_cast<ItemFrame *>(m_leftNavView->indexWidget(m_navModel->index(i, 0)));
            if (itemFrame == item) {
                item->setIconPixmap(m_iconSelectedList.at(i), QSize(80, 80));
                item->setSelectedBackground("selected");
                item->setSelected(true);
                if (i < moduleSize) {
                    m_modules.at(i)->updateData();
                    m_modules.at(i)->active();
                }
            } else {
                item->setIconPixmap(m_iconUnselectedList.at(i), QSize(80, 80));
                item->setSelectedBackground("unselected");
                item->setSelected(false);
            }
            item->setCheckState(false);
        }
    }
}

void MainWindowSnipe::pushWidget(ModuleInterface *const inter, QWidget *const w)
{
    m_contentStack.push({inter, w});
    if (m_contentStack.size() >= 2) {
        m_backwardBtn->show();
    } else {
        m_backwardBtn->hide();
    }
}

// 将窗口弹出出显示栈
void MainWindowSnipe::popWidget()
{
    if (!m_contentStack.isEmpty()) {
        auto content = m_contentStack.pop();
        m_centralLayout->removeWidget(content.second);
        content.second->hide();
    }

    if (m_contentStack.size() < 2) {
        m_backwardBtn->hide();
    }
}

void MainWindowSnipe::popAllWidget()
{
    while (!m_contentStack.isEmpty()) {
        auto content = m_contentStack.pop();
        m_centralLayout->removeWidget(content.second);
        content.second->hide();
    }
}

// 将窗口弹出出显示栈并删除对象
void MainWindowSnipe::popWidgetAndDelete()
{
    if (!m_contentStack.isEmpty()) {
        auto content = m_contentStack.pop();
        m_centralLayout->removeWidget(content.second);
        content.second->hide();
        content.second->deleteLater();
    }
}

// 显示上一步窗口
void MainWindowSnipe::back()
{
    onBackWardClick();
}

void MainWindowSnipe::onBackWardClick()
{
    if (m_contentStack.size() < 2) {
        return;
    }

    auto curWidget = m_contentStack.top().second;
    if (nullptr != curWidget) {
        QString accDes = curWidget->accessibleDescription();
        if (accDes == "ResultWidget") {
            this->backHome();
            return;
        }
    }

    popWidget();
    auto topModule = m_contentStack.top().first;
//    if (topModule->name() == "BackupModule") {
//        m_buttonBox->button(BACKUP_BUTTON_ID)->setChecked(true);
//    } else if (topModule->name() == "RestoreModule") {
//        m_buttonBox->button(RESTORE_BUTTON_ID)->setChecked(true);
//    } else {
//        m_buttonBox->button(ADVANCED_BUTTON_ID)->setChecked(true);
//    }

    auto topWidget = m_contentStack.top().second;
    if (topWidget != nullptr) {
        m_centralLayout->addWidget(m_contentStack.top().second);
        topWidget->setFocus();
        topWidget->show();
    }
}

// 回退到主页
void MainWindowSnipe::backHome()
{
    while (!m_contentStack.isEmpty()) {
        auto content = m_contentStack.pop();
        if (m_contentStack.isEmpty()) {
            m_contentStack.push(content);
            m_centralLayout->addWidget(content.second);
            content.second->show();
            content.second->setFocus();
            m_backwardBtn->hide();
            break;
        } else {
            m_centralLayout->removeWidget(content.second);
            content.second->hide();
        }
    }
}

// 返回按钮使能
void MainWindowSnipe::enableBackWard(bool enable)
{
    m_backwardBtn->setEnabled(enable);
    m_backwardBtn->setVisible(enable);
}

// 模块使能
void MainWindowSnipe::enableModule(bool enable)
{
    m_leftNavView->setEnabled(enable);
}

// 设置模块可见
void MainWindowSnipe::setModuleVisible(ModuleInterface *const inter, const bool visible)
{

}

// 设置当前显示模块
void MainWindowSnipe::setCurrentWidget(ModuleInterface *const inter, QWidget *const w)
{
    if (!m_contentStack.isEmpty()) {
        m_centralLayout->removeWidget(m_contentStack.top().second);
        m_contentStack.top().second->hide();
    }
    pushWidget(inter, w);
    m_centralLayout->addWidget(w);
    w->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    w->show();
    w->setFocus();
}

// 获取当前显示栈的索引
ModuleInterface *MainWindowSnipe::getCurrentModule()
{
    return nullptr;
}

void MainWindowSnipe::setMenuDisabled(bool disabled)
{
    DTitlebar *titleBar = this->titlebar();
    if (nullptr != titleBar) {
        titleBar->setMenuDisabled(disabled);
    }
}

void MainWindowSnipe::setQuitMenuDisabled(bool disabled)
{
    DTitlebar *titleBar = this->titlebar();
    if (nullptr != titleBar) {
        titleBar->setQuitMenuDisabled(disabled);
    }
}

void MainWindowSnipe::setMenuActionEnabled(const QString &actionText, bool enabled)
{
    DTitlebar *titleBar = this->titlebar();
    if (nullptr != titleBar) {
        QList<QAction*> actionList = titleBar->menu()->actions();
        auto itAction = std::find_if(actionList.begin(), actionList.end(), [=](const QAction *action) {
            return (actionText == action->text());
        });
        if (itAction != actionList.end()) {
            (*itAction)->setEnabled(enabled);
        }
    }
}

void MainWindowSnipe::setWindowFuncClose(bool enabled)
{
    DWindowManagerHelper::instance()->setMotifFunctions(windowHandle(), DWindowManagerHelper::FUNC_CLOSE, enabled);
    DTitlebar *titleBar = this->titlebar();
    if (nullptr != titleBar) {
        if (enabled) {
            auto flags = windowFlags();
            auto newFlags = flags &~ Qt::WindowCloseButtonHint &~ Qt::WindowMinimizeButtonHint;
            titleBar->setDisableFlags(newFlags);
        } else {
            titleBar->setDisableFlags(Qt::WindowCloseButtonHint);
        }
    }
}

void MainWindowSnipe::showSettingDialog()
{

}

void MainWindowSnipe::showLogDialog()
{
    if (m_logDialog == nullptr) {
        m_logDialog = new LogDialog();
    } else {
        m_logDialog->activateWindow();
        m_logDialog->raise();
    }

    QString curUserName = Utils::getUserName();
    bool isAdmin = Utils::isAdminUser(curUserName);
    QJsonObject request;
    OperateLogQuery query;
    if (isAdmin) {
        query.mask = 0;
    } else {
        query.mask = 0x08;
    }
    query.username = curUserName;
    query.orderByTimeDesc = true; // 日志默认按照时间排序显示
    //request = query.marshal();
    auto logReply = m_interface->ListOperateLogs(query);
    logReply.waitForFinished();
    if (!logReply.isValid()) {
        qCritical() << logReply.error();
        return;
    }

    OperateLogList operateLogList;
    QJsonObject jsonRoot = Utils::QStringToJson(logReply.value());
    QJsonArray logsObject = jsonRoot.value("logs").toArray();
    for (auto jsonObject : logsObject) {
        OperateLog operateLog;
        operateLog.unmarshal(jsonObject.toObject());
        operateLogList.append(operateLog);
    }
    m_logDialog->setData(operateLogList);
    m_logDialog->showToCenter();
}

void MainWindowSnipe::showBackupFileManagerDialog()
{

}

void MainWindowSnipe::navModuleClicked(int index)
{
    int moduleSize = m_modules.size();
    int rowCount = m_navModel->rowCount();
    if (index >= moduleSize) {
        return;
    }

    for (int i = 0; i < rowCount; ++i) {
        auto item = dynamic_cast<ItemFrame *>(m_leftNavView->indexWidget(m_navModel->index(i, 0)));
        if (index == i) {
            item->setIconPixmap(m_iconSelectedList.at(i), QSize(80, 80));
            item->setSelectedBackground("selected");
            item->setSelected(true);
            if (i < moduleSize) {
                m_modules.at(i)->active();
            }
        } else {
            item->setIconPixmap(m_iconUnselectedList.at(i), QSize(80, 80));
            item->setSelectedBackground("unselected");
            item->setSelected(false);
        }
    }
}

void MainWindowSnipe::ShowNewBackupPage()
{
    this->ShowBackupPage();
}

void MainWindowSnipe::ShowNewRestorePage()
{
    this->ShowRestorePage();
}

void MainWindowSnipe::ShowNewFactoryRestorePage()
{
    this->ShowFactoryRestorePage();
}

void MainWindowSnipe::ShowBackupPage()
{
    if (m_modules.isEmpty()) {
        return;
    }

    bool isRun = m_interface->IsRunning();
    if (!isRun) {
        auto module = m_modules.at(IMMU_BACKUP_MODULE_ID);
        if (nullptr != module) {
            module->active();
        }

        this->navModuleClicked(IMMU_BACKUP_MODULE_ID);
    }

    this->raise();
    if (this->isMinimized() || !this->isVisible()) {
        this->showNormal();
    }
    this->activateWindow();
}

void MainWindowSnipe::ShowRestorePage()
{
    if (m_modules.isEmpty()) {
        return;
    }

    bool isRun = m_interface->IsRunning();
    if (!isRun) {
        auto module = m_modules.at(IMMU_RESTORE_MODULE_ID);
        if (nullptr != module) {
            module->active();
        }

        this->navModuleClicked(IMMU_RESTORE_MODULE_ID);
    }

    this->raise();
    if (this->isMinimized() || !this->isVisible()) {
        this->showNormal();
    }
    this->activateWindow();
}

void MainWindowSnipe::ShowFactoryRestorePage()
{
    if (m_modules.isEmpty()) {
        return;
    }

    bool isRun = m_interface->IsRunning();
    if (!isRun) {
        auto module = m_modules.at(IMMU_FACTORY_RESTORE_MODULE_ID);
        if (nullptr != module) {
            module->active();
        }

        this->navModuleClicked(IMMU_FACTORY_RESTORE_MODULE_ID);
    }

    this->raise();
    if (this->isMinimized() || !this->isVisible()) {
        this->showNormal();
    }
    this->activateWindow();
}
