#include "FormConfigurationKey.h"
#include "ui_FormConfigurationKey.h"

#include <QScroller>
#include <QMessageBox>
#include <QComboBox>
#include <QDateTimeEdit>

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

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

    GeneralInterface::setTouchScroller(ui->scrollArea);

    m_cfg_key = ConfigManager::instance()->cfg_key();
    refreshConfig(m_cfg_key);
    initConnect();
}

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

bool FormConfigurationKey::returnParent()
{
    CONFIG_KEY_INFO info = getConfigKey();
    return ConfigManager::instance()->saveConfig(CONFIG_KEY, QVariant::fromValue<CONFIG_KEY_INFO>(info));
}

void FormConfigurationKey::initConnect()
{
    connect(ui->core_profile_state,                     &QToolButton::clicked, this, [this]() {
        ui->coreProfile_widget->setVisible(!ui->coreProfile_widget->isVisible());
        if (ui->coreProfile_widget->isVisible()) { // spread
            ui->core_profile_state->setIcon(QIcon(":/icons/packup.png"));
        } else { // pack up
            ui->core_profile_state->setIcon(QIcon(":/icons/spread.png"));
        }
    });

    connect(ui->localAuthListManagementProfile_state,  &QToolButton::clicked, this, [this]() {
        ui->localAuthListManagementProfile_widget->setVisible(!ui->localAuthListManagementProfile_widget->isVisible());
        if (ui->localAuthListManagementProfile_widget->isVisible()) { // spread
            ui->localAuthListManagementProfile_state->setIcon(QIcon(":/icons/packup.png"));
        } else { // pack up
            ui->localAuthListManagementProfile_state->setIcon(QIcon(":/icons/spread.png"));
        }
    });

    connect(ui->reservation_profile_state,              &QToolButton::clicked, this, [this]() {
        ui->reservation_profile_widget->setVisible(!ui->reservation_profile_widget->isVisible());
        if (ui->reservation_profile_widget->isVisible()) { // spread
            ui->reservation_profile_state->setIcon(QIcon(":/icons/packup.png"));
        } else { // pack up
            ui->reservation_profile_state->setIcon(QIcon(":/icons/spread.png"));
        }
    });

    connect(ui->smart_charging_profile_state,           &QToolButton::clicked, this, [this]() {
        ui->smart_charging_profile_widget->setVisible(!ui->smart_charging_profile_widget->isVisible());
        if (ui->smart_charging_profile_widget->isVisible()) { // spread
            ui->smart_charging_profile_state->setIcon(QIcon(":/icons/packup.png"));
        } else { // pack up
            ui->smart_charging_profile_state->setIcon(QIcon(":/icons/spread.png"));
        }
    });

    connect(GLOBALS, &Globals::ocppConfigKeyValueChanged, this, [this](const CONFIG_KEY_INFO& info){
        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_cfg_key = info;
                refreshConfig(info);
            } else if (ret == QMessageBox::No){
                return;
            }
        } else {
            m_cfg_key = info;
            refreshConfig(info);
        }
    });

    connect(ui->save, &QPushButton::clicked, this, [this]() {
        CONFIG_KEY_INFO info = getConfigKey();
        ConfigManager::instance()->saveConfig(CONFIG_KEY, QVariant::fromValue<CONFIG_KEY_INFO>(info));
    });

    connectAllValueChanged(this);

    connect(LanguageManager::instance(), &LanguageManager::languageChanged, this, [this]() { ui->retranslateUi(this); });
}

