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

#include "GUI/View/Device/DetectorEditor.h"
#include "Base/Util/Assert.h"
#include "GUI/Model/Detector/DetectorItem.h"
#include "GUI/Model/Detector/ResolutionFunctionItems.h"
#include "GUI/Model/Sim/InstrumentItems.h"
#include "GUI/View/Device/SpanPropertyForm.h"
#include "GUI/View/Numeric/ComboUtil.h"
#include "GUI/View/Numeric/DoubleSpinBox.h"
#include "GUI/View/Numeric/NumWidgetUtil.h"
#include "GUI/View/Numeric/SafeSpinBox.h"
#include <QFormLayout>

DetectorEditor::DetectorEditor(QWidget* parent, Scatter2DInstrumentItem* instrItem)
    : CollapsibleGroupBox("Detector parameters", parent, instrItem->expandDetector)
{
    auto* layout = new QVBoxLayout;
    body()->setLayout(layout);

    DetectorItem* detectorItem = instrItem->detectorItem();
    ASSERT(detectorItem);

    auto* xyrow = new QHBoxLayout;
    layout->addLayout(xyrow);

    auto* phiForm =
        new SpanPropertyForm(this, u8"\u03c6 axis", &detectorItem->phiAxis(), "phi axis");
    xyrow->addWidget(phiForm);

    auto* alphaForm =
        new SpanPropertyForm(this, u8"\u03b1 axis", &detectorItem->alphaAxis(), "alpha axis");
    xyrow->addWidget(alphaForm);

    //... resolution controls

    auto* resolutionForm = new StaticGroupBox("Resolution function", this);
    xyrow->addWidget(resolutionForm);

    auto* resolutionLayout = new QFormLayout;
    resolutionForm->body()->setLayout(resolutionLayout);
    resolutionLayout->setFieldGrowthPolicy(QFormLayout::FieldsStayAtSizeHint);

    auto updateResolutionForm = [parent = this, layout = resolutionLayout,
                                 item = detectorItem]() -> void {
        while (layout->rowCount() > 1)
            layout->removeRow(1);

        auto* resFunction = item->resolutionFunctionSelection().certainItem();
        if (auto* p = dynamic_cast<ResolutionFunction2DGaussianItem*>(resFunction)) {
            auto* sigmaXSpinBox = GUI::Util::createDoubleSpinBoxRow(layout, p->sigmaX());
            auto* sigmaYSpinBox = GUI::Util::createDoubleSpinBoxRow(layout, p->sigmaY());

            connect(sigmaXSpinBox, &DoubleSpinBox::valueChanged, [parent, p](double newValue) {
                p->setSigmaX(newValue);
                emit parent->dataChanged();
            });

            connect(sigmaYSpinBox, &DoubleSpinBox::valueChanged, [parent, p](double newValue) {
                p->setSigmaY(newValue);
                emit parent->dataChanged();
            });
        }
    };

    auto* typeCombo = GUI::Util::createComboBoxFromProperty(
        detectorItem->resolutionFunctionSelection(),
        [this, updateResolutionForm](int) {
            updateResolutionForm();
            emit dataChanged();
        },
        true);
    resolutionLayout->addRow("Type:", typeCombo);

    updateResolutionForm();
}
