#include "FormPayment.h"
#include "ui_FormPayment.h"

#include <QMessageBox>

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

FormPayment::FormPayment(BaseWidget *parent)
    : BaseWidget(parent)
    , ui(new Ui::FormPayment)
{
    ui->setupUi(this);

    m_tcu_cfg = ConfigManager::instance()->tcu_cfg();

    initWidget();
}

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

bool FormPayment::returnParent()
{
    if (isModify()) {
        auto ret = QMessageBox::question(this, tr("Save"),
                                         tr("The content has been modified. Do you want to save the changes?"),
                                         QMessageBox::Cancel | QMessageBox::No | QMessageBox::Yes);
        if (ret == QMessageBox::Yes) {      // save
            m_tcu_cfg.payment_config = getNewConfig();
            return ConfigManager::instance()->saveConfig(TCU_CONFIG, QVariant::fromValue<TCU_CFG>(m_tcu_cfg));
        } else if (ret == QMessageBox::No){ // no save
            return true;
        } else {                            // cancel
            return false;
        }
    }

    return true;
}

void FormPayment::initWidget()
{
    GeneralInterface::setTouchScroller(ui->scrollArea);
    initCurrencyCode();
    initCurrencySymbol();
    initComboBox();
    initCommandButton();

    refreshConfig(m_tcu_cfg.payment_config);
}

void FormPayment::initComboBox()
{
    ui->offline_price_type->addItem("Energy");

    ui->offline_price_timezone->addItem("Local");

    ui->currency_code->addItems(m_currency_code);
    ui->currency_symbol->addItems(m_currency_symbol);
    ui->decimal_place_currency->setValue(2);

    ui->pos_idtoken_prefix->setText("None");

    ui->pax_idtoken_type->addItem("Account");

    ui->wizar_idtoken_type->addItem("CardNum");
}

void FormPayment::initCommandButton()
{
    ui->pax_command_record->setMainText("Pax Command Record");
    ui->pax_command_record->setDescriptionText("");

    ui->pax_payment_record->setMainText("Pax Payment Record");
    ui->pax_payment_record->setDescriptionText("");

    ui->wizar_payment_record->setMainText("Wizar Payment Record");
    ui->wizar_payment_record->setDescriptionText("");
}

void FormPayment::initConnect()
{
    connectAllValueChanged(this);

    connect(LanguageManager::instance(), &LanguageManager::languageChanged, this, [this]() { ui->retranslateUi(this); });
    connect(GLOBALS, &Globals::tcuConfigValueChanged, this, [this](const TCU_CFG& tcu_cfg) {
        if (!this->isVisible()) return;
        if (isModify()) {
            auto ret = QMessageBox::information(this,
                                                tr("tips"),
                                                tr("Do you want to load the updated configuration file content?"),
                                                QMessageBox::No | QMessageBox::Yes);
            if (ret == QMessageBox::Yes) {
                m_tcu_cfg = tcu_cfg;
                refreshConfig(tcu_cfg.payment_config);
            } else if (ret == QMessageBox::No){
                return;
            }
        } else {
            m_tcu_cfg = tcu_cfg;
            refreshConfig(tcu_cfg.payment_config);
        }
    });
}

void FormPayment::initCurrencyCode()
{
    m_currency_code.clear();
    m_currency_code << "USD"
                    << "EUR"
                    << "CNY"
                    << "JPY"
                    << "GBP"
                    << "CHF"
                    << "AUD"
                    << "CAD"
                    << "HKD";
}

void FormPayment::initCurrencySymbol()
{
    m_currency_symbol.clear();
    m_currency_symbol   << "$"
                        << "€"
                        << "¥"
                        << "¥"
                        << "£"
                        << "CHF"
                        << "A$"
                        << "C$"
                        << "HK$";
}

