//  ************************************************************************************************
//
//  BornAgain: simulate and fit reflection and scattering
//
//! @file      GUI/coregui/DataLoaders/AutomaticMultiColumnDataLoader1DProperties.cpp
//! @brief     Implements class AutomaticMultiColumnDataLoader1DProperties
//!
//! @homepage  http://www.bornagainproject.org
//! @license   GNU General Public License v3 or higher (see COPYING)
//! @copyright Forschungszentrum Jülich GmbH 2021
//! @authors   Scientific Computing Group at MLZ (see CITATION, AUTHORS)
//
//  ************************************************************************************************

#include "GUI/coregui/DataLoaders/QREDataLoaderProperties.h"
#include "ui_QREDataLoaderProperties.h"
#include <QCheckBox>
#include <QtGui>

QREDataLoaderProperties::QREDataLoaderProperties() : m_allowFactors(false)
{
    m_ui = new Ui::QREDataLoaderProperties;
    m_ui->setupUi(this);

    allowFactors(false);

    connect(m_ui->headerPrefixEdit, &QLineEdit::textChanged, [=]() { emit propertiesChanged(); });
    connect(m_ui->linesToSkipEdit, &QLineEdit::textChanged, [=]() { emit propertiesChanged(); });
    connect(m_ui->separatorCombo, &QComboBox::currentTextChanged,
            [=]() { emit propertiesChanged(); });

    connect(m_ui->enableErrorCheckBox, &QCheckBox::stateChanged, this,
            &QREDataLoaderProperties::onErrorEnablingChanged);

    connect(m_ui->qUnitCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
            [=]() { emit propertiesChanged(); });

    for (int dataType = 0; dataType < 3; dataType++) {

        // In the following: disable the checkbox before signaling propertyChanged to suppress ghost
        // value changes in case the propertiesChanged signals triggers long calculations (the
        // spinbox would see a timeout in its "pressed"-loop and generate a second value change)
        connect(columnSpinBox(dataType), QOverload<int>::of(&QSpinBox::valueChanged), [=]() {
            columnSpinBox(dataType)->setEnabled(false);
            emit propertiesChanged();
            columnSpinBox(dataType)->setEnabled(true);
        });

        connect(factorSpinBox(dataType), QOverload<double>::of(&QDoubleSpinBox::valueChanged),
                [=]() {
                    factorSpinBox(dataType)->setEnabled(false);
                    emit propertiesChanged();
                    factorSpinBox(dataType)->setEnabled(true);
                });
    }
}

void QREDataLoaderProperties::allowFactors(bool b)
{
    m_allowFactors = b;
    for (int dataType = 0; dataType < 3; dataType++) {
        factorLabel(dataType)->setVisible(b);
        factorSpinBox(dataType)->setVisible(b);
    }

    updateErrorEnabling(m_ui->enableErrorCheckBox->isChecked());
}

double QREDataLoaderProperties::factor(int dataType) const
{
    const auto spinBox = factorSpinBox(dataType);
    return spinBox->isVisible() ? spinBox->value() : 1.0;
}

void QREDataLoaderProperties::updateErrorEnabling(bool enabled)
{
    const int lineInLayout = 2;

    for (int col = 2; col < m_ui->gridLayout->columnCount(); col++) {
        const auto layoutItem = m_ui->gridLayout->itemAtPosition(lineInLayout, col);
        if (layoutItem) {
            QWidget* w = layoutItem->widget();
            if (w) {
                const bool belongsToFactor = col == factorColumn || col == factorLabelColumn;
                w->setVisible(enabled && (!belongsToFactor || m_allowFactors));
            }
        }
    }
}

void QREDataLoaderProperties::onErrorEnablingChanged()
{
    const bool isEnabled = m_ui->enableErrorCheckBox->isChecked();

    updateErrorEnabling(isEnabled);

    emit propertiesChanged();
}

QSpinBox* QREDataLoaderProperties::columnSpinBox(int dataType) const
{
    const int lineInLayout = dataType;
    return dynamic_cast<QSpinBox*>(
        m_ui->gridLayout->itemAtPosition(lineInLayout, columnColumn)->widget());
}

QDoubleSpinBox* QREDataLoaderProperties::factorSpinBox(int dataType) const
{
    const int lineInLayout = dataType;
    return dynamic_cast<QDoubleSpinBox*>(
        m_ui->gridLayout->itemAtPosition(lineInLayout, factorColumn)->widget());
}

QLabel* QREDataLoaderProperties::factorLabel(int dataType) const
{
    const int lineInLayout = dataType;
    return dynamic_cast<QLabel*>(
        m_ui->gridLayout->itemAtPosition(lineInLayout, factorLabelColumn)->widget());
}
