//
// Created by 张雪明 <zhangxueming@uniontech.com> on 2024/12/4.
//
#include "ImmuGhostWidget.h"
#include "utils/Utils.h"
#include "utils/global.h"
#include "utils/Device.h"
#include <QVBoxLayout>
#include <DFontSizeManager>

TipsWidget::TipsWidget(QWidget *parent) : QWidget(parent)
{
    initUI();
    initLayout();
}

void TipsWidget::initUI()
{
    m_spinner = new DSpinner(this);
    m_spinner->setFixedSize(16, 16);
    m_spinner->setFocusPolicy(Qt::NoFocus);

    m_tipsLabel = new DLabel(this);
    m_tips = new DLabel(this);
    m_hLayout = new QHBoxLayout;

    m_spaceLabel = new DLabel(this);;
    m_spaceLabel->setFixedWidth(3);
}

void TipsWidget::initLayout()
{
    m_hLayout->setContentsMargins(0, 0, 0, 0);
    m_hLayout->addWidget(m_tips, 0, Qt::AlignLeft);

    this->setLayout(m_hLayout);
}

void TipsWidget::setTips(const QString &tips)
{
    m_tips->setText(tips);
}

void TipsWidget::resetLayout(LayoutType layoutType)
{
    if (m_hLayout != nullptr) {
        delete m_hLayout;
        m_hLayout = nullptr;
    }
    m_hLayout = new QHBoxLayout;
    m_hLayout->setContentsMargins(0, 0, 0, 0);
    this->setLayout(m_hLayout);

    switch (layoutType) {
        case LayoutType::tipsLayout: {
            m_hLayout->addWidget(m_tips, 0, Qt::AlignLeft);
            break;
        }
        case LayoutType::spinnerLayout: {
            QVBoxLayout * spinnerLayout = new QVBoxLayout;
            spinnerLayout->addSpacing(3);
            spinnerLayout->addWidget(m_spinner);
            m_hLayout->addLayout(spinnerLayout);
            m_hLayout->addSpacing(-5);
            m_hLayout->addWidget(m_spaceLabel);
            m_hLayout->addWidget(m_tips, 0, Qt::AlignLeft);
            break;
        }
        case LayoutType::tipsLabelLayout: {
            QVBoxLayout * tipLayout = new QVBoxLayout;
            tipLayout->addSpacing(3);
            tipLayout->addWidget(m_tipsLabel);
            m_hLayout->addLayout(tipLayout);
            m_hLayout->addSpacing(-5);
            m_hLayout->addWidget(m_spaceLabel);
            m_hLayout->addWidget(m_tips, 0, Qt::AlignLeft);
            break;
        }
        default:
            break;
    }
};

void TipsWidget::setTipsLabelIconPixmap(const QPixmap &iconPix)
{
    m_tipsLabel->setPixmap(iconPix);
}

void TipsWidget::showSpinner(bool show)
{
    if (show) {
        m_spinner->show();
        m_spinner->start();
    } else {
        m_spinner->hide();
        m_spinner->stop();
    }
}

GhostItemFrame::GhostItemFrame(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("GhostItemFrame");
    setBackgroundRole(DPalette::NoType);
    setLineWidth(0);
}

GhostItemFrame::~GhostItemFrame()
{}

void GhostItemFrame::initUI()
{
    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_tipsWidget = new TipsWidget;
    m_icon->setAlignment(Qt::AlignCenter);
    DFontSizeManager::instance()->bind(m_title, DFontSizeManager::T4);
}

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

    QVBoxLayout *centralLayout = new QVBoxLayout();
    centralLayout->setContentsMargins(20, 0, 50, 0);
    centralLayout->setSpacing(0);
    centralLayout->addSpacing(38);
    centralLayout->addLayout(titleHLayout);
    //   centralLayout->addWidget(m_titleDes, 0, Qt::AlignLeft);
    centralLayout->addSpacing(25);
    centralLayout->addWidget(m_storeUsed, 0, Qt::AlignLeft);
    centralLayout->addSpacing(5);

    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 GhostItemFrame::setTips(const QString &tips)
{
    if (nullptr != m_tipsWidget) {
        m_tipsWidget->setTips(tips);
    }
}

void GhostItemFrame::showSpinner(bool show)
{
    if (nullptr != m_tipsWidget) {
        m_tipsWidget->showSpinner(show);
    }
}

void GhostItemFrame::resetLayout(LayoutType layoutType)
{
    if (nullptr != m_tipsWidget) {
        m_tipsWidget->resetLayout(layoutType);
    }
}

void GhostItemFrame::setTipsLabelIconPixmap(const QPixmap &iconPix)
{
    if (nullptr != m_tipsWidget) {
        m_tipsWidget->setTipsLabelIconPixmap(iconPix);
    }
}