void FormConfigurationKey::connectAllValueChanged(QWidget* widget)
{
    // QLineEdit
    if (auto edit = qobject_cast<QLineEdit*>(widget)) {
        connect(edit,       &QLineEdit::textChanged,                                this, &FormConfigurationKey::valueChanged);
    }
    // QTextEdit
    else if (auto textEdit = qobject_cast<QTextEdit*>(widget)) {
        connect(textEdit,   &QTextEdit::textChanged,                                this, &FormConfigurationKey::valueChanged);
    }
    // QSpinBox
    else if (auto spin = qobject_cast<QSpinBox*>(widget)) {
        connect(spin,       QOverload<int>::of(&QSpinBox::valueChanged),            this, &FormConfigurationKey::valueChanged);
    }
    // QDoubleSpinBox
    else if (auto dspin = qobject_cast<QDoubleSpinBox*>(widget)) {
        connect(dspin,      QOverload<double>::of(&QDoubleSpinBox::valueChanged),   this, &FormConfigurationKey::valueChanged);
    }
    // QCheckBox
    else if (auto check = qobject_cast<QCheckBox*>(widget)) {
        connect(check,      &QCheckBox::stateChanged,                               this, &FormConfigurationKey::valueChanged);
    }
    // QComboBox
    else if (auto combo = qobject_cast<QComboBox*>(widget)) {
        connect(combo,      QOverload<int>::of(&QComboBox::currentIndexChanged),    this, &FormConfigurationKey::valueChanged);
    }
    // QDateTimeEdit
    else if (auto dateTime = qobject_cast<QDateTimeEdit*>(widget)) {
        connect(dateTime,   &QDateTimeEdit::dateTimeChanged,                        this, &FormConfigurationKey::valueChanged);
    }

    // 递归遍历所有子控件
    auto list = widget->findChildren<QWidget*>();
    for (auto child : std::as_const(list)) {
        connectAllValueChanged(child);
    }
}

void FormConfigurationKey::refreshConfig(const CONFIG_KEY_INFO &info)
{
    ui->allowOfflineTxForUnknownId->setChecked(info.CoreProfile.AllowOfflineTxForUnknownId);
    ui->authorizationCacheEnabled->setChecked(info.CoreProfile.AuthorizationCacheEnabled);
    ui->authorizeRemoteTxRequests->setChecked(info.CoreProfile.AuthorizeRemoteTxRequests);
    ui->blinkRepeat->setValue(info.CoreProfile.BlinkRepeat);
    ui->clockAlignedDataInterval->setValue(info.CoreProfile.ClockAlignedDataInterval);
    ui->connectionTimeOut->setValue(info.CoreProfile.ConnectionTimeOut);
    ui->connectorPhaseRotation->setText(info.CoreProfile.ConnectorPhaseRotation.join(';'));
    ui->connectorPhaseRotation->setFormType(General::Type::LONG_TEXT);
    ui->connectorPhaseRotationMaxLength->setValue(info.CoreProfile.ConnectorPhaseRotationMaxLength);
    ui->getConfigurationMaxKeys->setValue(info.CoreProfile.GetConfigurationMaxKeys);
    ui->heartbeatInterval->setValue(info.CoreProfile.HeartbeatInterval);
    ui->lightIntensity->setValue(info.CoreProfile.LightIntensity);
    ui->localAuthorizeOffline->setChecked(info.CoreProfile.LocalAuthorizeOffline);
    ui->localPreAuthorize->setChecked(info.CoreProfile.LocalPreAuthorize);
    ui->maxEnergyOnInvalidId->setValue(info.CoreProfile.MaxEnergyOnInvalidId);
    ui->meterValuesAlignedDataMaxLength->setValue(info.CoreProfile.MeterValuesAlignedDataMaxLength);
    ui->meterValuesSampledDataMaxLength->setValue(info.CoreProfile.MeterValuesSampledDataMaxLength);
    ui->meterValueSampleInterval->setValue(info.CoreProfile.MeterValueSampleInterval);
    ui->minimumStatusDuration->setValue(info.CoreProfile.MinimumStatusDuration);
    ui->numberOfConnectors->setValue(info.CoreProfile.NumberOfConnectors);
    ui->resetRetries->setValue(info.CoreProfile.ResetRetries);
    ui->stopTransactionOnEVSideDisconnect->setChecked(info.CoreProfile.StopTransactionOnEVSideDisconnect);
    ui->stopTransactionOnInvalidId->setChecked(info.CoreProfile.StopTransactionOnInvalidId);
    ui->stopTxnAlignedDataMaxLength->setValue(info.CoreProfile.StopTxnAlignedDataMaxLength);
    ui->stopTxnSampledDataMaxLength->setValue(info.CoreProfile.StopTxnSampledDataMaxLength);
    ui->supportedFeatureProfiles->setText(info.CoreProfile.SupportedFeatureProfiles.join(';'));
    ui->supportedFeatureProfiles->setFormType(General::Type::LONG_TEXT);
    ui->supportedFeatureProfilesMaxLength->setValue(info.CoreProfile.SupportedFeatureProfilesMaxLength);
    ui->transactionMessageAttempts->setValue(info.CoreProfile.TransactionMessageAttempts);
    ui->transactionMessageRetryInterval->setValue(info.CoreProfile.TransactionMessageRetryInterval);
    ui->unlockConnectorOnEVSideDisconnect->setChecked(info.CoreProfile.UnlockConnectorOnEVSideDisconnect);
    ui->webSocketPingInterval->setValue(info.CoreProfile.WebSocketPingInterval);
    ui->authorizationKey->setText(info.CoreProfile.AuthorizationKey);
    ui->authorizationCacheMaxLength->setValue(info.CoreProfile.AuthorizationCacheMaxLength);
    ui->localAuthListEnabled->setChecked(info.LocalAuthListManagementProfile.LocalAuthListEnabled);
    ui->localAuthListMaxLength->setValue(info.LocalAuthListManagementProfile.LocalAuthListMaxLength);
    ui->sendLocalListMaxLength->setValue(info.LocalAuthListManagementProfile.SendLocalListMaxLength);
    ui->reserveConnectorZeroSupported->setChecked(info.ReservationProfile.ReserveConnectorZeroSupported);
    ui->chargeProfileMaxStackLevel->setValue(info.SmartChargingProfile.ChargeProfileMaxStackLevel);
    ui->chargingScheduleAllowedChargingRateUnit->setText(info.SmartChargingProfile.ChargingScheduleAllowedChargingRateUnit.join(';'));
    ui->chargingScheduleAllowedChargingRateUnit->setFormType(General::Type::LONG_TEXT);
    ui->chargingScheduleMaxPeriods->setValue(info.SmartChargingProfile.ChargingScheduleMaxPeriods);
    ui->connectorSwitch3to1PhaseSupported->setChecked(info.SmartChargingProfile.ConnectorSwitch3to1PhaseSupported);
    ui->maxChargingProfilesInstalled->setValue(info.SmartChargingProfile.MaxChargingProfilesInstalled);
}

