#include "FormStandby.h"
#include "ui_FormStandby.h"

#include <QMouseEvent>
#include <QDebug>
#include <QtAlgorithms>

#include "Globals.h"
#include "GeneralInterface.h"
#include "LoggerHelper.h"
#include "ConfigManager.h"

#include "FormAuthentication.h"
#include "FormChargePrepare.h"
#include "FormCharging.h"
#include "FormPlugIn.h"
#include "FormPrice.h"
#include "FormFinished.h"

FormStandby::FormStandby(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::FormStandby)
    , m_gun_error_1(false)
    , m_gun_error_2(false)
{
    ui->setupUi(this);

    m_gun_num = ConfigManager::instance()->ccu_cfg().GUN_numb;

    initWidget();
    initConnect();
}

FormStandby::~FormStandby()
{
    delete ui;
}

void FormStandby::setBackground(QLabel *label, const QString &imageUrl)
{
    label->setPixmap(QPixmap(imageUrl));
}

void FormStandby::setTips(const QString &tips, int gun_index)
{
    if(gun_index == 1) {
        ui->charge_gun_tips_1->setText(tips);
    } else if (gun_index == 2) {
        ui->charge_gun_tips_2->setText(tips);
    }
}

void FormStandby::initWidget()
{
    this->setAttribute(Qt::WA_TranslucentBackground);

    initBackground();

    setRestartVisible(false, CHARGE_GUN_DEFAULT_1);
    setRestartVisible(false, CHARGE_GUN_DEFAULT_2);

    initForms();

    m_price = new FormPrice();
    // 设置父窗口
    m_price->setParent(this);
    // 设置为独立窗口
    m_price->setWindowFlags(Qt::Window | Qt::FramelessWindowHint);
    // 设置为应用程序的模态窗口，阻止本应用所有窗口的输入
    m_price->setWindowModality(Qt::WindowModal);
}

void FormStandby::initConnect()
{
    connect(GLOBALS, &Globals::valueChanged, this, &FormStandby::globalsValueChanged);

    // 充电枪类型信息数据改变信号处理
    connect(GLOBALS, &Globals::gunTypeValueChanged_1, this, [this](const QMap<uint8_t, QString>& value) {
        refreshGunType(value, CHARGE_GUN_DEFAULT_1);
    });
    connect(GLOBALS, &Globals::gunTypeValueChanged_2, this, [this](const QMap<uint8_t, QString>& value) {
        refreshGunType(value, CHARGE_GUN_DEFAULT_2);
    });

    // 充电付费信息按钮点击信号处理
    connect(ui->charge_gun_price_1, &QPushButton::clicked, this, [this]() {
        m_price->show();
    });
    connect(ui->charge_gun_price_2, &QPushButton::clicked, this, [this]() {
        m_price->show();
    });
}

void FormStandby::initBackground()
{
    // 设置充电枪背景图片
    setChargeGunBackground();

    // 设置充电进度条背景图片
    setChargeProgressBackground();
}

void FormStandby::initForms()
{
    // 初始化充电枪页面列表--充电枪1组
    initForms_1();

    // 初始化充电枪页面列表--充电枪2组
    initForms_2();

    refreshChargeGunInfo();
}

void FormStandby::initForms_1()
{
    // 列表中添加各个页面
    m_formMap_1[PLUG_IN]        = new FormPlugIn();
    m_formMap_1[CHARGING_FORM]  = new FormCharging();
    m_formMap_1[AUTHENTICATION] = new FormAuthentication();
    m_formMap_1[PRICE_FORM]     = new FormPrice();
    m_formMap_1[CHARGE_PREPARE] = new FormChargePrepare();
    m_formMap_1[FINISH_FORM]    = new FormFinished();

    // 添加页面到堆叠窗口并隐藏
    foreach (const auto& widget, m_formMap_1.values()) {
        ui->charge_gun_widget_1->addWidget(widget);

        // 强制布局系统更新
        ui->charge_gun_widget_1->updateGeometry();
    }
    showForm_1(PLUG_IN);
}

