#include "ctrlpowerpanel.h"
#include "globaldefine.h"
#include "deviceitem.h"
#include "devicepanel.h"
#include "base/waitingdlg.h"
#include "gutil/qnetwork.h"
#include "tools.h"
#include <QMessageBox>
#include <QTimeEdit>
#include <QJsonArray>
#include <QSettings>

CtrlPowerPanel::CtrlPowerPanel() {
    auto vBox = new VBox(this);

    lbScreenCfg = new QLabel;
    lbScreenCfg->setAlignment(Qt::AlignCenter);
    vBox->addWidget(lbScreenCfg);

    auto hBox = new HBox(vBox);
    hBox->addStretch();

    fdManual = new QRadioButton;
    hBox->addWidget(fdManual);
    hBox->addSpacing(40);

    fdSchedule = new QRadioButton;
    hBox->addWidget(fdSchedule);
    hBox->addStretch();

    auto stack = new QStackedLayout(vBox);
    {
        auto vBox = new VBox(stack);
        vBox->addSpacing(20);

        auto hBox = new HBox(vBox);
        hBox->addStretch();

        lbScreen = new QLabel;
        hBox->addWidget(lbScreen);

        fdScreen = new SwitchControl;
        fdScreen->setMinimumSize(QSize(80, 33));
        fdScreen->setSliderColor(QColor(0, 0, 0), QColor(0, 160, 230));
        fdScreen->setBgColor(QColor(200,200,200), QColor(0x00cc00));
        fdScreen->setTextColor(QColor(100,100,100), QColor(0, 160, 230));
        connect(fdScreen, &SwitchControl::checkedChanged, this, [this](bool checked) {
            if(gSelCards.isEmpty()) {
                QMessageBox::information(this, tr("Tip"), tr("NoSelectedController"));
                return;
            }
            QJsonObject json;
            json.insert("_id", "SetScreenOn");
            json.insert("_type", "SetScreenOn");
            json.insert("on", checked);
            if(gSelCards.count() == 1) {
                auto waitingDlg = new WaitingDlg(this, (checked ? tr("SetScreenOn") : tr("SetScreenOff"))+" ...");
                Def_CtrlReqPre
                connect(reply, &QNetworkReply::finished, this, [=] {
                    Def_CtrlSetReqAfter
                });
            } else {
                if(checked) foreach(auto card, gSelCards) {
                    Def_CtrlSetMulti(tr("SetScreenOn"))
                }
                else foreach(auto card, gSelCards) {
                    Def_CtrlSetMulti(tr("SetScreenOff"))
                }
            }
        });
        hBox->addWidget(fdScreen);
        hBox->addStretch();

        btnScreenGet = new QPushButton;
        btnScreenGet->setMinimumSize(QSize(60, 30));
        btnScreenGet->setProperty("ssType", "progManageTool");
        connect(btnScreenGet, &QPushButton::clicked, this, [this] {
            if(gSelCards.isEmpty()) {
                QMessageBox::information(this, tr("Tip"), tr("NoSelectedController"));
                return;
            }
            QJsonObject json;
            json.insert("_id", "IsScreenOn");
            json.insert("_type", "IsScreenOn");
            if(gSelCards.count() == 1) {
                auto waitingDlg = new WaitingDlg(this, tr("IsScreenOn")+" ...");
                Def_CtrlReqPre
                connect(reply, &QNetworkReply::finished, this, [=] {
                    Def_CtrlSingleGetReply
                    waitingDlg->success();
                    fdScreen->setCheckedStatus(json["on"].toBool());
                    auto item = findItem(card.id);
                    if(item) {
                        item->mCard.isScreenOn = json["on"].toBool();
                        item->setForeground(DeviceTable_Power, item->mCard.isScreenOn ? Qt::green : Qt::red);
                        item->setData(DeviceTable_Power, 0, item->mCard.isScreenOn ? tr("On") : tr("Off"));
                    }
                });
            } else {
                foreach(auto card, gSelCards) {
                    auto reply = NetReq("http://"+card.ip+":2016/settings").timeout(120000).post(json);
                    connect(reply, &QNetworkReply::finished, this, [=] {
                        QJsonDocument json;
                        QString err = checkReplyForJson(reply, &json);
                        if(err.isEmpty()) {
                            err = json["on"].toBool() ? tr("On") : tr("Off");
                            auto item = findItem(card.id);
                            if(item) {
                                item->mCard.isScreenOn = json["on"].toBool();
                                item->setForeground(DeviceTable_Power, item->mCard.isScreenOn ? Qt::green : Qt::red);
                                item->setData(DeviceTable_Power, 0, err);
                            }
                        }
                        gFdResInfo->append(card.id+" "+tr("IsScreenOn")+" "+err);
                    });
                }
            }
        });
        vBox->addWidget(btnScreenGet, 0, Qt::AlignCenter);
        vBox->addStretch();
    }
    {
        auto vBox = new VBox(stack);
        auto hBox = new HBox(vBox);
        hBox->setSpacing(10);

        tableSche = new Table({
            {"start", "", 100},
            {"end", "", 100},
            {"0", "", 60},
            {"1", "", 60},
            {"2", "", 60},
            {"3", "", 60},
            {"4", "", 60},
            {"5", "", 60},
            {"6", "", 60}
        });
        tableSche->setDefs();

        pushButtonAdd = new QPushButton;
        pushButtonAdd->setMinimumSize(QSize(60, 30));
        pushButtonAdd->setProperty("ssType", "progManageTool");
        connect(pushButtonAdd, &QPushButton::clicked, this, [this] {
            int row = tableSche->appendRow();
            auto timeEdit = new QTimeEdit(QTime(0, 0));
            timeEdit->setDisplayFormat("HH:mm");
            timeEdit->setAlignment(Qt::AlignCenter);
            tableSche->setCellWidget(row, "start", timeEdit);

            timeEdit = new QTimeEdit(QTime(1, 0));
            timeEdit->setDisplayFormat("HH:mm");
            timeEdit->setAlignment(Qt::AlignCenter);
            tableSche->setCellWidget(row, "end", timeEdit);

            for(int i=0; i<7; i++) {
                auto fd = new QCheckBox;
                fd->setChecked(true);
                tableSche->setCellWidget(row, QString::number(i), fd);
            }
        });
        hBox->addWidget(pushButtonAdd);

        pushButtonDelete = new QPushButton;
        pushButtonDelete->setMinimumSize(QSize(60, 30));
        pushButtonDelete->setProperty("ssType", "progManageTool");
        connect(pushButtonDelete, &QPushButton::clicked, this, [this] {
            auto selected = tableSche->selectedRanges();
            if(! selected.isEmpty()) tableSche->model()->removeRows(selected[0].topRow(), selected[0].rowCount());
        });
        hBox->addWidget(pushButtonDelete);

        pushButtonClear = new QPushButton;
        pushButtonClear->setMinimumSize(QSize(60, 30));
        pushButtonClear->setProperty("ssType", "progManageTool");
        connect(pushButtonClear, &QPushButton::clicked, tableSche, &Table::clearRows);
        hBox->addWidget(pushButtonClear);
        hBox->addStretch();

        pushButtonImport = new QPushButton;
        pushButtonImport->setMinimumSize(QSize(0, 30));
        pushButtonImport->setProperty("ssType", "progManageTool");
        connect(pushButtonImport, &QPushButton::clicked, this, [this] {
            auto dir = QSettings().value("CtrlScheduleDir").toString();
            if(dir.isEmpty()) dir = "/";
            QString scheFile = QFileDialog::getOpenFileName(this, tr("Import File"), dir, tr("PowerSchedule (*.pjs)"));
            if(scheFile.isEmpty()) return;
            QFile scheQFile(scheFile);
            if(! scheQFile.open(QIODevice::ReadOnly)) return;
            auto data = scheQFile.readAll();
            scheQFile.close();
            restoreScheduleJson(QJsonDocument::fromJson(data).object());
        });
        hBox->addWidget(pushButtonImport);

        pushButtonExport = new QPushButton;
        pushButtonExport->setMinimumSize(QSize(0, 30));
        pushButtonExport->setProperty("ssType", "progManageTool");
        connect(pushButtonExport, &QPushButton::clicked, this, [this] {
            QSettings settings;
            auto dir = settings.value("CtrlScheduleDir").toString();
            if(dir.isEmpty()) dir = "/";
            QString scheFile = QFileDialog::getSaveFileName(this, tr("Save File"), dir, tr("PowerSchedule (*.pjs)"));
            if(scheFile.isEmpty()) return;
            settings.setValue("CtrlScheduleDir", QFileInfo(scheFile).absolutePath());
            QFile scheQFile(scheFile);
            if(! scheQFile.open(QIODevice::WriteOnly)) return;
            scheQFile.write(QJsonDocument(getScheduleJson()).toJson());
            scheQFile.close();
        });
        hBox->addWidget(pushButtonExport);

        labelPowerScheduleTip = new QLabel;
        labelPowerScheduleTip->setWordWrap(true);
        vBox->addWidget(labelPowerScheduleTip);

        vBox->addWidget(tableSche);

        hBox = new HBox(vBox);
        hBox->addStretch();

        pushButtonApply = new QPushButton;
        pushButtonApply->setProperty("ssType", "progManageTool");
        pushButtonApply->setMinimumSize(QSize(60, 30));
        connect(pushButtonApply, &QPushButton::clicked, this, [this] {
            if(gSelCards.isEmpty()) {
                QMessageBox::information(this, tr("Tip"), tr("NoSelectedController"));
                return;
            }
            if(tableSche->rowCount()==0) clearSche();
            else {
                QJsonObject json;
                json.insert("_id", "SetTimingScreenTask");
                json.insert("_type", "SetTimingScreenTask");
                json.insert("screenTask", getScheduleJson());
                if(gSelCards.count() == 1) {
                    auto waitingDlg = new WaitingDlg(this, tr("SetTimingScreenTask"));
                    Def_CtrlReqPre;
                    connect(reply, &QNetworkReply::finished, this, [=] {
                        Def_CtrlSetReqAfter
                    });
                } else {
                    foreach(auto card, gSelCards) {
                        Def_CtrlSetMulti(tr("SetTimingScreenTask"))
                    }
                }
            }
        });
        hBox->addWidget(pushButtonApply);
        hBox->addStretch();

        pushButtonClearSchedule = new QPushButton;
        pushButtonClearSchedule->setMinimumSize(QSize(0, 30));
        pushButtonClearSchedule->setProperty("ssType", "progManageTool");
        connect(pushButtonClearSchedule, &QPushButton::clicked, this, [this] {
            if(gSelCards.isEmpty()) {
                QMessageBox::information(this, tr("Tip"), tr("NoSelectedController"));
                return;
            }
            clearSche();
        });
        hBox->addWidget(pushButtonClearSchedule);
        hBox->addStretch();

        pushButtonReadback = new QPushButton;
        pushButtonReadback->setMinimumSize(QSize(0, 30));
        pushButtonReadback->setProperty("ssType", "progManageTool");
        connect(pushButtonReadback, &QPushButton::clicked, this, [this] {
            if(gSelCards.isEmpty()) {
                QMessageBox::information(this, tr("Tip"), tr("NoSelectedController"));
                return;
            }
            QJsonObject json;
            json.insert("_id", "GetTimingScreenTask");
            json.insert("_type", "GetTimingScreenTask");
            if(gSelCards.count() == 1) {
                auto waitingDlg = new WaitingDlg(this, tr("GetTimingScreenTask"));
                Def_CtrlReqPre
                connect(reply, &QNetworkReply::finished, this, [this, reply, waitingDlg] {
                    Def_CtrlSingleGetReply
                    waitingDlg->success();
                    restoreScheduleJson(json["screenTask"].toObject());
                });
            }
        });
        hBox->addWidget(pushButtonReadback);

        hBox->addStretch();
    }

    connect(fdSchedule, &QRadioButton::toggled, stack, &QStackedLayout::setCurrentIndex);
    fdManual->setChecked(true);

    connect(gDevicePanel, &DevicePanel::sigSelectedDeviceList, this, [this] {
        if(isVisible()) init();
    });
    transUi();
}

