//
// Created by 张雪明 <zhangxueming@uniontech.com> on 2024/12/2.
//
#include "ImmuDataBackupWidget.h"
#include <DFontSizeManager>
#include <DPushButton>
#include <DSuggestButton>
#include <QHeaderView>
#include <QDir>
#include <QStandardPaths>
#include <DFileDialog>
#include <DDialog>
#include <QUuid>
#include <QGraphicsOpacityEffect>
#include <QListView>
#include <QScrollBar>
#include <QPainter>
#include <QPainterPath>
#include "common/ImmuBaseItemDelegate.h"
#include "common/ImmuBaseTableView.h"
#include "utils/Utils.h"

const int TABLE_COL_OPT_ID = 0;
const int TABLE_COL_DIR = 1;
const int TABLE_COL_ACTION = 2;


RoundedPopup::RoundedPopup(QWidget *parent, Qt::WindowFlags flags)
    : QWidget(parent, flags)
{
    // 设置窗口透明背景，以便绘制圆角效果
    setAttribute(Qt::WA_TranslucentBackground);
    setWindowFlag(Qt::WindowDoesNotAcceptFocus, true);
}

void RoundedPopup::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);

    QPainter painter(this);
    // 增强抗锯齿设置，添加更多渲染提示以获得更平滑的效果
    painter.setRenderHints(QPainter::Antialiasing | 
                            QPainter::TextAntialiasing | 
                            QPainter::SmoothPixmapTransform, true);

    // 创建圆角矩形路径
    QPainterPath path;
    int radius = 8; // 圆角半径
    path.addRoundedRect(rect().adjusted(0.5, 0.5, -0.5, -0.5), radius, radius);

    // 绘制背景
    painter.fillPath(path, palette().window());

    // 优化边框绘制，设置线条连接样式为平滑连接
    QPen borderPen(palette().color(QPalette::Mid));
    borderPen.setJoinStyle(Qt::RoundJoin); // 圆角连接
    painter.setPen(borderPen);
    painter.drawPath(path);

    // 设置窗口蒙版，确保只有圆角矩形区域可见
    setMask(path.toFillPolygon().toPolygon());
}

ImmuBackupIconComboBox::ImmuBackupIconComboBox(QWidget *parent) : QWidget(parent)
{
    QVBoxLayout *layout = new QVBoxLayout;
    layout->setContentsMargins(0, 0, 0, 0);
    setLayout(layout);

    m_comboBox = new QComboBox;
    m_comboBox->setVisible(false);
    m_comboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
    m_comboBox->setFocusPolicy(Qt::NoFocus);
    layout->addWidget(m_comboBox);

    m_button = new DIconButton;
    layout->addWidget(m_button);

    m_popup = new RoundedPopup(nullptr, Qt::Popup);
    m_popup->setFixedWidth(200);

    // 创建垂直布局
    QVBoxLayout* popupLayout = new QVBoxLayout(m_popup);
    popupLayout->setContentsMargins(8, 8, 8, 8); // 设置内边距，确保内容不紧贴边缘

    // 添加标题标签
    m_titleLabel = new QLabel();
    // titleLabel->setAlignment(Qt::AlignCenter);
    // QFont titleFont = titleLabel->font();
    // titleFont.setBold(true);
    // titleLabel->setFont(titleFont);
    popupLayout->addWidget(m_titleLabel);
    popupLayout->addSpacing(10);

    // // 添加分隔线
    // QFrame* separator = new QFrame;
    // separator->setFrameShape(QFrame::HLine);
    // separator->setFrameShadow(QFrame::Sunken);
    // popupLayout->addWidget(separator);

    // 添加列表视图，显示下拉选项
    m_listView = new DListView;
    m_listView->setModel(m_comboBox->model());
    m_listView->setSelectionModel(m_comboBox->view()->selectionModel());
    m_listView->setFrameShape(QFrame::NoFrame); // 移除列表视图的边框
    m_listView->setSelectionModel(m_comboBox->view()->selectionModel());
    //m_listView->setFixedWidth(120);
    m_listView->setBackgroundType(DStyledItemDelegate::NoBackground);
    m_listView->setEditTriggers(QAbstractItemView::NoEditTriggers);
    m_listView->verticalScrollBar()->setContextMenuPolicy(Qt::NoContextMenu);
    m_listView->horizontalScrollBar()->setContextMenuPolicy(Qt::NoContextMenu);
    m_listView->setSelectionMode(QAbstractItemView::SingleSelection);
    popupLayout->addWidget(m_listView);
    m_popup->hide();

    connect(m_listView, &QListView::clicked, [=](const QModelIndex& index) {
        Q_EMIT combCurrentIndexChanged(index.row());
        m_popup->hide();
    });

    connect(m_button, &QAbstractButton::clicked, [this] {
        m_comboBox->setCurrentIndex(-1);
        m_listView->clearSelection();
        m_popup->move(m_button->mapToGlobal(QPoint(m_popup->width() * -1 + m_button->width(), m_button->height() + 10)));
        m_popup->show();
    });
}