void FormStandby::initForms_2()
{
    // 列表中添加各个页面
    m_formMap_2[PLUG_IN]        = new FormPlugIn();
    m_formMap_2[CHARGING_FORM]  = new FormCharging();
    m_formMap_2[AUTHENTICATION] = new FormAuthentication();
    m_formMap_2[PRICE_FORM]     = new FormPrice();
    m_formMap_2[CHARGE_PREPARE] = new FormChargePrepare();
    m_formMap_2[FINISH_FORM]    = new FormFinished();

    // 添加页面到堆叠窗口并隐藏
    foreach (const auto& widget, m_formMap_2.values()) {
        ui->charge_gun_widget_2->addWidget(widget);

        // 强制布局系统更新
        ui->charge_gun_widget_2->updateGeometry();
    }
    showForm_2(PLUG_IN);
}

void FormStandby::setChargeGunBackground()
{
    backgroundImage_1 = new QLabel();
    backgroundImage_2 = new QLabel();

    // 将背景 Label 添加到布局，并占据全部单元格
    ui->gun_layout_1->addWidget(backgroundImage_1, 0, 0, ui->gun_layout_1->rowCount()-1, ui->gun_layout_1->columnCount());
    ui->gun_layout_2->addWidget(backgroundImage_2, 0, 0, ui->gun_layout_2->rowCount()-1, ui->gun_layout_2->columnCount());

    // 叠加显示背景图，将背景图显示在底层
    setBackground(backgroundImage_1, ":/images/starting/background.png");
    setBackground(backgroundImage_2, ":/images/starting/background.png");
    backgroundImage_1->lower();
    backgroundImage_2->lower();
    backgroundImage_1->setScaledContents(true);
    backgroundImage_2->setScaledContents(true);
}

void FormStandby::setChargeProgressBackground()
{
    charge_progress_bg_image_1 = new QLabel();
    charge_progress_bg_image_2 = new QLabel();

    ui->charge_schedule_layout_1->addWidget(charge_progress_bg_image_1,
                                            0,
                                            0,
                                            ui->charge_schedule_layout_1->rowCount(),
                                            ui->charge_schedule_layout_1->columnCount());
    ui->charge_schedule_layout_2->addWidget(charge_progress_bg_image_2,
                                            0,
                                            0,
                                            ui->charge_schedule_layout_2->rowCount(),
                                            ui->charge_schedule_layout_2->columnCount());

    // 叠加显示背景图，将背景图显示在底层
    setBackground(charge_progress_bg_image_1, ":/images/menu/plug_in_progress.png");
    setBackground(charge_progress_bg_image_2, ":/images/menu/plug_in_progress.png");

    charge_progress_bg_image_1->lower();
    charge_progress_bg_image_2->lower();
    charge_progress_bg_image_1->setScaledContents(true);
    charge_progress_bg_image_2->setScaledContents(true);

}

QStringList FormStandby::getGunErrorStringList(const QMap<uint8_t, QString> &error)
{
    QStringList result;
    auto keys = error.keys();
    for(auto &key : keys) {
        result.append(error.value(key));
    }

    return result;
}

void FormStandby::refreshGunType(const QMap<uint8_t, QString> &type, int gun_id)
{
    if (type.count() != 1) {
        QString msg = "Error: To get the specific category of charge gun!";
        LoggerHelper::intance()->info(msg);
        return;
    }

    auto keys = type.keys();
    auto gun_type = keys[0];
    auto gun_type_description = type.value(gun_type);

    switch (gun_id) {
    case CHARGE_GUN_DEFAULT_1:
        refreshGunType_1(gun_type, gun_type_description);
        break;
    case CHARGE_GUN_DEFAULT_2:
        refreshGunType_2(gun_type, gun_type_description);
        break;
    default:
        break;
    }
}

void FormStandby::refreshGunType_1(const uint8_t &type, const QString &description)
{
    auto icon_url = GeneralInterface::getGunIconUrl(type);

    ui->charge_gun_icon_1->setIcon(QIcon(icon_url));
    ui->charge_gun_type_1->setText(description);
}

