//
// Created by 张雪明 <zhangxueming@uniontech.com> on 2024/11/25.
//
#include "ImmuSystemBackupWidget.h"
#include "utils/Utils.h"
#include "utils/global.h"
#include <QVBoxLayout>
#include <DFontSizeManager>
#include <QGraphicsOpacityEffect>

SysBackupItemFrame::SysBackupItemFrame(const QString &title, const QString &titleDes, const QString &icon, QWidget *parent)
    : ImmuItemFrame(title, titleDes, icon, parent)
{
    setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
    setAttribute(Qt::WA_Hover,true);
    setObjectName("SysBackupItemFrame");
    setBackgroundRole(DPalette::NoType);
    setLineWidth(0);
}

SysBackupItemFrame::~SysBackupItemFrame()
{}

void SysBackupItemFrame::initUI()
{
    m_partitionPath = new DLabel(this);
    m_storeText = new DTipLabel();
    QFont storeTextFont = m_storeText->font();
    storeTextFont.setWeight(QFont::Normal);
    m_storeText->setFont(storeTextFont);
    DFontSizeManager::instance()->bind(m_storeText, DFontSizeManager::T8);

    m_icon->setAlignment(Qt::AlignCenter);
    DFontSizeManager::instance()->bind(m_title, DFontSizeManager::T5);
    QFont titleFont = m_title->font();
    titleFont.setWeight(QFont::Medium);
    m_title->setFont(titleFont);

    m_titleDes->setAlignment(Qt::AlignLeft);
    QFont titleDesFont = m_titleDes->font();
    titleDesFont.setWeight(QFont::Normal);
    m_titleDes->setFont(titleDesFont);
    DFontSizeManager::instance()->bind(m_titleDes, DFontSizeManager::T8);

    QPalette titleDesPalette;
    titleDesPalette.setColor(QPalette::BrightText, QColor(qRgba(0, 0, 0, 0.7)));
    m_titleDes->setPalette(titleDesPalette);
}

void SysBackupItemFrame::initLayout()
{
    QHBoxLayout *titleHLayout = new QHBoxLayout();
    titleHLayout->setContentsMargins(0, 0, 0, 0);
    titleHLayout->addWidget(m_title, 0, Qt::AlignLeft);
    titleHLayout->addSpacing(5);
    titleHLayout->addWidget(m_partitionPath, 0, Qt::AlignLeft);
    titleHLayout->addStretch();

    QVBoxLayout *centralLayout = new QVBoxLayout();
    centralLayout->setContentsMargins(20, 0, 40, 0);
    centralLayout->setSpacing(0);
    centralLayout->addSpacing(26);
    centralLayout->addLayout(titleHLayout);
    centralLayout->addSpacing(5);
    centralLayout->addWidget(m_titleDes, 0, Qt::AlignLeft);
    centralLayout->addSpacing(30);
    centralLayout->addWidget(m_storeUsed, 0, Qt::AlignLeft);
    centralLayout->addSpacing(10);

    QVBoxLayout *usedIconLayout = new QVBoxLayout;
    usedIconLayout->addSpacing(3);
    usedIconLayout->addWidget(m_usedLabelIcon, 0, Qt::AlignVCenter);
    QHBoxLayout *spaceHLayout = new QHBoxLayout;
    spaceHLayout->addLayout(usedIconLayout);
    spaceHLayout->addSpacing(5);
    spaceHLayout->addWidget(m_usedLabel);
    spaceHLayout->addSpacing(30);

    QVBoxLayout *availableIconLayout = new QVBoxLayout;
    availableIconLayout->addSpacing(3);
    availableIconLayout->addWidget(m_availableLabelIcon, 0, Qt::AlignVCenter);
    spaceHLayout->addLayout(availableIconLayout);

    spaceHLayout->addSpacing(5);
    spaceHLayout->addWidget(m_availableLabel);
    spaceHLayout->addStretch();
    spaceHLayout->addWidget(m_storeText, 0, Qt::AlignRight);
    centralLayout->addLayout(spaceHLayout);
    centralLayout->addStretch();

    m_mainHLayout = new QHBoxLayout(this);
    m_mainHLayout->setContentsMargins(20, 0, 0, 0);
    m_mainHLayout->setSpacing(0);
    m_mainHLayout->addWidget(m_icon, 0, Qt::AlignLeft);
    m_mainHLayout->addLayout(centralLayout);

    this->setLayout(m_mainHLayout);
}