void ImmuBackupIconComboBox::setDStyleIcon(const Dtk::Widget::DStyle::StandardPixmap &icon)
{
    m_button->setIcon(icon);
}

QAbstractButton* ImmuBackupIconComboBox::button()
{
    return m_button;
}

QComboBox* ImmuBackupIconComboBox::comboBox()
{
    return m_comboBox;
}

DListView* ImmuBackupIconComboBox::listView()
{
    return m_listView;
}

QLabel* ImmuBackupIconComboBox::titleLabel()
{
    return m_titleLabel;
}

void ImmuBackupIconComboBox::setMaxVisibleCount(int count)
{
    if (count > 0) {
        m_maxVisibleCount = count;
    }
}

ImmuBackupPathDeleteWidget::ImmuBackupPathDeleteWidget(QWidget *parent) : QWidget(parent)
{
    m_guiHelper = Dtk::Gui::DGuiApplicationHelper::instance();
    connect(m_guiHelper, &Dtk::Gui::DGuiApplicationHelper::themeTypeChanged, this, &ImmuBackupPathDeleteWidget::onThemeChange);

    QHBoxLayout *layout = new QHBoxLayout;
    layout->setContentsMargins(0, 0, 0, 0);
    layout->setAlignment(Qt::AlignLeft);
    setLayout(layout);
    m_deleteBtn = new DPushButton;
    m_deleteBtn->setToolTip(tr("Delete"));
    // 设置按钮背景透明
    QPalette palette = m_deleteBtn->palette();
    palette.setBrush(QPalette::Button, Qt::transparent);
    m_deleteBtn->setPalette(palette);
    m_deleteBtn->setAutoFillBackground(false);
    // 设置按钮无边框
    m_deleteBtn->setFlat(true);
    m_deleteBtn->setIconSize(QSize(16, 16));
    onThemeChange(m_guiHelper->themeType());
    layout->addWidget(m_deleteBtn);
    m_deleteBtn->setAccessibleName("ImmuBackupPathDeleteWidget_deleteBtn");
    m_spinner = new DSpinner;
    m_spinner->setFixedSize(24, 24);
    m_spinner->setVisible(false);
    m_spinner->setAccessibleName("ImmuBackupPathDeleteWidget_DSpinner");
    layout->addWidget(m_spinner);
    connect(m_deleteBtn, &QPushButton::clicked, this, &ImmuBackupPathDeleteWidget::onDelete);
}

void ImmuBackupPathDeleteWidget::setBackupPathInfo(const QString &opID, const QString &path)
{
    m_opIDPath.first = opID;
    m_opIDPath.second = path;
}

void ImmuBackupPathDeleteWidget::onDelete()
{
//    bool authed = false;
//    if (m_backupInfo.operateType == OperateType::SystemBackup) {
//        authed = Utils::authorization();
//    } else if (m_backupInfo.operateType == OperateType::UserDataBackup) {
//        authed = Utils::checkCommonUserAuthentication();
//    }
//
//    if (!authed) {
//        return;
//    }
//
//    if (m_isRemoving) {
//        return;
//    }
    //m_isRemoving = true;

    // 先修改状态，后发送信号，避免删除失败导致状态无法更正
    m_deleteBtn->setVisible(false);
    m_spinner->setVisible(true);
    m_spinner->start();

    Q_EMIT deleteBackupPathClicked(m_opIDPath.first);
}

void ImmuBackupPathDeleteWidget::onThemeChange(Dtk::Gui::DGuiApplicationHelper::ColorType themeType)
{
    if (nullptr != m_deleteBtn) {
        if (Dtk::Gui::DGuiApplicationHelper::ColorType::DarkType == themeType) {
            m_deleteBtn->setIcon(QIcon::fromTheme(":/resources/icons/delete_dark.svg"));
        } else {
            m_deleteBtn->setIcon(QIcon::fromTheme(":/resources/icons/delete.svg"));
        }
    }
}

void ImmuBackupPathDeleteWidget::setDeleteBtnVisible(bool visible)
{
    if (m_deleteBtn != nullptr) {
        m_deleteBtn->setVisible(visible);
    }
}

void ImmuBackupPathDeleteWidget::stopSpinner()
{
    if (m_spinner != nullptr) {
        m_spinner->stop();
    }
}

void ImmuBackupPathDeleteWidget::setSpinnerVisible(bool visible)
{
    if (m_spinner != nullptr) {
        m_spinner->setVisible(visible);
    }
}

