#include "boot.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QDebug>
#include <polkit-qt5-1/polkitqt1-authority.h>
#include <kysdk/applications/accessinfohelper.h>
using namespace kdk;

#include <kysdk/kysdk-system/libkysysinfo.h>

#include "lightlabel.h"

#include "grubverifydialog.h"
#include "ukcccommon.h"
using namespace ukcc;

enum TaskType {
    GRUBVERIFY,
    BOOTDELAY,
    DEFAULTBOOT,
};

#define DEFAULTLISTHEIGHT 240
Boot::Boot() : m_firstLoad(true)
{
    m_pluginName = tr("Boot");
    m_pluginType = COMMONINFO;
}

Boot::~Boot()
{
}

QString Boot::plugini18nName()
{
    return m_pluginName;
}

int Boot::pluginTypes()
{
    return m_pluginType;
}

QWidget *Boot::pluginUi()
{
    if (m_firstLoad) {
        m_firstLoad = false;
        m_pPluginWidget = new QWidget;
        m_pPluginWidget->setAttribute(Qt::WA_DeleteOnClose);

        initUI(m_pPluginWidget);

        m_pUkccSystemDbus = new QDBusInterface("com.control.center.qt.systemdbus",
                                          "/",
                                          "com.control.center.interface",
                                          QDBusConnection::systemBus(), this);
        qCritical() << "default timeout = " << m_pUkccSystemDbus->timeout();
        m_pUkccSystemDbus->setTimeout(2147483647); // -1 为默认的25s超时;
        if (!m_pUkccSystemDbus->isValid()){
            qCritical() << "Create Client Interface Failed:" << QDBusConnection::systemBus().lastError();
        }

        m_pUkccSessionDbus = new QDBusInterface( "org.ukui.ukcc.session",
                                                "/Boot",
                                                "org.ukui.ukcc.session.Boot",
                                                QDBusConnection::sessionBus(), this);

        m_pUkccSessionDbus->setTimeout(2147483647); // -1 为默认的25s超时;
        if (!m_pUkccSessionDbus->isValid()){
            qCritical() << "Create Client Interface Failed:" << QDBusConnection::sessionBus().lastError();
        }

        m_pukccGsetting = new QGSettings(UKCC_SCHAME, QByteArray(), this);

        initConnection();
    }
    return m_pPluginWidget;
}

const QString Boot::name() const
{
    return QStringLiteral("Boot");
}

bool Boot::isShowOnHomePage() const
{
    return true;
}

QIcon Boot::icon() const
{
    return QIcon::fromTheme("ukui-bootmenu-symbolic");
}

bool Boot::isEnable() const
{
    // icbc项目要求隐藏
    QString platformName = QString(QLatin1String(kdk_system_get_appScene()));
    qDebug() << "platformName = " << platformName;
    if (platformName.contains("ICBC", Qt::CaseInsensitive)) {
        return false;
    }
    return true;
}