void SysBackupItemFrame::setPartitionPathText(const QString &text)
{
    if (nullptr != m_partitionPath) {
        m_partitionPath->setText(text);
    }
}

ImmuSystemBackupWidget::ImmuSystemBackupWidget(DWidget *parent) : DWidget(parent)
{
    this->setAccessibleName("ImmuSystemBackupWidget");

    // 主题变换
    m_guiHelper = Dtk::Gui::DGuiApplicationHelper::instance();
    connect(m_guiHelper, &Dtk::Gui::DGuiApplicationHelper::themeTypeChanged, this, &ImmuSystemBackupWidget::onThemeChange);
    // 初始化UI
    initUI();

    auto themeType = DGuiApplicationHelper::instance()->themeType();
    this->onThemeChange(themeType);
}

void ImmuSystemBackupWidget::initUI()
{
    QVBoxLayout *verticalLayout = new QVBoxLayout(this);
    verticalLayout->setContentsMargins(12, 8, 0, 0);
    verticalLayout->setAlignment(Qt::AlignHCenter);

    m_title = new DLabel(this);
    m_title->setText(tr("System Backup"));
    m_title->setAccessibleName("uosBackup_SystemBackupLabel");
    m_title->setAlignment(Qt::AlignLeft);
    DFontSizeManager::instance()->bind(m_title, DFontSizeManager::T4);
    QFont titleFont = m_title->font();
    titleFont.setWeight(QFont::Bold);
    m_title->setFont(titleFont);

    m_titleDes = new DLabel(this);
    m_titleDes->setText(tr("Backup system files to protect you against system failure"));
    m_titleDes->setAccessibleName("uosBackup_SystemBackupSettingsDesLabel");
    m_titleDes->setAlignment(Qt::AlignLeft);

    m_labelDest = new DLabel(this);
    m_labelDest->setText(tr("Storage location:"));
    DFontSizeManager::instance()->bind(m_labelDest, DFontSizeManager::T5);
    QFont labelDestFont = m_labelDest->font();
    labelDestFont.setWeight(QFont::Medium);
    m_labelDest->setFont(labelDestFont);
    m_labelDest->setAccessibleName("uosBackup_StorageLocationLabel");

    m_dirChooseWidget = new DFileChooserEdit();
    m_dirChooseWidget->setFileMode(QFileDialog::Directory);
    m_dirChooseWidget->lineEdit()->setMinimumWidth(640);
    m_dirChooseWidget->lineEdit()->setReadOnly(true);
    QPalette chooseWidgetLineEditPalette = m_dirChooseWidget->lineEdit()->palette();
    chooseWidgetLineEditPalette.setColor(QPalette::Button, QColor(255, 255, 255));
    m_dirChooseWidget->lineEdit()->setPalette(chooseWidgetLineEditPalette);

   // m_curPartitionText = new DLabel(this);
    if (Utils::isImmutableSystem()) {
        m_dirChooseWidget->setText("/persistent/ostree/snapshot");
    } else {
        m_dirChooseWidget->setText("");
    }
    m_dirChooseWidget->setEnabled(false);

    QHBoxLayout *destHBoxLayout = new QHBoxLayout;
    destHBoxLayout->setContentsMargins(0, 0, 0, 0);
    destHBoxLayout->addWidget(m_labelDest, 0, Qt::AlignLeft);
    destHBoxLayout->addStretch();
    destHBoxLayout->addWidget(m_dirChooseWidget, 0, Qt::AlignRight);
    destHBoxLayout->addStretch();

    verticalLayout->addWidget(m_title, 0, Qt::AlignLeft);
    verticalLayout->addWidget(m_titleDes, 0, Qt::AlignLeft);
    verticalLayout->addSpacing(20);
    verticalLayout->addLayout(destHBoxLayout);
    verticalLayout->addSpacing(15);

    QString itemTitle = tr("Storage space status:");
    QString itemTitleDes = tr("Immutable systems use designated storage space for system backups, do not modify the storage paths");
    QString itemIconPath = ":/resources/icons/v25/data_disk.png";
    m_sysBackupItem = new SysBackupItemFrame(itemTitle, itemTitleDes, itemIconPath, this);
    m_sysBackupItem->setIconPixmap(itemIconPath, QSize(96, 96));
    m_sysBackupItem->setFixedSize(788, 198);
    m_sysBackupItem->initUI();
    m_sysBackupItem->initLayout();
    verticalLayout->addWidget(m_sysBackupItem, 0, Qt::AlignLeft);
    verticalLayout->addSpacing(95);

    QVBoxLayout *remarkLayout = new QVBoxLayout;
    remarkLayout->setContentsMargins(0, 0, 0, 0);
    remarkLayout->setAlignment(Qt::AlignLeft);
    DLabel *remarks = new DLabel;
    remarks->setText(tr("Note:") );
    remarks->setAccessibleName("uosBackup_SystemBackupNote");
    verticalLayout->addSpacing(100);
    verticalLayout->addWidget(remarks, 0, Qt::AlignLeft);
    verticalLayout->addSpacing(8);

    m_lineEdit = new DTextEdit;
    m_lineEdit->setFixedSize(788, 122);
    m_lineEdit->setAlignment(Qt::AlignTop);
#if DTK_VERSION >= DTK_VERSION_CHECK(5, 2, 2, 13)
    m_lineEdit->setPlaceholderText(tr("Optional"));
#endif
    QPalette lineEditPalette = m_lineEdit->palette();
    lineEditPalette.setColor(QPalette::Button, QColor(255, 255, 255));
    m_lineEdit->setPalette(lineEditPalette);
    m_lineEdit->setAccessibleName("uosBackup_SystemBackuptextEdit");
    m_lineEdit->setFocusPolicy(Qt::ClickFocus);
    m_lineEdit->setAcceptRichText(false);

    connect(m_lineEdit, &DTextEdit::textChanged, this, &ImmuSystemBackupWidget::onNoteTextChanged);
    remarkLayout->addWidget(m_lineEdit, 0, Qt::AlignLeft);

    m_lineEditCount = new DTipLabel;
    QString curCharCount = QString("(0/%1)").arg(m_maxNum);
    m_lineEditCount->setText(curCharCount);
    m_lineEditCount->setFixedHeight(40);

    QGraphicsOpacityEffect *opacityEffect = new QGraphicsOpacityEffect(m_lineEditCount);
    opacityEffect->setOpacity(0.6);
    m_lineEditCount->setGraphicsEffect(opacityEffect);

    QHBoxLayout *charCountHLayout = new QHBoxLayout;
    charCountHLayout->setContentsMargins(0, 46, 0, 0);
    charCountHLayout->addWidget(m_lineEditCount, 0, Qt::AlignRight);
    charCountHLayout->addSpacing(10);
    remarkLayout->addLayout(charCountHLayout);
    verticalLayout->addLayout(remarkLayout);
    verticalLayout->addSpacing(20);

    m_ostreeTips= new DLabel;
    m_ostreeTips->setAccessibleName("uosBackup_SystemBackupOStreeTips");
    m_ostreeTips->setAlignment(Qt::AlignCenter);
    m_ostreeTips->setFocusPolicy(Qt::NoFocus);
    m_ostreeTips->setStyleSheet("QLabel {"
                                "color: #FF5736;"
                                "}");
    m_tips= new DLabel;
    m_tips->setAccessibleName("uosBackup_SystemBackupTips");
    m_tips->setAlignment(Qt::AlignCenter);
    m_tips->setFocusPolicy(Qt::NoFocus);
    m_tips->setStyleSheet("QLabel {"
                          "color: #FF5736;"
                          "}");
    verticalLayout->addWidget(m_ostreeTips);
    verticalLayout->addWidget(m_tips);

    auto *startLayout = new QHBoxLayout;
    startLayout->setAlignment(Qt::AlignHCenter);

    m_start = new DPushButton(tr("Start Backup"));
    m_start->setAccessibleName("uosBackup_SystemBackupBackUp");
    m_start->setFixedSize(170, 36);
    // QPalette startPalette;
    // startPalette.setColor(QPalette::ButtonText, QColor(qRgb(0,88,222)));
    // m_start->setPalette(startPalette);
    // m_start->setForegroundRole(QPalette::ButtonText);

    if (m_dirChooseWidget->text().isEmpty()) {
        m_start->setEnabled(false);
    }
    startLayout->addStretch();
    startLayout->addWidget(m_start, 0, Qt::AlignmentFlag::AlignRight);
    startLayout->addSpacing(13);

    verticalLayout->addLayout(startLayout);
    verticalLayout->addSpacing(10);

    connect(m_start, &DPushButton::clicked, [this] {
        QString remark = m_lineEdit->toPlainText();
        Q_EMIT start(remark);
    });
}