void FormStandby::refreshGunType_2(const uint8_t &type, const QString &description)
{
    auto icon_url = GeneralInterface::getGunIconUrl(type);

    ui->charge_gun_icon_2->setIcon(QIcon(icon_url));
    ui->charge_gun_type_2->setText(description);
}

void FormStandby::refreshGunState(const QMap<uint8_t, QString> &state, int gun_id)
{
    auto states = state.keys();
    if (states.isEmpty()) return;

    switch (gun_id) {
    case CHARGE_GUN_DEFAULT_1:
        refreshGunState_1(GeneralInterface::getMaxElement(states));
        break;
    case CHARGE_GUN_DEFAULT_2:
        refreshGunState_2(GeneralInterface::getMaxElement(states));
        break;
    default:
        break;
    }
}

void FormStandby::refreshGunState_1(const uint8_t &state)
{
    switch (state) {
    case GUNSTATE_IDLE: // 空闲阶段，已插入充电桩的抢座中
        showForm_1(PLUG_IN);
        break;
    case GUNSTATE_PLUGIN: // 插枪等待阶段，已插入汽车充电仓
        showForm_1(AUTHENTICATION);
        break;
    case GUNSTATE_AUTHORIZATION: // 鉴权阶段，或者直接发送命令充电
        break;
    case GUNSTATE_PARAMETER: // 参数配置阶段
        showForm_1(CHARGE_PREPARE);
        break;
    case GUNSTATE_INSULATION: // 绝缘检测阶段
        break;
    case GUNSTATE_PRECHARGE: // 预充阶段
        break;
    case GUNSTATE_CHARGING: // 充电阶段
        showForm_1(CHARGING_FORM);
        break;
    case GUNSTATE_FINISHING: // 充电结束阶段
        break;
    default:
        break;
    }
}

void FormStandby::refreshGunState_2(const uint8_t &state)
{
    switch (state) {
    case GUNSTATE_IDLE: // 空闲阶段，已插入充电桩的抢座中
        showForm_2(PLUG_IN);
        break;
    case GUNSTATE_PLUGIN: // 插枪等待阶段，已插入汽车充电仓
        showForm_2(AUTHENTICATION);
        break;
    case GUNSTATE_AUTHORIZATION: // 鉴权阶段，或者直接发送命令充电
        break;
    case GUNSTATE_PARAMETER: // 参数配置阶段
        showForm_2(CHARGE_PREPARE);
        break;
    case GUNSTATE_INSULATION: // 绝缘检测阶段
        break;
    case GUNSTATE_PRECHARGE: // 预充阶段
        break;
    case GUNSTATE_CHARGING: // 充电阶段
        showForm_2(CHARGING_FORM);
        break;
    case GUNSTATE_FINISHING: // 充电结束阶段
        break;
    default:
        break;
    }
}

void FormStandby::showForm_1(workspace_form_enum form)
{
    if (!m_formMap_1.contains(form)) {
        return;
    }

    if (form != PLUG_IN) setPriceVisible(false, CHARGE_GUN_DEFAULT_1);
    else setPriceVisible(true, CHARGE_GUN_DEFAULT_1);

    m_currentForm = form;
    setCurrentChargeProgress(getChargeProgress(form), CHARGE_GUN_DEFAULT_1);
    ui->charge_gun_widget_1->setCurrentWidget(m_formMap_1[form]);
}

void FormStandby::showForm_2(workspace_form_enum form)
{
    if (!m_formMap_2.contains(form)) {
        return;
    }

    if (form != PLUG_IN) setPriceVisible(false, CHARGE_GUN_DEFAULT_2);
    else setPriceVisible(true, CHARGE_GUN_DEFAULT_2);

    m_currentForm = form;
    setCurrentChargeProgress(getChargeProgress(form), CHARGE_GUN_DEFAULT_2);
    ui->charge_gun_widget_2->setCurrentWidget(m_formMap_2[form]);
}