void Boot::initUI(QWidget *widget)
{
    QVBoxLayout *mainVLayout = new QVBoxLayout(widget);
    mainVLayout->setContentsMargins(0, 0, 0, 0);

    KLabel *bootTitleLabel = new KLabel(m_pPluginWidget);
    bootTitleLabel->setContentsMargins(16,0,0,0);
    KDK_EXTEND_ALL_INFO_FORMAT(bootTitleLabel, name(), "", "");
    //~ contents_path /Boot/Boot
    bootTitleLabel->setText(tr("Boot"));
    bootTitleLabel->setContentsMargins(14,0,0,0);

    QFrame *bootFrame = new QFrame(m_pPluginWidget);
    bootFrame->setFrameShape(QFrame::Shape::Box);
    bootFrame->setMinimumSize(550, 80);
    bootFrame->setMaximumSize(16777215, 80);

    QHBoxLayout *bootHLayout = new QHBoxLayout(bootFrame);
    QVBoxLayout *leftVlayout = new QVBoxLayout(bootFrame);

    //~ contents_path /Boot/Grub verify
    m_pGrubLabel = new QLabel(tr("Grub verify"));
    KDK_EXTEND_ALL_INFO_FORMAT(m_pGrubLabel, name(), "", "");
    m_pGrubLabel->setAlignment(Qt::AlignBottom);
    m_pGrubLabel->setMinimumWidth(140);
    LightLabel *needPasswdLabel = new LightLabel(tr("Password required for Grub editing after enabling"), m_pPluginWidget);
    KDK_EXTEND_ALL_INFO_FORMAT(needPasswdLabel, name(), "", "");
    needPasswdLabel->setAlignment(Qt::AlignTop);
    m_pResetPasswdBtn = new KPushButton();
    m_pResetPasswdBtn->setText(tr("Reset password"));
    KDK_EXTEND_ALL_INFO_FORMAT(m_pResetPasswdBtn, name(), "", "");
    m_pGrubBtn = new KSwitchButton();
    KDK_EXTEND_ALL_INFO_FORMAT(m_pGrubBtn, name(), "", "");

    leftVlayout->addWidget(m_pGrubLabel);
    leftVlayout->addWidget(needPasswdLabel);
    leftVlayout->setContentsMargins(0, 0, 0, 0);

    bootHLayout->addLayout(leftVlayout);
    bootHLayout->addStretch();
    bootHLayout->addWidget(m_pResetPasswdBtn);
    bootHLayout->addSpacing(7);
    bootHLayout->addWidget(m_pGrubBtn);
    bootHLayout->setContentsMargins(12, 0, 14, 0);

    bootFrame->setLayout(bootHLayout);

    //~ contents_path /Boot/Grub Boot Delay
    m_pGrubBootDelayFrame = new ComboxWidget(tr("Grub Boot Delay"), m_pPluginWidget, UkccFrame::Around);
    m_pGrubBootDelayFrame->label()->setFixedWidth(550);
    KDK_EXTEND_ALL_INFO_FORMAT(m_pGrubBootDelayFrame->label(), name(), "BootDelayLabel", "");
    QStringList fontScale;
    fontScale << tr("1s") << tr("2s") << tr("3s") << tr("4s") << tr("5s");
    m_pGrubBootDelayFrame->comboBox()->addItems(fontScale);
    KDK_EXTEND_ALL_INFO_FORMAT(m_pGrubBootDelayFrame->comboBox(), name(), "BootDelayCombox", "");

    m_pBootOrderFrame = new QFrame(m_pPluginWidget);
    m_pBootOrderFrame->setFrameShape(QFrame::Shape::Box);
    m_pDefaultBootLabel = new KLabel(m_pPluginWidget);
    //~ contents_path /Boot/Grub Default Boot Item
    m_pDefaultBootLabel->setText(tr("Grub Default Boot Item"));
    KDK_EXTEND_ALL_INFO_FORMAT(m_pDefaultBootLabel, name(), "BootOrderLabel", "");
    QVBoxLayout *bootListLayout = new QVBoxLayout(m_pBootOrderFrame);
    bootListLayout->setContentsMargins(16, 16, 16, 16);
    m_pBootListWidget = new QListWidget(m_pBootOrderFrame);
    KDK_EXTEND_ALL_INFO_FORMAT(m_pBootListWidget, name(), "BootOrderListWidget", "");
    m_pBootListWidget->setFixedHeight(DEFAULTLISTHEIGHT);
//    m_pBootListWidget->setSizeAdjustPolicy(QListWidget::AdjustToContents); //根据qt属性调整尺寸
    m_pBootListWidget->setContentsMargins(0, 0, 0, 0);
    m_pBootListWidget->setFocusPolicy(Qt::FocusPolicy::NoFocus);
    m_pBootListWidget->setVerticalScrollMode(QAbstractItemView::ScrollMode::ScrollPerPixel);
    bootListLayout->addWidget(m_pDefaultBootLabel);
    bootListLayout->addWidget(m_pBootListWidget);
    bootListLayout->addStretch();
    m_pBootOrderFrame->setLayout(bootListLayout);

    mainVLayout->addWidget(bootTitleLabel);
    mainVLayout->addWidget(bootFrame);
    mainVLayout->addWidget(m_pGrubBootDelayFrame);
    mainVLayout->addWidget(m_pBootOrderFrame);
    mainVLayout->addStretch();

    // 判断CPU架构隐藏
    QString cpu = UkccCommon::getCpuArchitecture();
    if (cpu.contains("sw") || cpu.contains("mips")) {
        m_pGrubBootDelayFrame->setVisible(false);
        m_pBootOrderFrame->setVisible(false);
    }
}