ImmuDataBackupWidget::ImmuDataBackupWidget(DWidget *parent) : DWidget(parent)
{
    this->setFixedHeight(610);
    initUI();
    initLayout();
    QString fileName = "/etc/fstab";
    m_fstabInfos = FSTab::getFSTabFromFile(fileName);
    FSTab::getFstabBindDir(m_fstabInfos, m_bindDirMap);
    m_isImmutable = Utils::isImmutableSystem();

    m_guiHelper = Dtk::Gui::DGuiApplicationHelper::instance();
    connect(m_guiHelper, &Dtk::Gui::DGuiApplicationHelper::themeTypeChanged, this, &ImmuDataBackupWidget::onThemeChange);

    this->onThemeChange(m_guiHelper->themeType());
}

QString ImmuDataBackupWidget::getDirBindPath(const QString &path)
{
    return m_bindDirMap[path];
}

void ImmuDataBackupWidget::initUI()
{
    this->setAccessibleName("uosDataBackup_ImmuDataBackupWidget");
    m_title = new DLabel(this);
    m_title->setText(tr("Data Backup"));
    m_title->setAccessibleName("uos_ImmuDataBackupWidget_Title");
    m_title->setAlignment(Qt::AlignLeft);
    QFont font = m_title->font();
    font.setWeight(QFont::DemiBold);
    font.setPixelSize(20);
    m_title->setFont(font);
    QPalette titlePalette;
    titlePalette.setColor(QPalette::BrightText, QColor(qRgb(0,26,46)));
    m_title->setPalette(titlePalette);

    m_titleDes = new DLabel(this);
    m_titleDes->setText(tr("Specify files and directories to back up, so as to avoid data loss or damage"));
    m_titleDes->setAccessibleName("uos_ImmuDataBackupWidget_Title");
    m_titleDes->setAlignment(Qt::AlignLeft);
    QFont titleDesfont = m_titleDes->font();
    titleDesfont.setWeight(QFont::Normal);
    titleDesfont.setPixelSize(14);
    m_titleDes->setFont(titleDesfont);
    QPalette titleDesPalette;
    titleDesPalette.setColor(QPalette::BrightText, QColor(qRgb(0,26,46)));
    m_titleDes->setPalette(titleDesPalette);

    m_backupDirTitle = new DLabel(this);
    m_backupDirTitle->setText(tr("Select the data to back up"));
    m_backupDirTitle->setAccessibleName("uos_ImmuDataBackupWidget_BackupDirTitle");
    m_backupDirTitle->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
    QFont backupDirTitleFont = m_backupDirTitle->font();
    backupDirTitleFont.setWeight(QFont::DemiBold);
    backupDirTitleFont.setPixelSize(16);
    m_backupDirTitle->setFont(backupDirTitleFont);
    QPalette backupDirTitlePalette;
    backupDirTitlePalette.setColor(QPalette::BrightText, QColor(qRgba(0,0,0,0.85)));
    m_backupDirTitle->setPalette(backupDirTitlePalette);

    m_addIconBtn = new DIconButton(this);
    m_addIconBtn->setAccessibleName("uos_ImmuDataBackupWidget_addIconButton");
    m_addIconBtn->setIcon(DStyle::SP_IncreaseElement);
    m_addIconBtn->setFixedSize(QSize(36,36));

    QString vaultPath = "/home/" + Utils::getUserName() + "/.config/Vault";
    if (QDir(vaultPath).exists()) {
        m_moreIconBtn = new ImmuBackupIconComboBox(this);
        m_moreIconBtn->setAccessibleName("uos_ImmuDataBackupWidget_moreIconButton");
        m_moreIconBtn->setDStyleIcon(DStyle::SP_SelectElement);
        m_moreIconBtn->setFixedSize(QSize(36, 36));

        m_moreIconBtn->titleLabel()->setText(tr("One-click backup of specified data"));
        m_moreIconBtn->comboBox()->clear();
        QIcon vaultIcon = QIcon::fromTheme(":/resources/icons/folder_vault.svg");
        m_moreIconBtn->comboBox()->addItem(vaultIcon, tr("Vault"));
    }

//    m_deleteIconBtn = new DIconButton(this);
//    m_deleteIconBtn->setAccessibleName("uos_DataBackupWidget_deleteIconButton");
//    m_deleteIconBtn->setIcon(DStyle::SP_DecreaseElement);
//    m_deleteIconBtn->setFixedSize(QSize(36,36));

    m_tableView = new ImmuBaseTableView(this);
    m_tableView->setAccessibleName("uos_ImmuDataBackupWidget_tableView");
    m_model = new QStandardItemModel;
    m_tableView->setModel(m_model);
    m_tableView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    auto itemDelegate = new ImmuBaseItemDelegate(this);
    m_tableView->setItemDelegate(itemDelegate);

    m_backupDir = new DLabel(this);
    m_backupDir->setText(tr("Backup directory") + ":");
    m_backupDir->setAccessibleName("uos_ImmuDataBackupWidget_BackupDirectory");
    m_backupDir->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
    QPalette backupDirPalette;
    backupDirPalette.setColor(QPalette::BrightText, QColor(qRgb(65,77,104)));
    m_backupDir->setPalette(backupDirPalette);
    connect(qApp, &QApplication::fontChanged, this, &ImmuDataBackupWidget::onBackDirFontChanged);
    int comboWidth = getComboWidth(m_backupDir->font());

    m_comboBox = new DComboBox(this);
    QPalette comboBoxPalette = m_comboBox->palette();
    comboBoxPalette.setColor(QPalette::Light, QColor(255, 255, 255));
    comboBoxPalette.setColor(QPalette::Dark, QColor(255, 255, 255));
    m_comboBox->setPalette(comboBoxPalette);
    m_comboBox->setFocusPolicy(Qt::FocusPolicy::NoFocus);
    m_comboBox->setAccessibleName("uos_ImmuDataBackupWidget_ComboBox");
    m_comboBox->setAccessibleDescription("uos_ImmuDataBackupWidget_ComboBoxDes");
    m_comboBox->setFixedWidth(comboWidth);

    m_noteLabel = new DLabel(this);
    m_noteLabel->setText(tr("Note") + ":");
    m_noteLabel->setAccessibleName("uos_ImmuDataBackupWidget_NoteLabel");
    m_noteLabel->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
    QPalette noteLabelPalette;
    noteLabelPalette.setColor(QPalette::BrightText, QColor(qRgb(65,77,104)));
    m_noteLabel->setPalette(noteLabelPalette);

    m_noteEdit = new DTextEdit(this);
    m_noteEdit->setFixedWidth(m_comboBox->width());
#if DTK_VERSION >= DTK_VERSION_CHECK(5, 2, 2, 13)
    m_noteEdit->setPlaceholderText(tr("Optional"));
#endif
    QPalette noteEditPalette = m_noteEdit->palette();
    noteEditPalette.setColor(QPalette::Button, QColor(255, 255, 255));
    m_noteEdit->setPalette(noteEditPalette);
    m_noteEdit->setAccessibleName("uos_ImmuDataBackupWidget_NoteContents");
    m_noteEdit->setFocusPolicy(Qt::FocusPolicy::ClickFocus);
    m_noteEdit->setAcceptRichText(false);
    m_noteEdit->setFixedHeight(69);

    connect(m_noteEdit, &DTextEdit::textChanged, this, &ImmuDataBackupWidget::onNoteTextChanged);

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

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

    m_spinner = new DSpinner(this);
    m_spinner->setAccessibleName("uos_ImmuDataBackupWidget_DSpinner");
    m_spinner->setFocusPolicy(Qt::NoFocus);
    m_spinner->setFixedSize(16,16);
    m_spinner->hide();

    m_tips= new DLabel(this);
    m_tips->setAccessibleName("uos_ImmuDataBackupWidget_Tips");
    m_tips->setAlignment(Qt::AlignCenter);
    m_tips->setFocusPolicy(Qt::NoFocus);
    m_tips->setStyleSheet("QLabel {"
                          "color: #FF5736;"
                          "}");

    m_startBtn = new DPushButton(this);
    m_startBtn->setText(tr("Start Backup"));
    m_startBtn->setAccessibleName("uos_ImmuDataBackupWidget_StartBackup");
    m_startBtn->setFixedSize(170, 36);
    m_startBtn->setEnabled(false);
    // QPalette startPalette;
    // startPalette.setColor(QPalette::ButtonText, QColor(qRgb(0,88,222)));
    // m_startBtn->setPalette(startPalette);
    // m_startBtn->setForegroundRole(QPalette::ButtonText);
}