void ImmuSystemBackupWidget::onNoteTextChanged()
{
    const int maxNotesLen = 40;
    QString notes = m_lineEdit->toPlainText();
    int len = notes.length();
    int num = len;
    if (len > maxNotesLen) {
        auto cursor = m_lineEdit->textCursor();
        cursor.deletePreviousChar();
        num = maxNotesLen;
    }

    this->updateNoteCharNum(num);
}

void ImmuSystemBackupWidget::updateNoteCharNum(int num)
{
    if (nullptr != m_lineEditCount) {
        QString curCharCount = QString("(%1/%2)").arg(num).arg(m_maxNum);
        m_lineEditCount->setText(curCharCount);
    }
}

void ImmuSystemBackupWidget::setTips(const QString &tips)
{
    if(m_tips != nullptr) {
        m_tips->setText(tips);
    }
}

void ImmuSystemBackupWidget::setTipsStyleSheet(const QString &styleSheet)
{
    if (nullptr != m_tips) {
        m_tips->setStyleSheet(styleSheet);
    }
}

void ImmuSystemBackupWidget::setNotes(const QString &txt)
{
    m_lineEdit->setText(txt);
}

void ImmuSystemBackupWidget::onThemeChange(Dtk::Gui::DGuiApplicationHelper::ColorType themeType)
{
    QColor sysBackupItemColor;
    QPalette lineEditPalette = m_lineEdit->palette();
    QPalette chooseWidgetLineEditPalette = m_dirChooseWidget->lineEdit()->palette();
    if (DGuiApplicationHelper::ColorType::DarkType == themeType) {
        chooseWidgetLineEditPalette.setColor(QPalette::Button, QColor(40, 40, 40));
        lineEditPalette.setColor(QPalette::Button, QColor(40, 40, 40));
        sysBackupItemColor.setRgb(40, 40, 40);
    } else {
        chooseWidgetLineEditPalette.setColor(QPalette::Button, QColor(255, 255, 255));
        lineEditPalette.setColor(QPalette::Button, QColor(255, 255, 255));
        sysBackupItemColor.setRgb(255, 255, 255);
    }

    m_dirChooseWidget->lineEdit()->setPalette(chooseWidgetLineEditPalette);
    m_lineEdit->setPalette(lineEditPalette);

    QPalette sysBackupItemPalette;
    sysBackupItemPalette.setBrush(QPalette::Window, QBrush(sysBackupItemColor));
    m_sysBackupItem->setPalette(sysBackupItemPalette);
}