ImmuGhostWidget::ImmuGhostWidget(DWidget *parent) : DWidget(parent)
{
    QSize iconSize(16,16);
    QString okIconPath = ":/resources/icons/v25/success.svg";
    QString warningIconPath = ":/resources/icons/v25/warning.svg";
    m_okIconPixmap = Utils::hidpiPixmap(okIconPath, iconSize);
    m_warningIconPixmap = Utils::hidpiPixmap(warningIconPath, iconSize);
    this->initUI();
    this->initLayout();

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

void ImmuGhostWidget::initUI()
{
    m_title = new DLabel(this);
    m_title->setText(tr("System Clone"));
    m_title->setAccessibleName("uosBackup_SystemCloneSettingsLabel");
    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("One click clone the system and data, and can be installed to other device"));
    m_titleDes->setAccessibleName("uosBackup_SystemCloneSettingsDesLabel");
    m_titleDes->setAlignment(Qt::AlignLeft);
    DFontSizeManager::instance()->bind(m_titleDes, DFontSizeManager::T6);
    QFont titleDesFont = m_titleDes->font();
    titleDesFont.setWeight(QFont::Normal);
    m_titleDes->setFont(titleDesFont);

    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_dirChooseWidget = new DFileChooserEdit();
#if DTK_VERSION >= DTK_VERSION_CHECK(5, 2, 2, 13)
    m_dirChooseWidget->setPlaceholderText(tr("Select a Directory"));
#endif
    m_dirChooseWidget->setAccessibleName("SystemClone_SelectADirectory");
    m_dirChooseWidget->lineEdit()->setAccessibleName("SystemCLone_dirChooseWidgetlineEdit");
    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);

    QString itemTitle = tr("Select a directory to save the .uimg image file");
    QString itemIconPath = ":/resources/icons/v25/data_disk.png";
    m_ghostItem = new GhostItemFrame("", "", itemIconPath, this);
    m_ghostItem->setIconPixmap(itemIconPath, QSize(96, 96));
    m_ghostItem->setFixedSize(788, 198);
    m_ghostItem->initUI();
    m_ghostItem->initLayout();
    m_ghostItem->setTips(itemTitle);
    m_ghostItem->setStoreText(tr("Available: %1GB/%2GB")
                                      .arg(0)
                                      .arg(0));

    m_tips = new DLabel;
    m_tips->hide();
    m_tips->setAccessibleName("uosImmuGhostWidget_tipsLabel");

    m_start = new DPushButton(tr("Start Backup"));
    m_start->setEnabled(false);
    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);

    m_guiHelper = Dtk::Gui::DGuiApplicationHelper::instance();
    connect(m_guiHelper, &Dtk::Gui::DGuiApplicationHelper::themeTypeChanged, this, &ImmuGhostWidget::onThemeChange);
    connect(m_dirChooseWidget, &DFileChooserEdit::dialogClosed, this, &ImmuGhostWidget::onFileDialogClosed);
    connect(m_start, &QPushButton::clicked, this, &ImmuGhostWidget::startBtnClicked, Qt::QueuedConnection);
}

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

    QHBoxLayout *locSelectHLayout = new QHBoxLayout;
    locSelectHLayout->addWidget(m_labelDest, 0, Qt::AlignLeft);
    locSelectHLayout->addSpacing(10);
    locSelectHLayout->addStretch();
    locSelectHLayout->addWidget(m_dirChooseWidget, 0, Qt::AlignRight);
    locSelectHLayout->addSpacing(12);

    verticalLayout->addWidget(m_title, 0, Qt::AlignLeft);
    verticalLayout->addWidget(m_titleDes, 0, Qt::AlignLeft);
    verticalLayout->addSpacing(50);
    verticalLayout->addLayout(locSelectHLayout);
    verticalLayout->addSpacing(30);
    verticalLayout->addWidget(m_ghostItem, 0, Qt::AlignLeft);
    verticalLayout->addSpacing(250);

    QHBoxLayout *calculateTipLayout = new QHBoxLayout();
    calculateTipLayout->setSpacing(10);
    calculateTipLayout->setContentsMargins(0,0,0,0);
    calculateTipLayout->addStretch();
    calculateTipLayout->addWidget(m_tips);
    calculateTipLayout->addStretch();
    QWidget *calculateTipWidget = new QWidget;
    calculateTipWidget->setAccessibleName("uosImmuGhostWidget_calculateTipWidget");
    calculateTipWidget->setFixedHeight(36);
    calculateTipWidget->setLayout(calculateTipLayout);

    verticalLayout->addWidget(calculateTipWidget, 0, Qt::AlignHCenter);

    QHBoxLayout *startLayout = new QHBoxLayout;
    startLayout->setAlignment(Qt::AlignHCenter);
    startLayout->addStretch();
    startLayout->addWidget(m_start, 0, Qt::AlignmentFlag::AlignRight);
    startLayout->addSpacing(13);

    verticalLayout->addLayout(startLayout);
    verticalLayout->addSpacing(10);
    this->setLayout(verticalLayout);
}

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

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

    QPalette ghostItemPalette;
    ghostItemPalette.setBrush(QPalette::Window, QBrush(ghostItemColor));
    m_ghostItem->setPalette(ghostItemPalette);
}