void Boot::initConnection()
{
    initGrubVerifyStatus();
    initBootTime();

    initBootList();
    initDefaultBoot();

    connect(m_pGrubBtn, &KSwitchButton::stateChanged, this, &Boot::bootSlot);

    connect(m_pResetPasswdBtn, &QPushButton::clicked, this, &Boot::resetPasswdSlot);

    connect(m_pGrubBootDelayFrame->comboBox(), QOverload<int>::of(&QComboBox::currentIndexChanged), this, &Boot::changeBootDelay);

    QDBusConnection::sessionBus().connect(QString(), QString("/Boot"), "org.ukui.ukcc.session.Boot", "finished", this, SLOT(taskFinished(int,bool)));
}

bool Boot::authoriyGrub()
{
    PolkitQt1::Authority::Result result;

    result = PolkitQt1::Authority::instance()->checkAuthorizationSync(
            "org.control.center.qt.systemdbus.action.grub",
            PolkitQt1::UnixProcessSubject(QCoreApplication::applicationPid()),
            PolkitQt1::Authority::AllowUserInteraction);

    if (result == PolkitQt1::Authority::Yes){
        return true;
    } else {
        return false;
    }
}

void Boot::taskFinished(int type, bool reply)
{
    qDebug() << "setting finished: type = " << type << "reply = " << reply;
    if (m_pLoadingWidget) {
        m_pLoadingWidget->hide();
        m_pLoadingWidget->close();
    }
    QDBusReply<bool> grubVerify;
    if (!reply) {
        switch (type) {
        case GRUBVERIFY:
            grubVerify = m_pUkccSystemDbus->call("getGrupPasswdStatus");
            m_pGrubBtn->blockSignals(true);
            m_pGrubBtn->setChecked(grubVerify);
            m_pGrubBtn->blockSignals(false);
            m_pResetPasswdBtn->setVisible(m_pGrubBtn->isChecked());
            break;
        case BOOTDELAY:
            initBootTime();
            break;
        case DEFAULTBOOT:
            initDefaultBoot();
            break;
        default:
            break;
        }
    } else {
        // 设置成功默认启动项，将gsetting设置为true
        switch (type) {
        case DEFAULTBOOT:
            if (!m_pukccGsetting->get(SYSTEMS_SAME).toBool()) {
                m_pukccGsetting->set(SYSTEMS_SAME, true);
            }
            break;
        default:
            break;
        }
    }
}