void FormStandby::setCurrentChargeProgress(const charge_progress_enum &progress, const int &gun_id)
{
    QString imageUrl = "";
    switch (progress) {
    case PLUG_IN_PROGRESS:
        if (m_gun_num == 1) imageUrl = ":/images/menu/plug_in_progress_once.png";
        else  imageUrl = ":/images/menu/plug_in_progress.png";
        break;
    case AUTHORIZATION_PROGRESS:
        if (m_gun_num == 1) imageUrl = ":/images/menu/authorization_progress_once.png";
        else imageUrl = ":/images/menu/authorization_progress.png";
        break;
    case CHARGING_PROGRESS:
        if (m_gun_num == 1) imageUrl = ":/images/menu/charging_progress_once.png";
        else imageUrl = ":/images/menu/charging_progress.png";
        break;
    case FINISHED_PROGRESS:
        if (m_gun_num == 1) imageUrl = ":/images/menu/finished_progress_once.png";
        else imageUrl = ":/images/menu/finished_progress.png";
        break;
    default: break;
    }

    if (imageUrl.isEmpty()) return;

    if (gun_id == CHARGE_GUN_DEFAULT_1) {
        setBackground(charge_progress_bg_image_1, imageUrl);
    } else if (gun_id == CHARGE_GUN_DEFAULT_2) {
        setBackground(charge_progress_bg_image_2, imageUrl);
    }

    setCurrentChargeProgressText(progress, gun_id);
}

void FormStandby::setCurrentChargeProgressText(const charge_progress_enum &progress, const int &gun_id)
{
    switch (progress) {
    case PLUG_IN_PROGRESS:
        setPlugInTextColor(gun_id, "color : #00C1C3");
        setAuthorizationTextColor(gun_id, "color : white");
        setChargingTextColor(gun_id, "color : white");
        setFinishedTextColor(gun_id, "color : white");
        break;
    case AUTHORIZATION_PROGRESS:
        setPlugInTextColor(gun_id, "color : #00C1C3");
        setAuthorizationTextColor(gun_id, "color : #00C1C3");
        setChargingTextColor(gun_id, "color : white");
        setFinishedTextColor(gun_id, "color : white");
        break;
    case CHARGING_PROGRESS:
        setPlugInTextColor(gun_id, "color : #00C1C3");
        setAuthorizationTextColor(gun_id, "color : #00C1C3");
        setChargingTextColor(gun_id, "color : #00C1C3");
        setFinishedTextColor(gun_id, "color : white");
        break;
    case FINISHED_PROGRESS:
        setPlugInTextColor(gun_id, "color : #00C1C3");
        setAuthorizationTextColor(gun_id, "color : #00C1C3");
        setChargingTextColor(gun_id, "color : #00C1C3");
        setFinishedTextColor(gun_id, "color : #00C1C3");
        break;
    default: break;
    }
}

charge_progress_enum FormStandby::getChargeProgress(const workspace_form_enum &form)
{
    switch (form) {
    case PLUG_IN: return PLUG_IN_PROGRESS;
    case CHARGING_FORM: return CHARGING_PROGRESS;
    case CHARGE_PREPARE: return AUTHORIZATION_PROGRESS;
    case AUTHENTICATION: return AUTHORIZATION_PROGRESS;
    case FINISH_FORM: return FINISHED_PROGRESS;
    default: break;
    }

    return UNKNOWN_PROGRESS;
}

void FormStandby::setPlugInTextColor(const int &gun_id, const QString &color)
{
    switch (gun_id) {
    case CHARGE_GUN_DEFAULT_1: ui->plug_in_1->setStyleSheet(color); break;
    case CHARGE_GUN_DEFAULT_2: ui->plug_in_2->setStyleSheet(color); break;
    default: break;
    }
}

void FormStandby::setAuthorizationTextColor(const int &gun_id, const QString &color)
{
    switch (gun_id) {
    case CHARGE_GUN_DEFAULT_1: ui->authorization_1->setStyleSheet(color); break;
    case CHARGE_GUN_DEFAULT_2: ui->authorization_2->setStyleSheet(color); break;
    default: break;
    }
}

void FormStandby::setChargingTextColor(const int &gun_id, const QString &color)
{
    switch (gun_id) {
    case CHARGE_GUN_DEFAULT_1: ui->charging_1->setStyleSheet(color); break;
    case CHARGE_GUN_DEFAULT_2: ui->charging_2->setStyleSheet(color); break;
    default: break;
    }
}

