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

#include "GUI/View/Device/AxisForm.h"
#include "GUI/Model/Descriptor/AxisProperty.h"
#include "GUI/Model/Project/ProjectDocument.h"
#include "GUI/View/Numeric/DSpinBox.h"
#include "GUI/View/Numeric/NumWidgetUtil.h"
#include <QFormLayout>
#include <QSpinBox>

AxisForm::AxisForm(QWidget* parent, const QString& group_title, AxisProperty* axis_property,
                   QString nbins_tooltip)
    : StaticGroupBox(group_title, parent)
{
    auto* layout = new QFormLayout;
    body()->setLayout(layout);
    setFixedWidth(300);

    layout->setFieldGrowthPolicy(QFormLayout::FieldsStayAtSizeHint);

    QSpinBox* nbins_spin_box =
        GUI::Util::createIntSpinBox([axis_property] { return axis_property->nbins(); },
                                    [this, axis_property](int v) {
                                        axis_property->setNbins(v);
                                        emit dataChanged();
                                        gDoc->setModified();
                                    },
                                    RealLimits::nonnegative(), nbins_tooltip);
    layout->addRow("# bins:", nbins_spin_box);

    DSpinBox* min_spin_box = GUI::Util::addDoubleSpinBoxRow(layout, axis_property->min());
    DSpinBox* max_spin_box = GUI::Util::addDoubleSpinBoxRow(layout, axis_property->max());

    connect(min_spin_box, &DSpinBox::valueChanged, [this, axis_property, max_spin_box](double v) {
        if (axis_property->min().dVal() != v) {
            axis_property->min().setDVal(v);
            emit dataChanged();
            if (axis_property->max().dVal() < v) {
                axis_property->max().setDVal(v);
                max_spin_box->updateValue();
            }
        }
    });

    connect(max_spin_box, &DSpinBox::valueChanged, [this, axis_property, min_spin_box](double v) {
        if (axis_property->max().dVal() != v) {
            axis_property->max().setDVal(v);
            emit dataChanged();
            if (axis_property->min().dVal() > v) {
                axis_property->min().setDVal(v);
                min_spin_box->updateValue();
            }
        }
    });
}