int ImmuDataBackupWidget::getComboWidth(const QFont &font)
{
    int backDirLen = m_backupDir->text().length();
    QFontMetrics fontMetrics(m_backupDir->font());
    QRect backDirTextRect = fontMetrics.boundingRect(m_backupDir->text());
    int backDirWidth = backDirTextRect.width();
    int fontHeight = fontMetrics.height();
    int pointSize = font.pointSize();
    int comboWidth = 740 - backDirWidth + backDirLen + pointSize;
    if (fontHeight < 21) {
        comboWidth += 8;
    } else if (fontHeight <= 23) {
        comboWidth += 6;
    } else if (fontHeight < 25) {
        comboWidth += 10;
    } else if (fontHeight >= 27) {
        comboWidth += 3;
    }
    // qWarning()<<"comboWidth: "<<comboWidth<<", fontHeight: "<<fontHeight<<", backDirWidth: "<<backDirWidth<<", pointSize: "<<pointSize;
    return comboWidth;
}

void ImmuDataBackupWidget::onBackDirFontChanged(const QFont &font)
{
    int comboWidth = getComboWidth(m_backupDir->font());
    m_comboBox->setFixedWidth(comboWidth);
    m_noteEdit->setFixedWidth(comboWidth);
}

void ImmuDataBackupWidget::initLayout()
{
    m_mainVLayout = new QVBoxLayout(this);
    m_mainVLayout->setContentsMargins(12, 8, 12, 30);
    m_mainVLayout->setAlignment(Qt::AlignHCenter);

    m_mainVLayout->addWidget(m_title);
    m_mainVLayout->addSpacing(-6);
    m_mainVLayout->addWidget(m_titleDes);

    QHBoxLayout *backupDirTitleIconBtnHLayout = new QHBoxLayout;
    backupDirTitleIconBtnHLayout->addWidget(m_backupDirTitle);
    backupDirTitleIconBtnHLayout->addSpacing(120);
    //backupDirTitleIconBtnHLayout->addWidget(m_deleteIconBtn);
    backupDirTitleIconBtnHLayout->addWidget(m_addIconBtn);
    if (m_moreIconBtn) {
        backupDirTitleIconBtnHLayout->addWidget(m_moreIconBtn);
    }
    m_mainVLayout->addLayout(backupDirTitleIconBtnHLayout);
    m_mainVLayout->addSpacing(5);

    initTableView();
    m_mainVLayout->addWidget(m_tableView);
    m_mainVLayout->addSpacing(20);

    QHBoxLayout *backupDirComboBoxHLayout = new QHBoxLayout;
    backupDirComboBoxHLayout->setContentsMargins(0, 0, 0, 0);
    backupDirComboBoxHLayout->addWidget(m_backupDir);
    backupDirComboBoxHLayout->addSpacing(8);
    backupDirComboBoxHLayout->addWidget(m_comboBox);
    m_mainVLayout->addSpacing(20);
    m_mainVLayout->addLayout(backupDirComboBoxHLayout);
    m_mainVLayout->addSpacing(10);

    QHBoxLayout *noteHLayout = new QHBoxLayout;
    noteHLayout->setContentsMargins(0, 0, 0, 0);
    noteHLayout->addWidget(m_noteLabel, 0, Qt::AlignTop);
    noteHLayout->addSpacing(8);
    noteHLayout->addWidget(m_noteEdit);
    m_mainVLayout->addLayout(noteHLayout);

    QHBoxLayout *charCountHLayout = new QHBoxLayout;
    charCountHLayout->setContentsMargins(0, 0, 0, 0);
    charCountHLayout->addWidget(m_noteEditCount, 0, Qt::AlignRight);
    charCountHLayout->addSpacing(10);
    m_mainVLayout->addSpacing(-44);
    m_mainVLayout->addLayout(charCountHLayout);

    m_mainVLayout->addSpacing(3);

    QHBoxLayout *loadingHLayout = new QHBoxLayout;
    loadingHLayout->setContentsMargins(0, 0, 0, 0);
    loadingHLayout->addStretch();
    loadingHLayout->addWidget(m_spinner);
    loadingHLayout->addSpacing(10);
    loadingHLayout->addWidget(m_tips);
    loadingHLayout->addStretch();
    m_mainVLayout->addLayout(loadingHLayout);
    m_mainVLayout->addSpacing(3);

    QHBoxLayout *cancelStartBtnHBoxLayout = new QHBoxLayout;
    cancelStartBtnHBoxLayout->setAlignment(Qt::AlignHCenter);
    cancelStartBtnHBoxLayout->addStretch();
    cancelStartBtnHBoxLayout->addWidget(m_startBtn);
    m_mainVLayout->addLayout(cancelStartBtnHBoxLayout);

    connect(m_addIconBtn, &DIconButton::clicked, this, &ImmuDataBackupWidget::onAddBtnClicked);
    if (m_moreIconBtn) {
        connect(m_moreIconBtn, &ImmuBackupIconComboBox::combCurrentIndexChanged, this, &ImmuDataBackupWidget::onMoreIconBtnCurrentIndexChanged);
    }
    connect(m_startBtn, &QPushButton::clicked, this, &ImmuDataBackupWidget::onStartBackup);
}