void FormStandby::setFinishedTextColor(const int &gun_id, const QString &color)
{
    switch (gun_id) {
    case CHARGE_GUN_DEFAULT_1: ui->finished_1->setStyleSheet(color); break;
    case CHARGE_GUN_DEFAULT_2: ui->finished_2->setStyleSheet(color); break;
    default: break;
    }
}

void FormStandby::refreshChargeGunInfo()
{
    auto plug_in_form = qobject_cast<FormPlugIn*>(m_formMap_1[PLUG_IN]);
    auto charging_form = qobject_cast<FormCharging*>(m_formMap_1[CHARGING_FORM]);
    auto finish_form = qobject_cast<FormFinished*>(m_formMap_1[FINISH_FORM]);
    auto plug_in_form_2 = qobject_cast<FormPlugIn*>(m_formMap_2[PLUG_IN]);
    auto charging_form_2 = qobject_cast<FormCharging*>(m_formMap_2[CHARGING_FORM]);
    auto finish_form_2 = qobject_cast<FormFinished*>(m_formMap_2[FINISH_FORM]);

    if (m_gun_num == 1) {
        ui->gun_widget_2->hide();
    } else if (m_gun_num == 2) {
        ui->gun_widget_2->show();
    }

    plug_in_form->refreshChargingBackground();
    plug_in_form_2->refreshChargingBackground();
    charging_form->refreshChargingBackground();
    charging_form_2->refreshChargingBackground();
    finish_form->refreshChargingBackground();
    finish_form_2->refreshChargingBackground();
}

void FormStandby::setRestartVisible(bool visible, const int &gun_id)
{
    if (gun_id == CHARGE_GUN_DEFAULT_1) {
        ui->charge_gun_restart_1->setVisible(visible);
    } else if (gun_id == CHARGE_GUN_DEFAULT_2) {
        ui->charge_gun_restart_2->setVisible(visible);
    }
}

void FormStandby::setPriceVisible(bool visible, const int &gun_id)
{
    if (gun_id == CHARGE_GUN_DEFAULT_1) {
        ui->charge_gun_price_1->setVisible(visible);
    } else if (gun_id == CHARGE_GUN_DEFAULT_2) {
        ui->charge_gun_price_2->setVisible(visible);
    }
}

void FormStandby::globalsValueChanged(const QString &key, const QVariant &value)
{
    switch (GLOBALS->getKeyIndex(key)) {
    case GLOBALS_GUN_BASIC_INFO_KEY_1:
    case GLOBALS_GUN_BASIC_INFO_KEY_2:
        // displayGunBasicInfo(value.value<BASIC_INFO>());
        break;
    case GLOBALS_CHARGING_INFO_KEY_1:
        // refreshChargeInfo_1(value.value<CHARGING_INFO>());
        break;
    case GLOBALS_CHARGING_INFO_KEY_2:
        // refreshChargeInfo_2(value.value<CHARGING_INFO>());
        break;
    case GLOBALS_GUN_ERROR_KEY_1:
        // refreshGunError_1(value.value<QMap<uint8_t, QString>>());
        break;
    case GLOBALS_GUN_ERROR_KEY_2:
        // refreshGunError_2(value.value<QMap<uint8_t, QString>>());
        break;
    case GLOBALS_GUN_STATE_KEY_1:
        // refreshGunState_1(value.value<QMap<uint8_t, QString>>());
        break;
    case GLOBALS_GUN_STATE_KEY_2:
        // refreshGunState_2(value.value<QMap<uint8_t, QString>>());
        break;
    case GLOBALS_GUN_TYPE_KEY_1:
        refreshGunType(value.value<QMap<uint8_t, QString>>(), CHARGE_GUN_DEFAULT_1);
        break;
    case GLOBALS_GUN_TYPE_KEY_2:
        refreshGunType(value.value<QMap<uint8_t, QString>>(), CHARGE_GUN_DEFAULT_2);
        break;
    default:
        break;
    }
}
