#include "mainwindow.h"
#include "base/softconfigdialog.h"
#include "gutil/qgui.h"
#include "cfg.h"
#include "tools.h"
#include "device/upgradeapkdialog.h"
#include <QColorDialog>
#include <QDesktopServices>
#include <QLabel>
#include <QMenu>
#include <QMessageBox>
#include <QProcess>
#include <QSettings>
#include <QButtonGroup>
#include <QHeaderView>
#include <QStandardPaths>
#include "QSimpleUpdater.h"

QWidget *gMainWin;
extern QPoint gPlayPos;

class ImgBtn : public QToolButton {
public:
    ImgBtn() {
        auto policy = sizePolicy();
        policy.setHorizontalPolicy(QSizePolicy::Preferred);
        setSizePolicy(policy);
        connect(this, &QToolButton::toggled, this, [this](bool checked) {
            setIcon(icons[checked ? 1 : 0]);
        });
    }
    void setIcons(const QIcon &unchecked, const QIcon &checked) {
        setIcon(unchecked);
        icons[0] = unchecked;
        icons[1] = checked;
    }
protected:
#if(QT_VERSION_MAJOR > 5)
    void enterEvent(QEnterEvent *) override {
#else
    void enterEvent(QEvent *) override {
#endif
        if(this->isChecked()) return;
        setIcon(icons[1]);
    }
    void leaveEvent(QEvent *) override {
        if(this->isChecked()) return;
        setIcon(icons[0]);
    }
    QIcon icons[2];
};

MainWindow::MainWindow(QWidget *parent) : BaseWin(parent) {
    setAttribute(Qt::WA_AlwaysShowToolTips);
    gMainWin = this;
    auto menuLang = new QMenu();

    auto actCN = new QAction("中文");
    actCN->setCheckable(true);
    actCN->setObjectName("zh_CN");
    menuLang->addAction(actCN);

    auto actTW = new QAction("中文繁体");
    actTW->setCheckable(true);
    actTW->setObjectName("zh_TW");
    menuLang->addAction(actTW);

    auto actEn = new QAction("English");
    actEn->setCheckable(true);
    actEn->setObjectName("en");
    menuLang->addAction(actEn);

    auto actJa = new QAction("日本語");
    actJa->setCheckable(true);
    actJa->setObjectName("ja");
    menuLang->addAction(actJa);

    langGrp = new QActionGroup(menuLang);
    langGrp->addAction(actCN);
    langGrp->addAction(actTW);
    langGrp->addAction(actEn);
    langGrp->addAction(actJa);

    connect(menuLang, &QMenu::triggered, this, [this](QAction* action) {
        auto lanName = action->objectName();
        translator.load("app_"+lanName, ":/i18n");
        transQt.load("qt_"+lanName, ":/i18n");
    });

    QSettings settings;
    QString langName = settings.value("Language").toString();
    QAction *actLan = nullptr;
    if(! langName.isEmpty()) {
        if(langName.endsWith("CN")) actLan = actCN;
        else if(langName.endsWith("TW")) actLan = actTW;
        else if(langName.startsWith("en")) actLan = actEn;
        else if(langName.startsWith("ja")) actLan = actJa;
    }
    if(actLan==nullptr) {
        langName = QLocale().name();
        if(langName.endsWith("TW")) actLan = actTW;
        else if(langName.startsWith("en")) actLan = actEn;
        else if(langName.startsWith("ja")) actLan = actJa;
        else actLan = actCN;
    }

    actLan->setChecked(true);
    auto lanName = actLan->objectName();
    translator.load("app_"+lanName, ":/i18n");
    transQt.load("qt_"+lanName, ":/i18n");
    QApplication::installTranslator(&translator);
    QApplication::installTranslator(&transQt);

    auto geo = settings.value("MainGeo").toRect();
    if(geo.width()>=800 && geo.height()>=500 && geo.x()>=-600 && geo.x()<=1280 && geo.y()>=-200 && geo.y()<=800) setGeometry(geo);
    else resize(1280, 800);
    if(settings.value("MainIsMax", false).toBool()) setWindowState(Qt::WindowMaximized);

    gPlayPos = settings.value("PlayPos").toPoint();

    setWindowTitle("LedOK Express");
    icon.load(":/res/Logo.png");
    titlePos = QPointF(26, 80);
    iconPos = QPointF(38, 20);
    auto plt = palette();
    plt.setBrush(QPalette::Window, QColor(0xdddddd));
    setPalette(plt);

    //项目保存的文档路径
    QString doc_path = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
    if(!doc_path.isEmpty()) {
        QDir app_dir = QDir(doc_path + "/" + QApplication::applicationName());
        if(!app_dir.exists()) {
            QDir doc_dir(doc_path);
            doc_dir.mkdir(QApplication::applicationName());
        }
    }

    //创建一个垂直布局
    auto vBox = new QVBoxLayout(center);
    vBox->setContentsMargins(0, 0, 0, 0);
    vBox->setSpacing(0);

    //自定义的标题上的工具栏创建（语言和设置选项）
    m_wTitle = new LoQTitleBar(this);
    installEventFilter(m_wTitle);

    //水平布局，放置配置按钮，最小化，最大化，关闭按钮
    QHBoxLayout *pLayout = new QHBoxLayout(m_wTitle);
    pLayout->setContentsMargins(0, 0, 0, 0);
    pLayout->addStretch();

    bn_Setting = new QPushButton();
    bn_Setting->setIcon(QIcon(":/res/AppSetting.png"));
    bn_Setting->setToolTip(tr("Setting"));

    pLayout->addWidget(bn_Setting);
    pLayout->addWidget(m_wTitle->bn_Minimize);
    pLayout->addWidget(m_wTitle->bn_Maximize);
    pLayout->addWidget(m_wTitle->bn_Close);

    auto menu_setting = new QMenu();
    act_lang = new QAction();
    act_lang->setMenu(menuLang);
    menu_setting->addAction(act_lang);

    act_softconfiguration = new QAction(tr("Software Config"));
    connect(act_softconfiguration, &QAction::triggered, this, [this] {
        SoftConfigDialog dlg(this);
        dlg.exec();
        mBtnGrp->button(MainPage_LoraScreen)->setVisible(gShowLoraScreen);
    });
    menu_setting->addAction(act_softconfiguration);

    act_update = new QAction(tr("Check for updates"));
    connect(act_update, &QAction::triggered, this, [this] {
        QDialog dlg(this);
        dlg.setWindowFlag(Qt::WindowContextHelpButtonHint, false);
        dlg.setWindowTitle(tr("Software Update"));
        dlg.resize(500, 400);

        auto vBox = new VBox(&dlg);

        auto label = new QLabel(tr("CurVersion")+": "+APP_VERSION);
        auto font = label->font();
        font.setPixelSize(18);
        label->setFont(font);
        vBox->addWidget(label);

        auto fdVerInfo = new QTextEdit;
        fdVerInfo->setReadOnly(true);
        vBox->addWidget(fdVerInfo);

        auto btnUpdate = new QPushButton(tr("Update"));
        btnUpdate->setFixedWidth(80);
        connect(btnUpdate, &QPushButton::clicked, this, [] {
            QSimpleUpdater::getInstance()->setNotifyOnUpdate(UpdVerUrl, true);
            QSimpleUpdater::getInstance()->setNotifyOnFinish(UpdVerUrl, false);
            QSimpleUpdater::getInstance()->setMandatoryUpdate(UpdVerUrl, true);
            QSimpleUpdater::getInstance()->checkForUpdates(UpdVerUrl);
        });
        vBox->addWidget(btnUpdate, 0, Qt::AlignHCenter);

        auto updater = QSimpleUpdater::getInstance();
        connect(updater, &QSimpleUpdater::checkingFinished, fdVerInfo, [fdVerInfo, btnUpdate] {
            if(QSimpleUpdater::getInstance()->getUpdateAvailable(UpdVerUrl)) fdVerInfo->setText(tr("LatestVersion:") + QSimpleUpdater::getInstance()->getLatestVersion(UpdVerUrl) + "\n" + tr("Update log:") + "\n" + QSimpleUpdater::getInstance()->getChangelog(UpdVerUrl));
            else {
                fdVerInfo->setText(tr("The current version is already the latest version") + "\n\n" + tr("Update log:") + "\n" + QSimpleUpdater::getInstance()->getChangelog(UpdVerUrl));
                btnUpdate->setVisible(false);
            }
        });
        updater->setModuleVersion(UpdVerUrl, APP_VERSION);
        updater->setNotifyOnUpdate(UpdVerUrl, false);
        updater->setNotifyOnFinish(UpdVerUrl, false);
        updater->checkForUpdates(UpdVerUrl);
        dlg.exec();
    });
    menu_setting->addAction(act_update);

    act_updatefirmware = new QAction(tr("firmware manager"));
    connect(act_updatefirmware, &QAction::triggered, this, [this] {
        UpgradeApkDialog dlg(this);
        dlg.exec();
    });
    menu_setting->addAction(act_updatefirmware);

    act_help = new QAction();
    connect(act_help, &QAction::triggered, this, [this] {
        auto act = langGrp->checkedAction();
        if(act==0) return;
        QDesktopServices::openUrl(QUrl::fromLocalFile(QCoreApplication::applicationDirPath()+"/help/"+act->objectName()+".pdf"));
    });
    menu_setting->addAction(act_help);

    actInfo = new QAction;
    connect(actInfo, &QAction::triggered, this, [this] {
        QMessageBox::information(this, tr("Info"),
                QString("SupportsSsl: ").append(QSslSocket::supportsSsl()?"true":"false")
                .append("\nSslLibraryBuildVersion: ").append(QSslSocket::sslLibraryBuildVersionString().append(" (").append(QString::number(QSslSocket::sslLibraryBuildVersionNumber())).append(")"))
                .append("\nSslLibraryVersion: ").append(QSslSocket::sslLibraryVersionString()).append(" (").append(QString::number(QSslSocket::sslLibraryVersionNumber())).append(")"));
    });
    menu_setting->addAction(actInfo);

    act_about = new QAction(tr("About"));
    connect(act_about, &QAction::triggered, this, [this] {
        QDialog dlg(this);
        dlg.setWindowFlag(Qt::WindowContextHelpButtonHint, false);
        dlg.setWindowTitle(tr("About"));

        auto hBox = new HBox(&dlg);
        hBox->setContentsMargins(24, 24, 24, 24);
        hBox->setSpacing(24);

        auto label = new QLabel;
        label->setPixmap(QPixmap(":/res/Logo.png"));
        hBox->addWidget(label);

        auto vBox = new VBox(hBox);

        label = new QLabel("LedOK Express");
        label->setAlignment(Qt::AlignCenter);
        auto font = label->font();
        font.setPixelSize(30);
        label->setFont(font);
        vBox->addWidget(label);

        label = new QLabel(APP_VERSION);
        font = label->font();
        font.setPixelSize(18);
        label->setFont(font);
        label->setAlignment(Qt::AlignCenter);
        vBox->addWidget(label);

        label = new QLabel("<a href=\"https://www.ledok.cn/\">www.ledok.cn");
        font = label->font();
        font.setPixelSize(20);
        label->setFont(font);
        label->setAlignment(Qt::AlignCenter);
        label->setOpenExternalLinks(true);
        vBox->addWidget(label);

        dlg.exec();
    });
    menu_setting->addAction(act_about);
    bn_Setting->setMenu(menu_setting);//按钮上添加下拉菜单

    QSimpleUpdater *updater = QSimpleUpdater::getInstance();
    connect(updater, &QSimpleUpdater::checkingFinished, this, [this]() {
        if(QSimpleUpdater::getInstance()->getUpdateAvailable(UpdVerUrl)) {//如果版本大于
            if(QSimpleUpdater::getInstance()->getUpdateSameVersionAvailable(UpdVerUrl)) bn_Setting->setStyleSheet("image: url(:/res/AppSetting.png);");//如果同样的版本，不显示红点提示
            else {//如果不同
                bn_Setting->setStyleSheet("image: url(:/res/AppSettingTip.png);");
                QIcon icon(":/res/reddot.png");
                act_update->setIcon(icon);
            }
        }
        else bn_Setting->setStyleSheet("image: url(:/res/AppSetting.png);");
    });
    updater->setModuleVersion(UpdVerUrl, APP_VERSION);
    updater->setNotifyOnUpdate(UpdVerUrl, false);
    updater->setNotifyOnFinish(UpdVerUrl, false);
    updater->checkForUpdates(UpdVerUrl);
    vBox->addWidget(m_wTitle);

    //设备管理，节目管理，高级节目管理页创建
    mDevicePanel = new DevicePanel(settings);
    mProgPanel = new ProgPanel(settings);
    m_wGuangYingPinWidget = new mGuangYingPinWidget();

    auto hBox = new QHBoxLayout();
    hBox->setSpacing(2);

    mBtnGrp = new QButtonGroup(this);
    hBox->addSpacing(144);
    for(int i=0; i<MainPage_End; i++) {
        auto btn = new ImgBtn();
        btn->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
        btn->setCheckable(true);
        btn->setIconSize(QSize(40,40));
        btn->setProperty("ss", "MainTab");
        if(i==MainPage_DeviceManager)    btn->setIcons(QIcon{":/res/DeviceManager_u.png"}, QIcon{":/res/DeviceManager_s.png"});
        else if(i==MainPage_ProgManager) btn->setIcons(QIcon{":/res/ProgramManager_u.png"}, QIcon{":/res/ProgramManager_s.png"});
        else if(i==MainPage_Setting)     btn->setIcons(QIcon{":/res/DeviceSetting_u.png"}, QIcon{":/res/DeviceSetting_s.png"});
        else if(i==MainPage_LoraScreen)  btn->setIcons(QIcon{":/res/GuangYingPin_u.png"}, QIcon{":/res/GuangYingPin_s.png"});
        hBox->addWidget(btn);
        mBtnGrp->addButton(btn, i);
    }

    vBox->addLayout(hBox);

    wgts[MainPage_DeviceManager] = mDevicePanel;
    wgts[MainPage_ProgManager] = mProgPanel;
    wgts[MainPage_Setting] = mDevicePanel;
    wgts[MainPage_LoraScreen] = m_wGuangYingPinWidget;

    vBox->addWidget(wgts[curIndex]);//初始化响应页面为终端管理页面

    mBtnGrp->button(curIndex)->setChecked(true);

    connect(mBtnGrp, &QButtonGroup::idToggled, this, [this, vBox](int id, bool checked) {
        if(!checked || id==curIndex) return;
        if((id==MainPage_DeviceManager && curIndex==MainPage_Setting) || (id==MainPage_Setting && curIndex==MainPage_DeviceManager)){
            mDevicePanel->ShowDevicesInfoOrControlWidget(id);
            curIndex = id;
        } else {
            vBox->replaceWidget(wgts[curIndex], wgts[id]);
            wgts[curIndex]->setParent(0);
            curIndex = id;
            if(curIndex == MainPage_DeviceManager || curIndex == MainPage_Setting) {
                //开启UDP定时器
                mDevicePanel->mUdpTimer.start(60000);
                int cnt = mDevicePanel->mDeviceTable->topLevelItemCount();
                for(int i=0; i<cnt; i++) {
                    auto item = static_cast<DeviceItem*>(mDevicePanel->mDeviceTable->topLevelItem(i));
                    item->mHeartbeatTimer.start(60000);
                    item->DeviceItemHttpPost();
                }
                mDevicePanel->ShowDevicesInfoOrControlWidget(id);
            }
        }
    });

    hBox = new QHBoxLayout();
    m_pOneKeyCheckCard = new QPushButton;
    m_pOneKeyCheckCard->setCursor(Qt::PointingHandCursor);
    m_pOneKeyCheckCard->setProperty("ssType", "progManageTool");
    connect(m_pOneKeyCheckCard, &QPushButton::clicked, this, [this] {
        auto res = QMessageBox::warning(this, tr("Tip Info"), tr("RestoreLedCardIpByUdpTip"), QMessageBox::Ok, QMessageBox::Cancel);
        if(res == QMessageBox::Ok) mDevicePanel->RestoreLedCardIpByUdpCmd();
    });
    hBox->addWidget(m_pOneKeyCheckCard);
    hBox->addStretch();

    //hBox->addWidget(new QLabel("ver: " APP_VERSION ".2"));

    vBox->addLayout(hBox);

    gVideoCompress = settings.value("VideoCompress", true).toBool();
    gVideoTranscoding = settings.value("VideoTranscoding", true).toBool();
    gTextAntialiasing = settings.value("TextAntialiasing", false).toBool();
    gShowLoraScreen = settings.value("GuangYingPin", false).toBool();
    gWidthSplit = settings.value("WidthSplit", false).toBool();

    if(! gShowLoraScreen) mBtnGrp->button(MainPage_LoraScreen)->hide();
    if(settings.value("AddFirewallFlag").toString() !="1") {
        //添加exe到win防火墙例外
        auto appFile = QCoreApplication::applicationFilePath();
        appFile.replace('/','\\');
        QProcess cmd;
        connect(&cmd, &QProcess::readyReadStandardOutput, this, [&cmd] {
            qDebug()<<"out"<<QString::fromLocal8Bit(cmd.readAllStandardOutput());
        });
        connect(&cmd, &QProcess::readyReadStandardError, this, [&cmd] {
            qDebug()<<"err"<<QString::fromLocal8Bit(cmd.readAllStandardError());
        });
        qDebug()<<"Add Firewall"<<appFile;
        cmd.start("netsh advfirewall firewall add rule name=\"allow LedOK\" dir=in program=\""+appFile+"\"", {"security=authnoencap", "action=allow"});
        cmd.waitForFinished();

        appFile = QApplication::applicationDirPath()+"\\LedSet\\LedSet3.0.exe";
        appFile.replace('/','\\');
        qDebug()<<"Add Firewall"<<appFile;
        cmd.start("netsh advfirewall firewall add rule name=\"allow LedOK\" dir=in program=\""+appFile+"\"", {"security=authnoencap", "action=allow"});
        cmd.waitForFinished();
        settings.setValue("AddFirewallFlag", "1");
    };

    transUi();

    int ci = 0;
    int grays[] = {0, 0x22, 0x44, 0x66, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff};
    for(; ci < 12; ci++) QColorDialog::setStandardColor(ci, QColor(grays[ci], grays[ci], grays[ci]));
    int higs[] = {0x80, 0xff, 0xff};
    int mids[] = {0x40, 0x80, 0xbf};
    int lows[] = {   0,    0, 0x7f};
    for(int i=0; i<3; i++) {
        QColorDialog::setStandardColor(ci++, QColor(higs[i], lows[i], lows[i]));
        QColorDialog::setStandardColor(ci++, QColor(higs[i], higs[i], lows[i]));
        QColorDialog::setStandardColor(ci++, QColor(lows[i], higs[i], lows[i]));
        QColorDialog::setStandardColor(ci++, QColor(lows[i], higs[i], higs[i]));
        QColorDialog::setStandardColor(ci++, QColor(lows[i], lows[i], higs[i]));
        QColorDialog::setStandardColor(ci++, QColor(higs[i], lows[i], higs[i]));

        QColorDialog::setStandardColor(ci++, QColor(higs[i], lows[i], mids[i]));
        QColorDialog::setStandardColor(ci++, QColor(higs[i], mids[i], lows[i]));
        QColorDialog::setStandardColor(ci++, QColor(mids[i], higs[i], lows[i]));
        QColorDialog::setStandardColor(ci++, QColor(lows[i], higs[i], mids[i]));
        QColorDialog::setStandardColor(ci++, QColor(lows[i], mids[i], higs[i]));
        QColorDialog::setStandardColor(ci++, QColor(mids[i], lows[i], higs[i]));
    }

//    auto btn = new QPushButton("Test");
//    hBox->addWidget(btn);
//    connect(btn, &QPushButton::clicked, btn, [this] {
//        test();
//    });
}
void MainWindow::test() {
    QNetworkRequest request{QUrl{"http://localhost/stock/test/timeout"}};
    request.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy);
    request.setTransferTimeout(4000);
    auto doReply = [](QNetworkReply *reply) {
        auto err = reply->error();
        if(err != QNetworkReply::NoError) {
            qDebug()<<"Error"<<err;
            return;
        }
        auto status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
        if(status != 200) {
            qDebug()<<"status"<<status;
            return;
        }
        qDebug()<<"reply url"<<reply->url();
        auto resp = reply->readAll();
        qDebug()<<"resp"<<resp;
    };
    auto reply = Tools::netManager().get(request);
    connect(reply, &QNetworkReply::finished, this, [reply, doReply, request] {
        reply->deleteLater();
        if(reply->error() != QNetworkReply::OperationCanceledError) {
            doReply(reply);
            return;
        }
        qDebug()<<"timeout again";
        auto reply = Tools::netManager().get(request);
        reply->connect(reply, &QNetworkReply::finished, reply, [reply, doReply] {
            reply->deleteLater();
            doReply(reply);
        });
    });
}

