#include "MaskPageRunning.h"
#include "app/Application.h"
#include "app/AppData.h"
#include "app/Station.h"
#include "app/Device.h"
#include "common/JsonN.h"


static int CreateParamLabel(PARAM* p, int parent, int x, int y, std::string k, std::string v)
{
    PvApp::label(p, parent, x, y, 70, 30, k, QSS::LABEL_KEY);
    return PvApp::label(p, parent, x += 70, y, 120, 30, v, QSS::LABEL_VAL);
}

class CardDevice : PvObject
{
public:
    static std::shared_ptr<CardDevice> create(PARAM* p, int parent, int x, int y)
    {
        return std::make_shared<CardDevice>(p, parent, x, y);
    }

    CardDevice(PARAM* p, int parent, int x, int y) : PvObject(p)
    {
        card_ = PvApp::label(p, parent, x, y, 400, 250, "", QSS::QSS_CARD_DEVICE);

        PvApp::label(p, card_, 10, 10, 60, 60, "", "border:none; background-color: rgb(39, 158, 145);");
        ui.name = PvApp::label(p, card_, 80, 10, 100, 20, "");
        ui.code = PvApp::label(p, card_, 80, 30, 100, 20, "");
        ui.type = PvApp::label(p, card_, 80, 50, 100, 20, "", QSS::label(14, "rgb(8, 161, 249)"));

        int x1 = 190;
        ui.online = PvApp::labelAlignCenter(p, card_, x1, 10, 70, 30, "在线", QSS::LABEL_VAL);
        ui.running = PvApp::labelAlignCenter(p, card_, x1 += 70, 10, 70, 30, "空闲", QSS::LABEL_VAL);
        ui.err = PvApp::labelAlignCenter(p, card_, x1 += 70, 10, 70, 30, "正常", QSS::LABEL_VAL);

        PvApp::labelAlignCenter(p, card_, x1 = 190, 40, 70, 30, "在线状态", QSS::LABEL_KEY);
        PvApp::labelAlignCenter(p, card_, x1 += 70, 40, 70, 30, "工作状态", QSS::LABEL_KEY);
        PvApp::labelAlignCenter(p, card_, x1 += 70, 40, 70, 30, "故障状态", QSS::LABEL_KEY);


        PvApp::label(p, card_, 10, 80, 80, 30, "运行分析：", QSS::LABEL_KEY);
        PvApp::button(p, card_, 80, 83, 60, 24, "查看");

        // 默认创建 10 个参数标签：
        int n = 10;
        vecParamLabel.resize(n);
        for (int i = 0; i<n; i++)
        {
            int row = i/2;
            int col = i%2;
            int h = 25;
            vecParamLabel[i].first = PvApp::label(p, card_, 10 + 200*col, 115 + h*row, 70, h, "参数"+std::to_string(i) + ":", QSS::LABEL_KEY);
            vecParamLabel[i].second = PvApp::label(p, card_, 10 + 200*col + 70, 115 + h*row, 120, h, "---", QSS::LABEL_VAL);
        }
    }

    void setCard(std::string type, std::string name, std::string code)
    {
        if (ui.code != PV_ID_NUL) { pvSetText(p, ui.code, code.c_str()); }
        if (ui.name != PV_ID_NUL) { pvSetText(p, ui.name, name.c_str()); }
        if (ui.type != PV_ID_NUL) { pvSetText(p, ui.type, type.c_str()); }
    }

    void setParamkeys(std::vector<std::string> vecKeys)
    {
        for (int i = 0; i<vecParamLabel.size(); i++)
        {
            auto& labelKey = vecParamLabel[i].first;
            auto& labelVal = vecParamLabel[i].second;
            if (i<vecKeys.size())
            {
                std::string& title = vecKeys[i] + "：";
                pvSetText(p, labelKey, title.c_str());
                pvSetText(p, labelVal, "---");
                pvShow(p, labelKey);
                pvShow(p, labelVal);
            }
            else
            {
                pvHide(p, labelKey);
                pvHide(p, labelVal);
            }
        }
    }