void ImmuDataBackupWidget::initTableView()
{
    m_tableView->setFixedHeight(260);
    m_tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
    m_tableView->setSortingEnabled(false);
    m_tableView->setFocusPolicy(Qt::NoFocus);
    m_tableView->setRowBackgroundDelta(10);

    auto optIdItem = new QStandardItem(tr("ID."));
    optIdItem->setTextAlignment(Qt::AlignVCenter);

    auto directoryItem = new QStandardItem(tr("Directory"));
    directoryItem->setTextAlignment(Qt::AlignVCenter);

    auto actionItem = new QStandardItem(tr("Action"));
    actionItem->setTextAlignment(Qt::AlignVCenter);


    m_model->setHorizontalHeaderItem(TABLE_COL_OPT_ID, optIdItem);
    m_model->setHorizontalHeaderItem(TABLE_COL_DIR, directoryItem);
    m_model->setHorizontalHeaderItem(TABLE_COL_ACTION, actionItem);

//    m_tableView->header()->setSectionResizeMode(QHeaderView::Stretch);
    m_tableView->setColumnWidth(TABLE_COL_OPT_ID, 20);
    m_tableView->setColumnWidth(TABLE_COL_DIR, 610);
    m_tableView->setColumnWidth(TABLE_COL_ACTION, 30);

    m_tableView->hideColumn(TABLE_COL_OPT_ID);

    // 禁止拖动列宽
    QHeaderView *headerView = m_tableView->header();
    headerView->setSectionResizeMode(TABLE_COL_OPT_ID, QHeaderView::ResizeMode::Fixed);
    headerView->setSectionResizeMode(TABLE_COL_DIR, QHeaderView::ResizeMode::Fixed);
    headerView->setSectionResizeMode(TABLE_COL_ACTION, QHeaderView::ResizeMode::Fixed);
}