void ImmuGhostWidget::onFileDialogClosed(int code)
{
    if (code == QDialog::Accepted) {
        if (nullptr != m_tips) {
            m_tips->hide();
        }
    } else {
        return;
    }

    QString srcDirStr = m_dirChooseWidget->lineEdit()->text();
    if (srcDirStr.isEmpty()) {
        setResultInfo("", false);
        return;
    }

    QString fstype;
    QString devPath;
    Utils::getFsTypeAndDevicePathByDir(srcDirStr, fstype, devPath);
    if (!Device::isFsTypeSupportedGhost(fstype)) {
       // setDestDirText("");
        setResultInfo(tr("The file system of the selected directory is unsupported. Please select one on a disk in ext4, btrfs, xfs format."), false);
        return;
    }

    QString calcTips = tr("Calculating space...");
    setErrorInfo("", true);
    setStoreItemInfo(0, 0);
    m_ghostItem->setTips(calcTips);
    m_ghostItem->resetLayout(LayoutType::spinnerLayout);
    m_ghostItem->showSpinner(true);
    m_ghostItem->setTipsLabelIconPixmap(QPixmap());
    m_dirChooseWidget->setEnabled(false);
    Q_EMIT checkSpaceSignal(srcDirStr);

    m_start->setEnabled(false);
}

void ImmuGhostWidget::setGhostItemTips(const QString &tips)
{
    if (nullptr != m_ghostItem) {
        m_ghostItem->setTips(tips);
    }
}

void ImmuGhostWidget::setTipsStyleSheet(const QString &styleSheet)
{}

QString ImmuGhostWidget::getDestDirText()
{
    QString labelText = m_dirChooseWidget->lineEdit()->text();

    return labelText;
}

void ImmuGhostWidget::setStoreItemInfo(quint64 usedSize, quint64 totalSize)
{
    if (nullptr != m_ghostItem) {
        m_ghostItem->showSpinner(false);
        if (totalSize > 0 && usedSize > 0) {
            m_ghostItem->setStoreUsedValue((int)(usedSize * 100 / totalSize));
            m_ghostItem->setStoreText(tr("Available: %1/%2")
                .arg(Utils::byte2DisplaySize(totalSize - usedSize))
                .arg(Utils::byte2DisplaySize(totalSize)));
        } else {
            if (totalSize > 0) {
                m_ghostItem->setStoreUsedValue(100);
            } else {
                m_ghostItem->setStoreUsedValue(0);
            }
            m_ghostItem->setStoreText(tr("Available: %1GB/%2GB")
                                              .arg(0)
                                              .arg(QString().asprintf("%.1f", totalSize * 1.0 / GiB)));
        }
    }
}

void ImmuGhostWidget::resetLayout(LayoutType layoutType)
{
    if (nullptr != m_ghostItem) {
        m_ghostItem->resetLayout(layoutType);
    }
}

void ImmuGhostWidget::setDefaultStorePathTips()
{
    m_dirChooseWidget->lineEdit()->setText("");
#if DTK_VERSION >= DTK_VERSION_CHECK(5, 2, 2, 13)
    m_dirChooseWidget->setPlaceholderText(tr("Select a Directory"));
#endif
}

void ImmuGhostWidget::setGhostItemTipsLabelIcon(int status)
{
    const int successIconStatus = 0;
    const int warningIconStatus = 1;
    const int noIconStatus = 2;
    if (successIconStatus == status) {
        m_ghostItem->setTipsLabelIconPixmap(m_okIconPixmap);
    } else if (warningIconStatus == status) {
        m_ghostItem->setTipsLabelIconPixmap(m_warningIconPixmap);
    } else if (noIconStatus == status) {
        m_ghostItem->setTipsLabelIconPixmap(QPixmap());
    }
}

void ImmuGhostWidget::startBtnClicked()
{
    QString srcDirStr = m_dirChooseWidget->lineEdit()->text();
    Q_EMIT start(srcDirStr);
}

void ImmuGhostWidget::setStartEnable(bool enable)
{
    m_start->setEnabled(enable);
}

void ImmuGhostWidget::setCancelEnable(bool enable)
{
  //  m_cancel->setEnabled(enable);
}

void ImmuGhostWidget::setResultInfo(const QString &info, bool error)
{
    setErrorInfo(info, error);

    m_dirChooseWidget->setEnabled(true);
    m_ghostItem->showSpinner(false);
}

void ImmuGhostWidget::setErrorInfo(const QString &info, bool normalStyle)
{
    m_tips->setText(info);
    if (normalStyle) {
        QLabel styleLabel;
        m_tips->setStyleSheet(styleLabel.styleSheet());
    } else {
        m_tips->setStyleSheet("QLabel {"
                                        "color: #FF0000;"
                                        "border: none;"
                                        "background-color: transparent;"
                                        "}");
    }

    if (info.isEmpty()) {
        m_tips->hide();
    } else {
        m_tips->show();
    }
}
