//  ************************************************************************************************
//
//  BornAgain: simulate and fit reflection and scattering
//
//! @file      GUI/View/Sample/HeinzFormLayout.cpp
//! @brief     Implements class HeinzFormLayout.
//!
//! @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/View/Sample/HeinzFormLayout.h"
#include "Base/Util/Assert.h"
#include "GUI/Model/Descriptor/VectorProperty.h"
#include "GUI/View/Numeric/DoubleSpinBox.h"
#include "GUI/View/Sample/LayerEditorUtil.h"
#include "GUI/View/Sample/SampleEditorController.h"
#include "GUI/View/Widget/GroupBoxes.h"
#include <QLabel>
#include <QPushButton>

namespace {

QLabel* createBoldLabel(const QString& text)
{
    auto* l = new QLabel(text);
    QFont f = l->font();
    f.setBold(true);
    l->setFont(f);
    return l;
}

} // namespace


HeinzFormLayout::HeinzFormLayout(SampleEditorController* ec)
    : m_ec(ec)
{
    QFormLayout::setFormAlignment(Qt::AlignLeft | Qt::AlignBottom);
    QFormLayout::setFieldGrowthPolicy(QFormLayout::FieldsStayAtSizeHint);
}

void HeinzFormLayout::insertRow(int row, QString label, QWidget* w)
{
    if (!label.endsWith(":"))
        label += ":";
    QFormLayout::insertRow(row, ::createBoldLabel(label), w);
}

void HeinzFormLayout::insertRow(int row, QWidget* w)
{
    QFormLayout::insertRow(row, w);
}

void HeinzFormLayout::addBoldRow(const QString& label, QWidget* w)
{
    insertRow(rowCount(), label, w);
}

void HeinzFormLayout::addGroupOfValues(const QString& labelText, const DoubleProperties& values)
{
    auto* w = new QWidget(QFormLayout::parentWidget());
    w->setObjectName("PropertyBaseWidget");
    w->setAttribute(Qt::WA_StyledBackground, true);
    w->setStyleSheet("#PropertyBaseWidget {background-color: transparent}");

    auto* gridLayout = new QGridLayout(w);
    gridLayout->setContentsMargins(0, 0, 0, 0);
    gridLayout->setSpacing(6);

    GUI::Util::Layer::addMultiPropertyToGrid(gridLayout, 0, values, m_ec, true);

    addBoldRow(labelText, w);
}

void HeinzFormLayout::addVector(VectorProperty& d, bool vertically /*= true*/)
{
    auto* w = new QWidget(QFormLayout::parentWidget());
    w->setObjectName("PropertyBaseWidget");
    w->setAttribute(Qt::WA_StyledBackground, true);
    w->setStyleSheet("#PropertyBaseWidget {background-color: transparent}");

    auto* gridLayout = new QGridLayout(w);
    gridLayout->setContentsMargins(0, 0, 0, 0);
    gridLayout->setSpacing(6);

    GUI::Util::Layer::addMultiPropertyToGrid(gridLayout, 0, {&d.x(), &d.y(), &d.z()}, m_ec,
                                             vertically, true);
    addBoldRow(d.label(), w);
}

void HeinzFormLayout::setRowVisible(int row, bool visible)
{
    QFormLayout::itemAt(row, QFormLayout::LabelRole)->widget()->setVisible(visible);
    QFormLayout::itemAt(row, QFormLayout::FieldRole)->widget()->setVisible(visible);
}

void HeinzFormLayout::addStructureEditingRow(QPushButton* button)
{
    auto* w = new QWidget(QFormLayout::parentWidget());
    auto* l = new QHBoxLayout(w);
    l->setContentsMargins(0, 0, 0, 0);
    l->setAlignment(Qt::AlignLeft);
    l->setSizeConstraint(QLayout::SetMinimumSize);
    l->addWidget(button);
    QFormLayout::addRow(w);
}

void HeinzFormLayout::addValue(DoubleProperty& d)
{
    insertValue(QFormLayout::rowCount(), d);
}

void HeinzFormLayout::addValue(DoubleProperty& d, std::function<void(double)> onValueChange)
{
    insertValue(QFormLayout::rowCount(), d, onValueChange);
}

void HeinzFormLayout::insertValue(int row, DoubleProperty& d)
{
    insertValue(row, d, [ec = m_ec, &d](double newValue) { ec->setDouble(newValue, d); });
}

void HeinzFormLayout::insertValue(int row, DoubleProperty& d,
                                  std::function<void(double)> onValueChange)
{
    auto* editor = new DoubleSpinBox(&d);
    QObject::connect(editor, &DoubleSpinBox::valueChanged, onValueChange);

    QString labelText = d.label();
    if (!labelText.endsWith(":"))
        labelText += ":";
    QLabel* label = ::createBoldLabel(labelText);
    label->setAlignment(Qt::AlignLeft | Qt::AlignBottom);
    label->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::MinimumExpanding);
    label->setBuddy(editor);

    QFormLayout::insertRow(row, label, editor);
}