    void show(int visible)
    {
        visible ? pvShow(p, card_) : pvHide(p, card_);
    }

    struct {
        int code = PV_ID_NUL;
        int name = PV_ID_NUL;
        int type = PV_ID_NUL;
        int online = PV_ID_NUL;
        int running = PV_ID_NUL;
        int err = PV_ID_NUL;
    } ui;

    int card_;

    std::vector<std::pair<int, int>> vecParamLabel;
    std::map<std::string, int> mapParam_;
};

MaskPageRunning::MaskPageRunning(PARAM* p) : PvMask(p)
{
}

int MaskPageRunning::initUI(EPvCode pvcode)
{
    auto& appdata = Application::data();
    
    PvApp::label(p, 0, 10, 100, 1900, 850, "", "background-color: rgb(5, 47, 77); border-radius: 10px;");
    PvApp::label(p, 0, 10, 150, 220, 790, "", "background-color: rgb(8, 54, 91); border-radius: 10px;");
    int workspace = PvApp::label(p, 0, 240, 150, 1670, 790, "", "background-color: rgba(8, 54, 91, 0); border-radius: 10px;");

    std::vector<std::string> vecStationNames = appdata.getStationNames();
    PvApp::label(p, 0, 20, 110, 80, 30, "场站切换", "color:white; font: bold 16px;");
    ui.comboxStation = PvApp::combox(p, 0, 100, 110, 150, 30, vecStationNames);
    if (vecStationNames.size() > 0)
    {
        activeStation = appdata.getStationByName(vecStationNames[0]);
    }

    PvApp::label(p, 0, 320, 110, 80, 30, "运行模式", "color:white; font: bold 16px;");
    ui.comboxWorkMode = PvApp::combox(p, 0, 400, 110, 200, 30, appdata.getWorkModes(), activeStation->stationId - 1);

    PvApp::label(p, 0, 670, 110, 80, 30, "策略名称", "color:white; font: bold 16px;");
    PvApp::combox(p, 0, 750, 110, 200, 30, appdata.getPolicyNames());

    int x = 20, y = 160, w = 200, h = 180;
    // 储能设备
    {
        this->initModule(storage, "储能设备", x, y, w, h);
        storage.workspace = PvApp::widget(p, workspace, 0, 0, 1670, 790);
        pvHide(p, storage.workspace);

        // 创建信息卡片
        {
            vecCard_.resize(12);
            for (int i=0; i<vecCard_.size(); ++i)
            {
                vecCard_[i] = CardDevice::create(p, storage.workspace, (i%4)*410, (i/4)*260);
            }
        }
    }

    // 光伏设备
    {
        this->initModule(solar, "光伏设备", x, y += (h+10), w, h);
        solar.workspace = storage.workspace;
        pvHide(p, solar.workspace);
    }
    // 充电设备
    {
        this->initModule(charge, "充电设备", x, y += (h+10), w, h);
        charge.workspace = storage.workspace;
        pvHide(p, charge.workspace);
    }
    // 环境与安防设备
    {
        this->initModule(security, "环境与安防设备", x, y += (h+10), w, h);
        security.workspace = PvApp::widget(p, workspace, 0, 0, 1670, 790);
        pvHide(p, security.workspace);

        {
            std::string style = QSS::label(20, "white; padding: 0px 0px 0px 10px;", "rgb(8, 54, 91)", "none; border-radius: 5px;");
            for (int i = 0; i<12; ++i)
            {
                int w = 320, h = 240;
                int x = 0+(w+10)*(i%4), y = 0+(h+10)*(i/4);
                int cardId = PvApp::label(p, security.workspace, x, y, w, h, "监控点 " + std::to_string(i+1), style);
                pvSetAlignment(p, cardId, AlignLeft | AlignTop);

                PvApp::label(p, cardId, 10, 40, w-20, h-50, "", QSS::label(14, "", "", "8px solid black; border-radius: 0px;"));
                PvApp::image(p, cardId, (w-77)*0.5, 40+(h-40-77)*0.5, 77, 77, "play1.png");
            }
        }
        {

            int w = 320, h = 50;
            int pid = PvApp::label(p, security.workspace, 1320, 10, w, 200, "环境温度信息", QSS::label(20, "", "", "none;"));
            pvSetAlignment(p, pid, AlignLeft | AlignTop);
            PvApp::label(p, pid, 0, 30, w, 5, "", QSS::QSS_UNDERLINE);

            int x = 0, y = 50;
            PvApp::label(p, pid, x, y, w, h, "", QSS::label(14, "", "rgb(16, 105, 125)", "none; border-radius: 5px 5px 0px 0px;"));
            PvApp::label(p, pid, x, y, w, h*2, "", QSS::label(14, "", "", "1px solid rgb(12, 255, 251); border-radius: 5px;"));
            {
                w = w/3;
                PvApp::labelCenter(p, pid, x, y, w, h, "点位");
                PvApp::labelCenter(p, pid, x+w, y, w, h, "温度");
                PvApp::labelCenter(p, pid, x+w*2, y, w, h, "湿度");
                PvApp::labelCenter(p, pid, x, y += h, w, h, "#1");
                PvApp::labelCenter(p, pid, x+w, y, w, h, "20 ℃");
                PvApp::labelCenter(p, pid, x+w*2, y, w, h, "30 %");
            }
        }
        {
            int  w = 320, h = 50;
            int pid = PvApp::label(p, security.workspace, 1320, 200, w, 500, "消防信息", QSS::label(20, "", "", "none;"));
            pvSetAlignment(p, pid, AlignLeft | AlignTop);
            PvApp::label(p, pid, 0, 30, w, 5, "", QSS::QSS_UNDERLINE);

            int x = 0, y = 50;
            PvApp::label(p, pid, x, y, w, h, "", QSS::label(14, "", "rgb(16, 105, 125)", "none; border-radius: 5px 5px 0px 0px;"));
            PvApp::label(p, pid, x, y, w, h*9, "", QSS::label(14, "", "", "1px solid rgb(12, 255, 251); border-radius: 5px;"));
            {
                w = w/2;
                PvApp::labelCenter(p, pid, x, y, w, h, "点位");
                PvApp::labelCenter(p, pid, x+w, y, w, h, "烟感状态");
                PvApp::labelCenter(p, pid, x, y += h, w, h, "#1");
                PvApp::labelCenter(p, pid, x+w, y, w, h, "XXX");
                PvApp::labelCenter(p, pid, x, y += h, w, h, "#2");
                PvApp::labelCenter(p, pid, x+w, y, w, h, "XXX");
                PvApp::labelCenter(p, pid, x, y += h, w, h, "#3");
                PvApp::labelCenter(p, pid, x+w, y, w, h, "XXX");
                PvApp::labelCenter(p, pid, x, y += h, w, h, "#4");
                PvApp::labelCenter(p, pid, x+w, y, w, h, "XXX");
                PvApp::labelCenter(p, pid, x, y += h, w, h, "#5");
                PvApp::labelCenter(p, pid, x+w, y, w, h, "XXX");
                PvApp::labelCenter(p, pid, x, y += h, w, h, "#6");
                PvApp::labelCenter(p, pid, x+w, y, w, h, "XXX");
                PvApp::labelCenter(p, pid, x, y += h, w, h, "#7");
                PvApp::labelCenter(p, pid, x+w, y, w, h, "XXX");
                PvApp::labelCenter(p, pid, x, y += h, w, h, "#8");
                PvApp::labelCenter(p, pid, x+w, y, w, h, "XXX");
            }
        }
    }

    activeBoxPanel(&storage);

    {
        PvApp::bind(p, PvEvent::TEXT_EVENT, ui.comboxStation, [=](std::string s) { this->onComboxStation(s); });
        PvApp::bind(p, PvEvent::TEXT_EVENT, ui.comboxWorkMode, [=](std::string s) { this->onComboxWorkMode(s); });
    }

    return 0;
}