void CtrlPowerPanel::showEvent(QShowEvent *event) {
    QWidget::showEvent(event);
    init();
}
void CtrlPowerPanel::init() {
    bool isSingle = gSelCards.count()==1;
    pushButtonReadback->setEnabled(isSingle);
    if(! isSingle) return;
    auto card = gSelCards[0];
    fdScreen->setCheckedStatus(card.isScreenOn);

    QJsonObject json;
    json.insert("_id", "GetTimingScreenTask");
    json.insert("_type", "GetTimingScreenTask");
    auto reply = NetReq("http://"+card.ip+":2016/settings").timeout(120000).post(json);
    connect(reply, &QNetworkReply::finished, this, [this, reply, card] {
        QJsonDocument json;
        QString err = checkReplyForJson(reply, &json);
        if(! err.isEmpty()) return;
        if(restoreScheduleJson(json["screenTask"].toObject())) fdSchedule->setChecked(true);
        else fdManual->setChecked(true);
    });
}

void CtrlPowerPanel::changeEvent(QEvent *event) {
    QWidget::changeEvent(event);
    if(event->type() == QEvent::LanguageChange) transUi();
}
void CtrlPowerPanel::transUi() {
    lbScreenCfg->setText(tr("Power Configuration"));
    fdManual->setText(tr("Manual"));
    fdSchedule->setText(tr("Schedule"));

    lbScreen->setText(tr("Power"));
    fdScreen->setText(tr("Off"), tr("On"));
    btnScreenGet->setText(tr("Readback"));

    tableSche->setHeaderText("start", tr("Start Time"));
    tableSche->setHeaderText("end", tr("End Time"));
    tableSche->setHeaderText("0", tr("SUN"));
    tableSche->setHeaderText("1", tr("MON"));
    tableSche->setHeaderText("2", tr("TUE"));
    tableSche->setHeaderText("3", tr("WED"));
    tableSche->setHeaderText("4", tr("THU"));
    tableSche->setHeaderText("5", tr("FRI"));
    tableSche->setHeaderText("6", tr("SAT"));

    pushButtonAdd->setText(tr("Add"));
    pushButtonApply->setText(tr("Apply"));
    pushButtonClear->setText(tr("Clear"));
    pushButtonDelete->setText(tr("Delete"));
    pushButtonImport->setText(tr("Import"));
    pushButtonExport->setText(tr("Export"));
    labelPowerScheduleTip->setText(tr("It is power off state outside the schedule time period"));
    pushButtonClearSchedule->setText(tr("Clear Schedule"));
    pushButtonReadback->setText(tr("Readback"));
}
bool CtrlPowerPanel::restoreScheduleJson(QJsonObject oTaskSync) {
    tableSche->setRowCount(0);
    auto schedules = oTaskSync["schedules"].toArray();
    foreach(QJsonValue schedule, schedules) {
        int row = tableSche->rowCount();
        tableSche->insertRow(row);

        auto timeEdit = new QTimeEdit(QTime::fromString(schedule["startTime"].toString()+":00"));
        timeEdit->setDisplayFormat("HH:mm");
        timeEdit->setAlignment(Qt::AlignCenter);
        tableSche->setCellWidget(row, "start", timeEdit);

        timeEdit = new QTimeEdit(QTime::fromString(schedule["endTime"].toString()+":00"));
        timeEdit->setDisplayFormat("HH:mm");
        timeEdit->setAlignment(Qt::AlignCenter);
        tableSche->setCellWidget(row, "end", timeEdit);

        if(schedule["filterType"].toString()=="None") for(int i=0; i<7; i++) {
            auto fd = new QCheckBox;
            fd->setChecked(true);
            tableSche->setCellWidget(row, QString::number(i), fd);
        } else if(schedule["filterType"].toString()=="Week") {
            auto weekFilter = schedule["weekFilter"].toArray();
            for(int i=0; i<7; i++) {
                auto fd = new QCheckBox;
                if(weekFilter.contains(i)) fd->setChecked(true);
                tableSche->setCellWidget(row, QString::number(i), fd);
            }
        }
    }
    return schedules.count() > 0;
}
QJsonObject CtrlPowerPanel::getScheduleJson() {
    QJsonArray schedules;
    for(int i=0; i<tableSche->rowCount(); i++) {
        QJsonObject schedule;
        schedule["timeType"]    = "Range";
        schedule["startTime"]   = static_cast<QTimeEdit*>(tableSche->cellWidget(i, "start"))->text();
        schedule["endTime"]     = static_cast<QTimeEdit*>(tableSche->cellWidget(i, "end"))->text();
        schedule["dateType"]    = "All";
        schedule["monthFilter"] = QJsonArray();
        QJsonArray weekFilter;
        for(int d=0; d<7; d++) if(static_cast<QCheckBox*>(tableSche->cellWidget(i, QString::number(d)))->isChecked()) weekFilter.append(d);
        if(weekFilter.size()>=7) {
            schedule["filterType"] = "None";
            weekFilter = QJsonArray();
        } else schedule["filterType"] = "Week";
        schedule["weekFilter"] = weekFilter;
        schedules.append(schedule);
    }
    return QJsonObject{
        {"createBy", "alahover"},
        {"name", "TimingScreen"},
        {"schedules", schedules}
    };
}
void CtrlPowerPanel::clearSche() {
    auto btn = QMessageBox::question(this, tr("Tip Info"), tr("Clear schedule task?"));
    if(btn != QMessageBox::Yes) return;
    QJsonObject json;
    json.insert("_id", "CleanTimingScreenTask");
    json.insert("_type", "CleanTimingScreenTask");
    if(gSelCards.count() == 1) {
        auto waitingDlg = new WaitingDlg(this, tr("CleanTimingScreenTask"));
        Def_CtrlReqPre;
        connect(reply, &QNetworkReply::finished, this, [=] {
            Def_CtrlSetReqAfter
        });
    } else {
        foreach(auto card, gSelCards) {
            Def_CtrlSetMulti(tr("CleanTimingScreenTask"))
        }
    }
}