//
// Created by uos on 2022/3/16.
//

#include "RestoreWidget.h"
#include "common/ItemFrame.h"
#include "utils/Utils.h"
#include <QVBoxLayout>
#include <QScrollBar>
#include <QDebug>

enum OptType {
    SystemRestore = 0,  //系统还原
    DataRestore,        //数据还原
    InitializeRestore,  //初始化还原（恢复出厂设置）
    OtherRestore        //其他还原（兼容v20备份文件）
};

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

RestoreWidget::RestoreWidget(DWidget *parent)
{
    this->setAccessibleName("uosRestore_RestoreWidget");
    m_bDirectionRTL = Utils::isDirectionRTL();
    // 主题变换
    m_guiHelper = Dtk::Gui::DGuiApplicationHelper::instance();
    connect(m_guiHelper, &Dtk::Gui::DGuiApplicationHelper::themeTypeChanged, this, &RestoreWidget::onThemeChange);
    // 初始化UI
    initUI();
}

int RestoreWidget::getRestoreUiLayoutType()
{
    int defaultLayout = Utils::getUILayoutType(UI::UI_RESTORE_MODULE);
    if (-1 == defaultLayout) {
        qCritical()<<"getRestoreUiLayoutType failed";
    }
    return defaultLayout;
}

void RestoreWidget::uiHorizontalLayout()
{
    m_restoreView->setViewportMargins(QMargins(0, 0, 0, 0));
    m_restoreView->setViewMode(QListView::IconMode);

    // 不可以拖拽
    m_restoreView->setDragEnabled(false);
    m_restoreView->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
    m_restoreView->setSpacing(10);
    // 每个对象大小
    m_restoreView->setItemSize(QSize(ITEM_FRAME_WIDTH, ITEM_FRAME_HEIGHT));

    m_restoreView->setTextElideMode(Qt::ElideRight);
    m_restoreView->setBackgroundType(DStyledItemDelegate::RoundedBackground);
}

void RestoreWidget::uiVerticalLayout()
{
    m_restoreView->setViewportMargins(QMargins(0, 0, 0, 0));
    m_restoreView->setViewMode(QListView::IconMode);

    // 不可以拖拽
    m_restoreView->setDragEnabled(false);
    // m_restoreView->verticalScrollBar()->setContextMenuPolicy(Qt::NoContextMenu);
    m_restoreView->verticalScrollBar()->setEnabled(false);
    m_restoreView->horizontalScrollBar()->setEnabled(false);
    m_restoreView->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
    m_restoreView->setSpacing(10);
    // 每个对象大小
    m_restoreView->setItemSize(QSize(ITEM_FRAME_WIDTH_VERTICAL_LAYOUT, ITEM_FRAME_HEIGHT_VERTICAL_LAYOUT));

    m_restoreView->setTextElideMode(Qt::ElideRight);
    m_restoreView->setBackgroundType(DStyledItemDelegate::RoundedBackground);
}

void RestoreWidget::initHelpLayout()
{
    m_helpLabel = new QLabel;
    m_helpLabel->setAccessibleName("uosRestore_HelpLabel");
    m_helpLabel->installEventFilter(this);
    Dtk::Gui::DGuiApplicationHelper::ColorType themeType =  Dtk::Gui::DGuiApplicationHelper::instance()->themeType();
    m_helpLabel->setPixmap(HelpDialog::getPixMapByThemeType(themeType));
    m_helpLabel->setFixedSize(20, 20);
}

void RestoreWidget::startCalculateTip(bool start, const QString &tipInfo)
{
    if (start) {
        m_calculateTip->start();
        m_calculateTip->show();
        m_restoreView->setEnabled(false);
        m_nextBtn->setEnabled(false);

        m_errorInfoLabel->setText(tipInfo);
        QLabel styleLabel;
        m_errorInfoLabel->setStyleSheet(styleLabel.styleSheet());
        m_errorInfoLabel->show();

    } else {
        m_calculateTip->hide();
        m_calculateTip->stop();
        m_restoreView->setEnabled(true);
        m_nextBtn->setEnabled(true);

        m_errorInfoLabel->setStyleSheet("QLabel {"
                                        "color: #FF0000;"
                                        "border: none;"
                                        "background-color: transparent;"
                                        "}");
        if (tipInfo.isEmpty()) {
            m_errorInfoLabel->setText("");
            m_errorInfoLabel->hide();
        } else {
            m_errorInfoLabel->setText(tipInfo);
            m_errorInfoLabel->show();
        }

    }
}