void ImmuDataBackupWidget::setDestDevice(const QJsonObject &jsonObject)
{
    m_comboBox->clear();
    m_partitionList.clear();
    QJsonArray disks = jsonObject.value("disks").toArray();
    for (auto a : disks) {
        QString diskName = a.toObject().value("disk").toString();
        QJsonArray partitions = a.toObject().value("partitions").toArray();
        for (auto p : partitions) {
            Partition partition;
            partition.unmarshal(p.toObject());
            m_partitionList.append(partition);
            m_comboBox->addItem(QString("%1(%2),  %3,  (%4/%5)").arg(diskName).arg(partition.fsType)
                                        .arg(partition.name).arg(Utils::byte2DisplaySize(partition.used)).arg(Utils::byte2DisplaySize(partition.size)));
        }
    }

    if (m_partitionList.isEmpty()) {
        m_startBtn->setEnabled(false);
        // this->setTips(tr("Please insert a removable disk, supported format: ext4, btrfs, xfs"));
        // this->setTipsStyleSheet("QLabel {"
        //                         "color: #FF5736;"
        //                         "}");
        m_comboBox->setPlaceholderText(tr("Please insert a removable disk, supported format: ext4, btrfs, xfs"));
        this->setAddIconBtnEnable(false);
        this->setMoreIconBtnEnable(false);
    } else {
        this->setTips("");
        this->setAddIconBtnEnable(true);
        this->setMoreIconBtnEnable(true);
    }
}

QString ImmuDataBackupWidget::getDestDeviceUUID()
{
    if (m_comboBox->count() == m_partitionList.size()) {
        Partition selectPartition = m_partitionList.at(m_comboBox->currentIndex());
        if (!selectPartition.fsTypeSupportedDataBackup) {
            DDialog dlg(this);
            dlg.setMessage(::QObject::tr("The file system of the device is unsupported. Please select one in ext4, btrfs, xfs format."));
            dlg.setIcon(QIcon::fromTheme("dialog-warning"));
            dlg.setAccessibleName("ImmuDataBackupWidget_deviceUnsupportedDDialog");
            QRect rect = geometry();
            dlg.move(rect.center());
            dlg.moveToCenter();
            dlg.exec();
            return "";
        }
        return selectPartition.uuid;
    }

    return "";
}