void ImmuSystemBackupWidget::setDestPartitionText(const QJsonObject &jsonObject)
{
    Partition partition;
    partition.unmarshal(jsonObject);
    if (partition.name.isEmpty() && jsonObject.contains("disk")) {
        partition.name = jsonObject.value("disk").toString().trimmed();
    }

    if ((0 == partition.size) && jsonObject.contains("size")) {
        partition.size = Utils::parsePartitionSize(jsonObject.value("size").toString());
    }

    if ((0 == partition.used) && jsonObject.contains("used")) {
        partition.used = Utils::parsePartitionSize(jsonObject.value("used").toString());
    }

    if ((0 == partition.free) && jsonObject.contains("free")) {
        partition.free = Utils::parsePartitionSize(jsonObject.value("free").toString());
    }

    if (0 == partition.size) {
        m_start->setEnabled(false);
        m_sysBackupItem->setStoreUsedValue(0);
        m_sysBackupItem->setPartitionPathText("");
        m_sysBackupItem->setStoreText(tr("Available: %1/%2")
                                              .arg(0)
                                              .arg(0));
        return;
    }

    m_sysBackupItem->setStoreUsedValue((int)((partition.size - partition.free) * 100 / partition.size));
    m_sysBackupItem->setStoreText(tr("Available: %1/%2")
                                 .arg(Utils::byte2DisplaySize(partition.free))
                                 .arg(Utils::byte2DisplaySize(partition.size)));
    m_sysBackupItem->setPartitionPathText("/dev/" + partition.name);
    if (partition.free < 1 * 1024 * 1024 * 1024) {
        this->setTips(tr("Insufficient disk space. Please clean up first."));
        m_start->setEnabled(false);
    } else {
        this->setTips("");
        m_start->setEnabled(true);
    }
}