void RestoreWidget::setErrorInfo(const QString &tipInfo)
{
    m_errorInfoLabel->setStyleSheet("QLabel {"
                                    "color: #FF0000;"
                                    "border: none;"
                                    "background-color: transparent;"
                                    "}");
    m_errorInfoLabel->setText(tipInfo);
    m_errorInfoLabel->show();
}

void RestoreWidget::initUI()
{
    int uiLayout = this->getRestoreUiLayoutType();
    QString osEditionType = Utils::getOSEditionType();
    //垂直布局
    QVBoxLayout *verticalLayout = new QVBoxLayout(this);
    if (UI::UI_LAYOUT_RESTORE_HORIZONTAL == uiLayout) {
        verticalLayout->setContentsMargins(0, 20, 0, 10);
    } else if (UI::UI_LAYOUT_RESTORE_VERTICAL == uiLayout) {
        verticalLayout->setContentsMargins(0, 50, 0, 5);
    }

    m_title = new DLabel(this);
    m_title->setText(tr("Choose a way to restore data"));
    m_title->setAccessibleName("uosRestore_RestoreChooseTitle");
    m_title->setAlignment(Qt::AlignCenter);
    m_title->setFixedHeight(35);
    DFontSizeManager::instance()->bind(m_title, DFontSizeManager::T6);
    QFont font = m_title->font();
    font.setWeight(QFont::Medium);
    m_title->setFont(font);
    QPalette titlePalette;
    titlePalette.setColor(QPalette::BrightText, QColor(qRgba(0,0,0,0.7)));
    m_title->setPalette(titlePalette);
    verticalLayout->addWidget(m_title, 0, Qt::AlignHCenter);

    m_restoreView = new DListView(this);
    m_restoreView->setAccessibleName("uosRestore_RestoreListView");
    m_model = new QStandardItemModel(m_restoreView);
    m_restoreView->setModel(m_model);

    if (UI::UI_LAYOUT_RESTORE_HORIZONTAL == uiLayout) {
        verticalLayout->addSpacing(50);
        if (m_bDirectionRTL) {
            m_restoreView->setFixedSize(550, 600);
            verticalLayout->addWidget(m_restoreView, 0, Qt::AlignHCenter);
        } else {
            verticalLayout->addWidget(m_restoreView);
        }
    } else if (UI::UI_LAYOUT_RESTORE_VERTICAL == uiLayout) {
        verticalLayout->addSpacing(8);
        if (m_bDirectionRTL) {
            m_restoreView->setFixedSize(600, 500);
            verticalLayout->addWidget(m_restoreView, 0, Qt::AlignHCenter);
        } else {
            verticalLayout->addWidget(m_restoreView, Qt::AlignHCenter);
        }
        // verticalLayout->addSpacing(8);
    }

    m_restoreView->setFrameShape(QFrame::Shape::NoFrame);
    // 不能编辑触发
    m_restoreView->setEditTriggers(QListView::NoEditTriggers);
    // 不可以拖拽
//    m_restoreView->setDragEnabled(false);  // 不能在这里设置，还是可以拖出一个空白的出来，导致界面崩溃
    // 设置其他属性
    m_restoreView->clearSelection();
    m_restoreView->clearFocus();
    m_restoreView->clearMask();

    verticalLayout->addStretch();
    m_calculateTip = new DSpinner;
    m_calculateTip->setAccessibleName("uosRestore_DSpinner");
    m_calculateTip->hide();
    m_calculateTip->setFixedSize(16, 16);
    m_calculateTip->setFocusPolicy(Qt::NoFocus);
    m_errorInfoLabel = new DLabel;
    m_errorInfoLabel->setAccessibleName("uosRestore_ErrorInfoLabel");
    m_errorInfoLabel->hide();
    m_errorInfoLabel->setText(tr("Attention: Your current system will be restored. Please proceed carefully!"));
    m_errorInfoLabel->setStyleSheet("QLabel {"
                                    "color: #FF0000;"
                                    "border: none;"
                                    "background-color: transparent;"
                                    "}");

    QHBoxLayout *calculateTipLayout = new QHBoxLayout();
    // calculateTipLayout->setSpacing(10);
    calculateTipLayout->setContentsMargins(0,0,0,0);
    calculateTipLayout->addStretch();
    calculateTipLayout->addWidget(m_calculateTip);
    calculateTipLayout->addWidget(m_errorInfoLabel);
    calculateTipLayout->addStretch();
    QWidget *calculateTipWidget = new QWidget;
    calculateTipWidget->setFixedHeight(36);
    calculateTipWidget->setLayout(calculateTipLayout);
    verticalLayout->addWidget(calculateTipWidget, 0, Qt::AlignHCenter);

    m_nextBtn = new DPushButton;
    m_nextBtn->setText(tr("Next"));
    m_nextBtn->setAccessibleName("uosRestore_Next");
    m_nextBtn->setFixedSize(200, 36);
    m_nextBtn->setEnabled(false);

    QHBoxLayout *hBoxLayout = new QHBoxLayout;
    if (UI::UI_LAYOUT_RESTORE_HORIZONTAL == uiLayout) {
        this->uiHorizontalLayout();
        this->initHelpLayout();

        QLabel *leftLabel = new QLabel;
        leftLabel->setFixedSize(20, 20);
        leftLabel->setAccessibleName("uosRestore_LeftLabel");

        hBoxLayout->setContentsMargins(13, 0, 13, 0);
        hBoxLayout->addWidget(leftLabel, 0, Qt::AlignLeft);
        hBoxLayout->addWidget(m_nextBtn, Qt::AlignHCenter);
        hBoxLayout->addWidget(m_helpLabel, 0, Qt::AlignRight);

        initHelpDialog();
    } else if (UI::UI_LAYOUT_RESTORE_VERTICAL == uiLayout) {
        this->uiVerticalLayout();
        hBoxLayout->addWidget(m_nextBtn, Qt::AlignHCenter);
    }

    verticalLayout->addLayout(hBoxLayout);

    // 按钮  中间标题
    QStringList titles = {
            tr("System Restore"),
            tr("Data Restore"),
            tr("Reset to factory settings"),
            tr("Other Ways")
    };

    m_iconList =  QStringList({
            ":/resources/icons/system_restore.svg",
            ":/resources/icons/data_restore.svg",
            ":/resources/icons/factory_restore.svg",
            ":/resources/icons/other_restore.svg"
    });

    if ("Community" == osEditionType || !m_isSupportOtherWays) {
        titles.removeAll(tr("Other Ways"));
        m_iconList.removeAll(":/resources/icons/other_restore.svg");
    }

    Q_ASSERT(titles.size() == m_iconList.size());

    QStringList description = {
            tr("Restore your system from a restore point."),
            tr("Restore your data from a data backup."),
            tr("Restore your system to the initial installation state."),
            tr("Restore from the backup of UnionTech OS 20.")
    };

    for (int i = 0; i < titles.size(); i++) {
        auto *item = new QStandardItem;
        if (titles.at(i) == tr("System Restore")) {
            item->setAccessibleText("uos_SystemRestore");
        } else if (titles.at(i) == tr("Data Restore")) {
            item->setAccessibleText("uos_DataRestore");
        } else if (titles.at(i) == tr("Reset to factory settings")) {
            item->setAccessibleText("uos_ResetToFactorySettings");
        } else if (titles.at(i) == tr("Other Ways")) {
            item->setAccessibleText("uos_OtherWays");
        }
        m_model->appendRow(item);

        ItemFrame *itemFrame = new ItemFrame(titles.at(i), description.at(i), m_iconList.at(i), m_restoreView);
        itemFrame->setLayoutStype(uiLayout);
        if (UI::UI_LAYOUT_RESTORE_HORIZONTAL == uiLayout) {
            itemFrame->setFixedSize(ITEM_FRAME_WIDTH, ITEM_FRAME_HEIGHT);
            itemFrame->setIconPixmap(m_iconList.at(i), QSize(96, 96));
        } else if (UI::UI_LAYOUT_RESTORE_VERTICAL == uiLayout) {
            itemFrame->setFixedSize(ITEM_FRAME_WIDTH_VERTICAL_LAYOUT, ITEM_FRAME_HEIGHT_VERTICAL_LAYOUT);
            // UI 设计师已同意设置成下面的大小实际在界面展示出来的效果
            itemFrame->setIconPixmap(m_iconList.at(i), QSize(56, 56));
        }
        itemFrame->initLayout();
        m_restoreView->setIndexWidget(m_model->index(i, 0), itemFrame);
        m_restoreView->setSpacing(16); // 界面实际显示效果间隔大概是 14
        connect(itemFrame, &ItemFrame::clicked, this, &RestoreWidget::onItemChanged);
    }
    connect(m_nextBtn, &QPushButton::clicked, [=] {
        auto index = m_restoreView->currentIndex();
        if (!index.isValid()) {
            return;
        }
        if (nullptr != m_errorInfoLabel) {
            m_errorInfoLabel->setText("");
            m_errorInfoLabel->hide();
        }
        switch (static_cast<OptType>(index.row())) {
            case SystemRestore:
                Q_EMIT notifySystemRestore();
                break;
            case DataRestore:
                Q_EMIT notifyDataRestore();
                break;
            case InitializeRestore:
                Q_EMIT notifyInitializeRestore();
                break;
            case OtherRestore:
                Q_EMIT notifyOtherRestore();
                break;
            default:
                break;
        }
    });

    connect(this, &RestoreWidget::enter, this, [=] {
        QPoint point = m_helpLabel->mapToGlobal(QPoint());
        QPoint nextBtnPoint = m_nextBtn->mapToGlobal(QPoint());
        int x = point.x();
        int w = m_helpDialog->width();
        if (x > nextBtnPoint.x()) {
            x -= w;
        }
        m_helpDialog->move(x, point.y() - m_helpDialog->height() -10);
        m_helpDialog->raise();
        m_helpDialog->activateWindow();
        m_helpDialog->show();
    });

    connect(this, &RestoreWidget::leave, this, [=] {
        m_helpDialog->hide();
        if (!this->isActiveWindow()) {
            this->raise();
            this->activateWindow();
        }
    });
}