void MaskPageRunning::initModule(Module& module, std::string name, int x, int y, int w, int h)
{
    module.name = name;
    
    int deviceNum = activeStation->getDeviceNumByGroup(1);
    int pid = module.widget = PvApp::label(p, 0, x, y, w, h, "", QSS::LABEL_BOX);
    PvApp::label(p, module.widget, 10, 20, w, 30, module.name, QSS::LABEL_TITLE);
    pvSetAlignment(p, module.widget, AlignTop | AlignLeft);
    module.labelPower = PvApp::lineLabel(p, pid, PvRect(10, 80, 180, 30), 70, "总功率：", "60 W");
    module.labelNum = PvApp::lineLabel(p, pid, PvRect(10, 110, 180, 30), 70, "设备数量：", std::to_string(deviceNum).c_str());
    module.btn = PvApp::button(p, pid, 0, 0, w, h, "", "background-color: transparent;");
}


EPvCode MaskPageRunning::onEventButton(int pvid)
{
    if (pvid == storage.btn) { activeBoxPanel(&storage); }
    else if (pvid == solar.btn) { activeBoxPanel(&solar); }
    else if (pvid == charge.btn) { activeBoxPanel(&charge); }
    else if (pvid == security.btn) { activeBoxPanel(&security); }
    return EPvCode::NUL;
}