void FormPayment::connectAllValueChanged(QWidget *widget)
{
    // QLineEdit
    if (auto edit = qobject_cast<QLineEdit*>(widget)) {
        connect(edit,   &QLineEdit::textChanged,                                    this, &FormPayment::onValueChanged);
    }
    // QSpinBox
    else if (auto spin = qobject_cast<QSpinBox*>(widget)) {
        connect(spin,   QOverload<int>::of(&QSpinBox::valueChanged),                this, &FormPayment::onValueChanged);
    }
    // CustomLineEdit
    else if (auto edit = qobject_cast<CustomLineEdit*>(widget)) {
        connect(edit,   &CustomLineEdit::textChanged,                               this, &FormPayment::onValueChanged);
    }
    // CustomSpinBox
    else if (auto spin = qobject_cast<CustomSpinBox*>(widget)) {
        connect(spin,   QOverload<int>::of(&CustomSpinBox::valueChanged),           this, &FormPayment::onValueChanged);
    }
    // QDoubleSpinBox
    else if (auto dspin = qobject_cast<QDoubleSpinBox*>(widget)) {
        connect(dspin,  QOverload<double>::of(&QDoubleSpinBox::valueChanged),       this, &FormPayment::onValueChanged);
    }
    // QCheckBox
    else if (auto check = qobject_cast<QCheckBox*>(widget)) {
        connect(check,  &QCheckBox::stateChanged,                                   this, &FormPayment::onValueChanged);
    }
    // QComboBox
    else if (auto combo = qobject_cast<CustomComboBox*>(widget)) {
        connect(combo,  QOverload<int>::of(&CustomComboBox::currentIndexChanged),   this, &FormPayment::onValueChanged);
    }
    // 递归遍历所有子控件
    for (auto child : widget->findChildren<QWidget*>()) {
        connectAllValueChanged(child);
    }
}

void FormPayment::refreshConfig(const PAYMENT_INFO &info)
{
    // price config
    ui->enable_offline_pricing->setChecked(info.price_setting.offline_pricing);
    ui->offline_price_type->setCurrentIndex(info.price_setting.offline_price_type);
    ui->offline_price_timezone->setCurrentIndex(info.price_setting.offline_price_timezone);
    ui->mini_amount->setValue(info.price_setting.mini_amount_charging_permission);
    ui->currency_symbol->setCurrentIndex(info.price_setting.currency_symbol);
    ui->currency_code->setCurrentIndex(info.price_setting.currency_code);
    ui->decimal_place_currency->setValue(info.price_setting.decimal_places_currency);

    ui->total_elec_energy_loss_ratio->setValue(info.total_elec_energy_loss_ratio);

    // pos config
    ui->pos_machine_manufacturer->setText(info.pos_machine.pos_machine_manufacturer);
    ui->backout_pos_payment->setChecked(info.pos_machine.backout_pos_payment);
    ui->ocpp_online_pos_payment->setCheckable(info.pos_machine.ocpp_online_pos_payment);
    ui->pos_idtoken_prefix->setText(info.pos_machine.id_token_prefix);
    ui->max_payment_record_num->setValue(info.pos_machine.max_payment_record_num);
    ui->pos_max_wait_duration->setValue(info.pos_machine.pos_max_wait_duration);

    // pax config
    ui->pax_idtoken_type->setCurrentIndex(info.pax_config.id_token_type);

    // wizar config
    ui->wizar_idtoken_type->setCurrentIndex(info.wizar_config.id_token_type);
}

PAYMENT_INFO FormPayment::getNewConfig()
{
    PAYMENT_INFO config;
    // price config
    config.price_setting.offline_pricing = ui->enable_offline_pricing->isChecked();
    config.price_setting.offline_price_type = ui->offline_price_type->currentIndex();
    config.price_setting.offline_price_timezone = ui->offline_price_timezone->currentIndex();
    config.price_setting.mini_amount_charging_permission = ui->mini_amount->value();
    config.price_setting.currency_symbol = ui->currency_symbol->currentIndex();
    config.price_setting.currency_code = ui->currency_code->currentIndex();
    config.price_setting.decimal_places_currency = ui->decimal_place_currency->value();

    config.total_elec_energy_loss_ratio = ui->total_elec_energy_loss_ratio->text().toInt();
    
    // pos config
    config.pos_machine.pos_machine_manufacturer = ui->pos_machine_manufacturer->text();
    config.pos_machine.backout_pos_payment = ui->backout_pos_payment->isChecked();
    config.pos_machine.ocpp_online_pos_payment = ui->ocpp_online_pos_payment->isChecked();
    config.pos_machine.id_token_prefix = ui->pos_idtoken_prefix->text();
    config.pos_machine.max_payment_record_num = ui->max_payment_record_num->value();
    config.pos_machine.pos_max_wait_duration = ui->pos_max_wait_duration->value();

    // pax config
    config.pax_config.id_token_type = ui->pax_idtoken_type->currentIndex();

    // wizar config
    config.wizar_config.id_token_type = ui->wizar_idtoken_type->currentIndex();

    return config;
}

void FormPayment::onValueChanged()
{
    setIsModify(true);
}

void FormPayment::showEvent(QShowEvent *event)
{
    setIsModify(false);
    BaseWidget::showEvent(event);
}

void FormPayment::hideEvent(QHideEvent *event)
{
    setIsModify(false);
    BaseWidget::hideEvent(event);
}