int FormConfigurationKey::calculateTextEditHeight(QTextEdit *textEdit)
{
    int docHeight = textEdit->document()->size().height();
    int margins = textEdit->contentsMargins().top() + textEdit->contentsMargins().bottom();
    return docHeight + margins;
}

CONFIG_KEY_INFO FormConfigurationKey::getConfigKey()
{
    CONFIG_KEY_INFO info;
    info.CoreProfile.AllowOfflineTxForUnknownId                         = ui->allowOfflineTxForUnknownId->isChecked();
    info.CoreProfile.AuthorizationCacheEnabled                          = ui->authorizationCacheEnabled->isChecked();
    info.CoreProfile.AuthorizeRemoteTxRequests                          = ui->authorizeRemoteTxRequests->isChecked();
    info.CoreProfile.BlinkRepeat                                        = ui->blinkRepeat->value();
    info.CoreProfile.ClockAlignedDataInterval                           = ui->clockAlignedDataInterval->value();
    info.CoreProfile.ConnectionTimeOut                                  = ui->connectionTimeOut->value();
    info.CoreProfile.ConnectorPhaseRotation                             = ui->connectorPhaseRotation->text().split(';');
    info.CoreProfile.ConnectorPhaseRotationMaxLength                    = ui->connectorPhaseRotationMaxLength->value();
    info.CoreProfile.GetConfigurationMaxKeys                            = ui->getConfigurationMaxKeys->value();
    info.CoreProfile.HeartbeatInterval                                  = ui->heartbeatInterval->value();
    info.CoreProfile.LightIntensity                                     = ui->lightIntensity->value();
    info.CoreProfile.LocalAuthorizeOffline                              = ui->localAuthorizeOffline->isChecked();
    info.CoreProfile.LocalPreAuthorize                                  = ui->localPreAuthorize->isChecked();
    info.CoreProfile.MaxEnergyOnInvalidId                               = ui->maxEnergyOnInvalidId->value();
    info.CoreProfile.MeterValuesAlignedDataMaxLength                    = ui->meterValuesAlignedDataMaxLength->value();
    info.CoreProfile.MeterValuesSampledDataMaxLength                    = ui->meterValuesSampledDataMaxLength->value();
    info.CoreProfile.MeterValueSampleInterval                           = ui->meterValueSampleInterval->value();
    info.CoreProfile.MinimumStatusDuration                              = ui->minimumStatusDuration->value();
    info.CoreProfile.NumberOfConnectors                                 = ui->numberOfConnectors->value();
    info.CoreProfile.ResetRetries                                       = ui->resetRetries->value();
    info.CoreProfile.StopTransactionOnEVSideDisconnect                  = ui->stopTransactionOnEVSideDisconnect->isChecked();
    info.CoreProfile.StopTransactionOnInvalidId                         = ui->stopTransactionOnInvalidId->isChecked();
    info.CoreProfile.StopTxnAlignedDataMaxLength                        = ui->stopTxnAlignedDataMaxLength->value();
    info.CoreProfile.StopTxnSampledDataMaxLength                        = ui->stopTxnSampledDataMaxLength->value();
    info.CoreProfile.SupportedFeatureProfiles                           = ui->supportedFeatureProfiles->text().split(';');
    info.CoreProfile.SupportedFeatureProfilesMaxLength                  = ui->supportedFeatureProfilesMaxLength->value();
    info.CoreProfile.TransactionMessageAttempts                         = ui->transactionMessageAttempts->value();
    info.CoreProfile.TransactionMessageRetryInterval                    = ui->transactionMessageRetryInterval->value();
    info.CoreProfile.UnlockConnectorOnEVSideDisconnect                  = ui->unlockConnectorOnEVSideDisconnect->isChecked();
    info.CoreProfile.WebSocketPingInterval                              = ui->webSocketPingInterval->value();
    info.CoreProfile.AuthorizationKey                                   = ui->authorizationKey->text();
    info.CoreProfile.AuthorizationCacheMaxLength                        = ui->authorizationCacheMaxLength->value();
    info.LocalAuthListManagementProfile.LocalAuthListEnabled            = ui->localAuthListEnabled->isChecked();
    info.LocalAuthListManagementProfile.LocalAuthListMaxLength          = ui->localAuthListMaxLength->value();
    info.LocalAuthListManagementProfile.SendLocalListMaxLength          = ui->sendLocalListMaxLength->value();
    info.ReservationProfile.ReserveConnectorZeroSupported               = ui->reserveConnectorZeroSupported->isChecked();
    info.SmartChargingProfile.ChargeProfileMaxStackLevel                = ui->chargeProfileMaxStackLevel->value();
    info.SmartChargingProfile.ChargingScheduleAllowedChargingRateUnit   = ui->chargingScheduleAllowedChargingRateUnit->text().split(';');
    info.SmartChargingProfile.ChargingScheduleMaxPeriods                = ui->chargingScheduleMaxPeriods->value();
    info.SmartChargingProfile.ConnectorSwitch3to1PhaseSupported         = ui->connectorSwitch3to1PhaseSupported->isChecked();
    info.SmartChargingProfile.MaxChargingProfilesInstalled              = ui->maxChargingProfilesInstalled->value();
    return info;
}

void FormConfigurationKey::valueChanged()
{
    setIsModify(true);
}

void FormConfigurationKey::showEvent(QShowEvent *event)
{
    m_cfg_key = ConfigManager::instance()->cfg_key();
    refreshConfig(m_cfg_key);
    setIsModify(false);
    BaseWidget::showEvent(event);
}

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