void MaskPageRunning::activeBoxPanel(Module* module)
{
    if (activeBox) 
    { 
        pvSetStyleSheet(p, activeBox->widget, QSS::LABEL_BOX.c_str()); 
        pvHide(p, activeBox->workspace);
    }
    activeBox = module;
    if (activeBox) 
    { 
        pvSetStyleSheet(p, activeBox->widget, QSS::QSS_BOX_ACTIVE.c_str());
        pvShow(p, activeBox->workspace);
    }

    auto& appdata = Application::data();
    if (activeBox->workspace != security.workspace)
    {
        // 更新卡片：
        std::vector<std::shared_ptr<Device>> vecDevice;
        activeStation->getDeviceByGroup(1, vecDevice);

        pvSetText(p, module->labelNum, std::to_string(vecDevice.size()).c_str());

        // 读取储能设备信息
        for (int i = 0; i<vecCard_.size(); ++i)
        {
            auto& card = vecCard_[i];
            if (i < vecDevice.size())
            {
                auto device = vecDevice[i];
                auto typeDef = appdata.getDeviceTypeDef(device->type);
                if (typeDef)
                {
                    std::vector<std::string> vecKeys;
                    JSON::parse(typeDef->fieldsAttr.value("key"), vecKeys);
                    card->setCard(typeDef->name, device->name, device->code);
                    card->setParamkeys(vecKeys);
                }
                card->show(1);
            }
            else
            {
                card->show(0);
            }
        }
    }
}

void MaskPageRunning::updateWorkspace()
{

}

void MaskPageRunning::onComboxStation(std::string stationName)
{
    if (!activeStation) return;

    auto& appdata = Application::data();
    activeStation = appdata.getStationByName(stationName);

    // 更新运行模式和策略
    {
        int index = activeStation->workModeId - 1;
        if (index < 0) { index = 0; }
        pvSetCurrentItem(p, ui.comboxWorkMode, index);
    }

    this->activeBoxPanel(activeBox);
}

void MaskPageRunning::onComboxWorkMode(std::string modeName)
{
    if (!activeStation) return;

    auto& appdata = Application::data();

    int workModeId = appdata.getWorkModeIdByName(modeName);
    activeStation->setWorkMode(workModeId);


}