void Boot::initBootList()
{
    QString grubMenus(kdk_system_get_grub_menu());
    grubMenus.remove("\"");
    grubMenus.remove("{");
    grubMenus.remove("}");

    qDebug() << "get boot list = " << grubMenus;
    QStringList grubMenuItem =  grubMenus.split(",");
    for (int i = 0; i < grubMenuItem.count(); i++) {
        QString tmp = grubMenuItem[i];
        QStringList item = tmp.split(":");
        if (item.size() >= 2) {
            qDebug() << "grub menu type :" << item.at(1);
            if (item.at(1) == "menuentry") {
                qDebug() << "grub menu :" << item.at(0);
                BootListWidget *appWidget = new BootListWidget(m_pBootListWidget);
                appWidget->setProperty("grubOrder", i);
                appWidget->setBootName(item.at(0));
                appWidget->showSelectedIcon(false);
                bootlist.append(appWidget);
                connect(appWidget, &BootListWidget::clicked, this, &Boot::setDefaultBoot);

                QListWidgetItem *appListWidgetItem = new QListWidgetItem(m_pBootListWidget);
                appListWidgetItem->setSizeHint(QSize(m_pBootListWidget->width(),36));
                appListWidgetItem->setFlags(Qt::NoItemFlags);
                m_pBootListWidget->addItem(appListWidgetItem);
                m_pBootListWidget->setItemWidget(appListWidgetItem, appWidget);
            }
        }
    }
}

void Boot::initDefaultBoot()
{
    if (m_pUkccSessionDbus != nullptr) {
//        QDBusReply<int> ret = m_pUkccSessionDbus->call("getGrubDefault");

        // 获取到当前系统不一致，启动项列表不进行勾选
        qDebug() << "gsetting key of system-same = " << m_pukccGsetting->get(SYSTEMS_SAME).toBool();
        if (!m_pukccGsetting->get(SYSTEMS_SAME).toBool()) {
            return;
        }

        QDBusReply<int> ret = m_pUkccSystemDbus->call("getDefaultBootItem");

        m_preBootDefault = ret;
        if (ret >= 0) {
            foreach (BootListWidget *appWidget, bootlist) {
                if (appWidget->property("grubOrder").toInt() == ret) {
                    appWidget->showSelectedIcon(true);
                } else {
                    appWidget->showSelectedIcon(false);
                }
            }
        }
    }
}

void Boot::initGrubVerifyStatus()
{
    if (m_pUkccSessionDbus != nullptr) {
//        QDBusReply<bool> ret = m_pUkccSessionDbus->call("getVerifyStatus");
        QDBusReply<bool> ret = m_pUkccSystemDbus->call("getGrupPasswdStatus");
        m_pGrubBtn->blockSignals(true);
        m_pGrubBtn->setChecked(ret);
        m_pGrubBtn->blockSignals(false);
    }

    m_pResetPasswdBtn->setVisible(m_pGrubBtn->isChecked());
}

void Boot::initBootTime()
{
    if (m_pUkccSessionDbus != nullptr) {
//        QDBusReply<int> ret = m_pUkccSessionDbus->call("getBootDelay");
        QDBusReply<int> ret = m_pUkccSystemDbus->call("getGrubBootTime");
        m_preBootDelay = ret;
        if (ret > 0 && ret <= 5) {
            m_pGrubBootDelayFrame->comboBox()->blockSignals(true);
            m_pGrubBootDelayFrame->comboBox()->setCurrentIndex(ret-1);
            m_pGrubBootDelayFrame->comboBox()->blockSignals(false);
        }
    }
}

void Boot::bootSlot(bool checked)
{
    if (checked) {
        GrubVerify *dia = new GrubVerify(m_pPluginWidget);
        QPushButton *confirmBtn = dia->getConfirmBtn();
        connect(confirmBtn, &QPushButton::clicked, this, [=](){
            setGrubPasswd(dia->getPwd(),checked);
        });
        if (dia->exec() != QDialog::Accepted) {
            m_pGrubBtn->blockSignals(true);
            m_pGrubBtn->setChecked(!checked);
            m_pGrubBtn->blockSignals(false);
            m_pResetPasswdBtn->setVisible(m_pGrubBtn->isChecked());
        }
    } else {
        setGrubPasswd("", checked);
    }

    UkccCommon::buriedSettings(name(), "open grub passwd", QString("settings"), m_pGrubBtn->isChecked() ? "true" : "false");
    m_pResetPasswdBtn->setVisible(m_pGrubBtn->isChecked());
}