void ImmuDataBackupWidget::onAddBtnClicked(bool clicked)
{
    QString userPath = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
    DFileDialog dialog(this);
    dialog.setFileMode(DFileDialog::ExistingFiles);
    dialog.setDirectory(userPath);
    //dialog.setNameFilter(filter);
    dialog.setOption(QFileDialog::HideNameFilterDetails);
    //dialog.setWindowTitle(tr("Import Photos and Videos"));
    dialog.setAllowMixedSelection(true);
    dialog.setAccessibleName("ImmuDataBackupWidget_AddBtnClickedDFileDialog");
    const int mode = dialog.exec();
    if (mode != QDialog::Accepted) {
        return;
    }
    const QStringList &fileList = dialog.selectedFiles();
    if (fileList.isEmpty()) {
        return;
    }

    bool enableStartBtn = false;
    static QString curUserName = Utils::getUserName();
    QString homeBindPath = m_bindDirMap["/home"];
    QString userSupportPath = userPath;
    if (!homeBindPath.isEmpty()) {
        if (homeBindPath.endsWith("/")) {
            userSupportPath = homeBindPath + curUserName;
        } else {
            userSupportPath = homeBindPath + "/" + curUserName;
        }
    }
    QDir homeDir("/home");
    QString realHomeDir = homeDir.canonicalPath();
    if (m_isImmutable) {
        if ("/home" != realHomeDir) {
            userSupportPath = realHomeDir + "/" + curUserName;
        }
    }

    QStringList supportPathList;
    QString homeDirErrMsg;
    QString pathExistErrMsg;
    int existPathNum = 0;
    for (const QString &path : fileList) {
        if (!path.startsWith(userPath) && !path.startsWith(userSupportPath)) {
            homeDirErrMsg = tr("Please select data in the current user's home directory");
        } else {
            auto items = m_model->findItems(path, Qt::MatchExactly, TABLE_COL_DIR);
            if (!items.isEmpty()) {
                ++existPathNum;
                if (pathExistErrMsg.isEmpty()) {
                    pathExistErrMsg = tr("The selected directory is in included in %1").arg(path);
                }
            } else {
                supportPathList.append(path);
            }
        }
    }

    if (existPathNum > 1) {
        pathExistErrMsg = QString("%1 ...").arg(pathExistErrMsg);
    }

    if (!homeDirErrMsg.isEmpty()) {
        DDialog dialog(this);
        dialog.setMessage(homeDirErrMsg);
        dialog.setIcon(QIcon::fromTheme("dialog-warning"));
        dialog.setAccessibleName("ImmuDataBackupWidget_AddPathHomeWarningDialog");
        QRect rect = geometry();
        dialog.move(rect.center());
        dialog.moveToCenter();
        dialog.exec();
    }

    if (!pathExistErrMsg.isEmpty()) {
        DDialog dialog(this);
        dialog.setMessage(pathExistErrMsg);
        dialog.setIcon(QIcon::fromTheme("dialog-warning"));
        dialog.setAccessibleName("ImmuDataBackupWidget_pathExistErrMsgDialog");
        QRect rect = geometry();
        dialog.move(rect.center());
        dialog.moveToCenter();
        dialog.exec();
    }

    for (const QString &path : supportPathList) {
        int currentRow = m_model->rowCount();
        QString opID = QUuid::createUuid().toString();
        m_model->setItem(currentRow, TABLE_COL_OPT_ID, new QStandardItem(opID));
        auto pathItem = new QStandardItem(path);
        m_model->setItem(currentRow, TABLE_COL_DIR, pathItem);

        auto actionItem = new QStandardItem();
        actionItem->setAccessibleText(opID + "_deleteWidget");
        m_model->setItem(currentRow, TABLE_COL_ACTION, actionItem);
        auto deleteWidget = new ImmuBackupPathDeleteWidget;
        deleteWidget->setBackupPathInfo(opID, path);
        m_tableView->setIndexWidget(m_model->index(currentRow, TABLE_COL_ACTION), deleteWidget);
        connect(deleteWidget, &ImmuBackupPathDeleteWidget::deleteBackupPathClicked,
                this, &ImmuDataBackupWidget::onDeleteBackupPathClicked);
        enableStartBtn = true;
    }

    int n = m_model->rowCount();
    if (n <= 0) {
        m_startBtn->setEnabled(false);
    } else {
        m_startBtn->setEnabled(true);
    }
}

void ImmuDataBackupWidget::onDeleteBackupPathClicked(const QString &opID)
{
    auto items = m_model->findItems(opID, Qt::MatchExactly, TABLE_COL_OPT_ID);
    for (auto &item : items) {
        m_model->removeRow(m_model->indexFromItem(item).row());
    }

    int n = m_model->rowCount();
    if (n <= 0) {
        m_startBtn->setEnabled(false);
    }
}

void ImmuDataBackupWidget::onStartBackup()
{
    QString remark = m_noteEdit->toPlainText();
    Q_EMIT start(remark);
}

QStringList ImmuDataBackupWidget::getBackupFiles()
{
    QStringList backupFiles;
    auto root = m_model->invisibleRootItem();
    if (nullptr == root) {
        return backupFiles;
    }

    QDir homeDir("/home");
    QString realHomeDir = homeDir.canonicalPath();
    QString homePre;
    if (realHomeDir.startsWith("/var/home")) {
        homePre = "/var";
    }
    int row = 0;
    while (root->child(row) != nullptr) {
        auto item = root->child(row, TABLE_COL_DIR);
        if (item == nullptr) {
            continue;
        }

        if (m_isImmutable && !homePre.isEmpty()) {
            backupFiles <<homePre + item->text();
        } else {
            backupFiles << item->text();
        }
#ifdef QT_DEBUG
        qInfo() << item->text();
#endif
        ++row;
    }

    return backupFiles;
}

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

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

void ImmuDataBackupWidget::startSpinner()
{
    if (nullptr != m_spinner) {
        m_spinner->show();
        m_spinner->start();
    }
}

void ImmuDataBackupWidget::stopSpinner()
{
    if (nullptr != m_spinner) {
        m_spinner->stop();
        m_spinner->hide();
    }
}