void RestoreWidget::initHelpDialog()
{
    m_helpDialog = new HelpDialog();
    m_helpDialog->setFixedSize(QSize(320,340));

    QList<QPair<QString, QString>> tipsList = {
            {tr("System Restore"),
             tr("Restore your system from a restore point.")
             },

            {tr("Data Restore"),
             tr("Restore your data from a data backup.")
             },

            {tr("Restore from Initial Backup"),
             tr("Restore your system to the initial installation state.")
             },

            {tr("Other Ways"),
             tr("Restore from the backup of UnionTech OS 20.")
            }
    };

    QList<HelpInfoItem> helpInfos;
    m_helpDialog->tipsPairList2HelpInfoItemList(tipsList, helpInfos);
    m_helpDialog->setContentText(helpInfos);
}

void RestoreWidget::onThemeChange(Dtk::Gui::DGuiApplicationHelper::ColorType themeType)
{
    if (nullptr != m_helpLabel) {
        m_helpLabel->setPixmap(HelpDialog::getPixMapByThemeType(themeType));
    }
}

void RestoreWidget::onItemChanged(bool checked)
{
    if (checked) {
        auto *itemFrame = dynamic_cast<ItemFrame *>(sender());
        int rowCount = m_model->rowCount();
        for (int i = 0; i < rowCount; ++i) {
            auto item = dynamic_cast<ItemFrame *>(m_restoreView->indexWidget(m_model->index(i, 0)));
            item->setCheckState(itemFrame == item);
        }
        m_nextBtn->setEnabled(checked);
    }
}

bool RestoreWidget::eventFilter(QObject* watched, QEvent* event)
{
    if (watched == m_helpLabel) {
        switch (event->type()) {
            case QEvent::Enter: {
                Q_EMIT enter();
                break;
            }
            case QEvent::Leave: {
                Q_EMIT leave();
                break;
            }
            default:
                break;
        }
    }

    return QWidget::eventFilter(watched, event);
}