void Boot::setGrubPasswd(QString pwd, bool isOpen)
{
    if (!authoriyGrub()){
        m_pGrubBtn->blockSignals(true);
        m_pGrubBtn->setChecked(!isOpen);
        m_pGrubBtn->blockSignals(false);
        return;
    }

    m_pUkccSessionDbus->call("addTask", pwd, isOpen, 0);
    showLoadingWidget(m_pGrubLabel->text());
}

void Boot::resetPasswdSlot()
{
    GrubVerify *dia =  new GrubVerify(m_pPluginWidget);
    QPushButton *confirmBtn = dia->getConfirmBtn();
    connect(confirmBtn, &QPushButton::clicked, this, [=](){
        if (!authoriyGrub()){
            return;
        }

        UkccCommon::buriedSettings(name(), m_pResetPasswdBtn->text(), QString("clicked"), m_pGrubLabel->text());

        showLoadingWidget(m_pGrubLabel->text());
        m_pUkccSessionDbus->call("addTask", dia->getPwd(), true, 0);
    });
    dia->exec();
}

void Boot::changeBootDelay(int index)
{
    if (!authoriyGrub()){
        m_pGrubBootDelayFrame->comboBox()->blockSignals(true);
        m_pGrubBootDelayFrame->comboBox()->setCurrentIndex(m_preBootDelay-1);
        m_pGrubBootDelayFrame->comboBox()->blockSignals(false);
        return;
    }

    // 启动延时 修改/etc/default/grub中GRUB_TIMEOUT,update-grub
    qDebug() << "set boot delay = " << index+1;
    m_preBootDelay = index+1;

    UkccCommon::buriedSettings(name(), m_pGrubBootDelayFrame->title(), QString("selected"), QString::number(index));

    m_pUkccSessionDbus->call("addTask", index+1, 1);
    showLoadingWidget(m_pGrubBootDelayFrame->title());
}

void Boot::setDefaultBoot(int order)
{
    // 获取到当前系统一致，设置默认启动项时不弹授权
    if (m_pukccGsetting->get(SYSTEMS_SAME).toBool()) {
        // 获取到当前系统一致并点击启动项为当前启动项，不弹授权
        QDBusReply<int> ret = m_pUkccSystemDbus->call("getDefaultBootItem");
        if (ret == order) {
            return;
        }
    }

    QString currentBootDefault;
    if (!authoriyGrub()){
        foreach (BootListWidget *appWidget, bootlist) {
            if (appWidget->property("grubOrder").toInt() == m_preBootDefault) {
                appWidget->showSelectedIcon(true);
                currentBootDefault = appWidget->getBootName();
            } else {
                appWidget->showSelectedIcon(false);
            }
        }
        return;
    }

    qDebug() << "set default boot = " << order;
    m_preBootDefault = order;
    foreach (BootListWidget *appWidget, bootlist) {
        if (appWidget->property("grubOrder").toInt() == order) {
            appWidget->showSelectedIcon(true);
        } else {
            appWidget->showSelectedIcon(false);
        }
    }

    UkccCommon::buriedSettings(name(), m_pDefaultBootLabel->text(), QString("selected"), currentBootDefault);

    showLoadingWidget(m_pDefaultBootLabel->text());
    m_pUkccSessionDbus->call("addTask", order, 2);
}

void Boot::showLoadingWidget(QString text)
{
    if (m_pLoadingWidget == nullptr) {
        QWidget *parentWidget = m_pPluginWidget->topLevelWidget();
        m_pLoadingWidget = new LoadingWidget(parentWidget, 0.4);
        m_pLoadingWidget->setGeometry(0, 0, parentWidget->geometry().width(), parentWidget->geometry().height());
    }

    m_pLoadingWidget->setLoadingText(text);
    m_pLoadingWidget->setLoading();
    m_pLoadingWidget->show();

}