MainWindow::~MainWindow() {
    QSettings settings;
    auto act = langGrp->checkedAction();
    if(act) settings.setValue("Language", act->objectName());
    settings.setValue("MainGeo", normalGeometry());
    settings.setValue("MainIsMax", isMaximized());
    settings.setValue("PlayPos", gPlayPos);
    if(mDevicePanel->fdIP) {
        auto ipstr = mDevicePanel->fdIP->toPlainText();
        if(! ipstr.isEmpty()) settings.setValue("SpecifyIP", ipstr);
        else settings.remove("SpecifyIP");
    }
    if(m_pTimerSendResoreIpOneKey!=nullptr) {
        if(m_pTimerSendResoreIpOneKey->isActive()) m_pTimerSendResoreIpOneKey->stop();
        delete m_pTimerSendResoreIpOneKey;
    }
    settings.setValue("ProgramListSortColumn", mProgPanel->mProgTree->sortColumn());
    settings.setValue("ProgramListSortOrder", mProgPanel->mProgTree->header()->sortIndicatorOrder());
}
void MainWindow::changeEvent(QEvent *event) {
    BaseWin::changeEvent(event);
    if(event->type() == QEvent::LanguageChange) transUi();
}
void MainWindow::transUi() {
    m_wTitle->refreshLable();
    mBtnGrp->button(MainPage_DeviceManager)->setText(tr("Device"));
    mBtnGrp->button(MainPage_ProgManager)->setText(tr("Program"));
    mBtnGrp->button(MainPage_Setting)->setText(tr("Control"));
    mBtnGrp->button(MainPage_LoraScreen)->setText(tr("GuangYinPin"));
    m_pOneKeyCheckCard->setText(tr("Check card"));
    act_lang->setText(tr("Language"));
    act_help->setText(tr("Help"));
    actInfo->setText(tr("Info"));
    act_about->setText(tr("About"));
    act_update->setText(tr("Check for updates"));
    act_updatefirmware->setText(tr("firmware manager"));
    act_softconfiguration->setText(tr("Software Config"));
    bn_Setting->setToolTip(tr("Setting"));
}