void ImmuDataBackupWidget::setButtonEnable(bool enable)
{
    if (nullptr != m_startBtn) {
        m_startBtn->setEnabled(enable);
    }

    if (nullptr != m_cancelBtn) {
        m_cancelBtn->setEnabled(enable);
    }

    if (nullptr != m_addIconBtn) {
        m_addIconBtn->setEnabled(enable);
    }

    if (nullptr != m_moreIconBtn) {
        m_moreIconBtn->setEnabled(enable);
    }

    if (nullptr != m_comboBox) {
        m_comboBox->setEnabled(enable);
    }

    if (nullptr != m_noteEdit) {
        m_noteEdit->setEnabled(enable);
    }
}

QString ImmuDataBackupWidget::getNote()
{
    if (nullptr != m_noteEdit) {
        QString remark = m_noteEdit->toPlainText();
        return remark;
    }

    return "";
}

void ImmuDataBackupWidget::resetWidget()
{
    if (nullptr != m_startBtn) {
        m_startBtn->setEnabled(false);
    }

    if (nullptr != m_cancelBtn) {
        m_cancelBtn->setEnabled(true);
    }

    if (nullptr != m_comboBox) {
        m_comboBox->setEnabled(true);
    }

    if (nullptr != m_addIconBtn) {
        m_addIconBtn->setEnabled(true);
    }

    if (nullptr != m_moreIconBtn) {
        m_moreIconBtn->setEnabled(true);
    }

    if (nullptr != m_noteEdit) {
        m_noteEdit->clear();
        m_noteEdit->setEnabled(true);
    }

    if (nullptr != m_model) {
        m_model->removeRows(0, m_model->rowCount());
    }

    if (nullptr != m_tips) {
        m_tips->setText("");
    }

    if (nullptr != m_spinner) {
        m_spinner->hide();
        m_spinner->stop();
    }
}

void ImmuDataBackupWidget::setAddIconBtnEnable(bool enable)
{
    if (nullptr != m_addIconBtn) {
        m_addIconBtn->setEnabled(enable);
    }
}

void ImmuDataBackupWidget::setMoreIconBtnEnable(bool enable)
{
    if (nullptr != m_moreIconBtn) {
        m_moreIconBtn->setEnabled(enable);
    }
}

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

    this->updateNoteCharNum(num);
}

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


void ImmuDataBackupWidget::onThemeChange(Dtk::Gui::DGuiApplicationHelper::ColorType themeType)
{
    QPalette comboBoxPalette = m_comboBox->palette();
    QPalette noteEditPalette = m_noteEdit->palette();
    if (themeType == Dtk::Gui::DGuiApplicationHelper::LightType) {
        comboBoxPalette.setColor(QPalette::Light, QColor(255, 255, 255));
        comboBoxPalette.setColor(QPalette::Dark, QColor(255, 255, 255));

        noteEditPalette.setColor(QPalette::Button, QColor(255, 255, 255));
    } else {
        comboBoxPalette.setColor(QPalette::Light, QColor(40, 40, 40));
        comboBoxPalette.setColor(QPalette::Dark, QColor(40, 40, 40));

        noteEditPalette.setColor(QPalette::Button, QColor(40, 40, 40));
    }

    m_comboBox->setPalette(comboBoxPalette);
    m_noteEdit->setPalette(noteEditPalette);
}

void ImmuDataBackupWidget::onMoreIconBtnCurrentIndexChanged(const int &index)
{
    QString path="";
    if (index == 0) {
        QString vaultPath = "/home/" + Utils::getUserName() + "/.config/Vault";
        if (QDir(vaultPath).exists()) {
            path = vaultPath;
        }
    }

    if (path.isEmpty()) {
        return;
    }

    auto items = m_model->findItems(path, Qt::MatchExactly, TABLE_COL_DIR);
    if (!items.isEmpty()) {
        return;
    }

    int currentRow = m_model->rowCount();
    QString opID = QUuid::createUuid().toString();
    m_model->setItem(currentRow, TABLE_COL_OPT_ID, new QStandardItem(opID));
    auto pathItem = new QStandardItem(path);
    m_model->setItem(currentRow, TABLE_COL_DIR, pathItem);

    auto actionItem = new QStandardItem();
    actionItem->setAccessibleText(opID + "_deleteWidget");
    m_model->setItem(currentRow, TABLE_COL_ACTION, actionItem);
    auto deleteWidget = new ImmuBackupPathDeleteWidget;
    deleteWidget->setBackupPathInfo(opID, path);
    m_tableView->setIndexWidget(m_model->index(currentRow, TABLE_COL_ACTION), deleteWidget);
    connect(deleteWidget, &ImmuBackupPathDeleteWidget::deleteBackupPathClicked,
            this, &ImmuDataBackupWidget::onDeleteBackupPathClicked);

    if (m_model->rowCount() <= 0) {
        m_startBtn->setEnabled(false);
    } else {
        m_startBtn->setEnabled(true);
    }
}