//  ************************************************************************************************
//
//  BornAgain: simulate and fit reflection and scattering
//
//! @file      GUI/View/PropertyEditor/PropertyEditorFactory.cpp
//! @brief     Implements PropertyEditorFactory namespace
//!
//! @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/PropertyEditor/PropertyEditorFactory.h"
#include "GUI/Model/Data/ComboProperty.h"
#include "GUI/Model/Job/FitParameterItem.h"
#include "GUI/Model/Project/ProjectDocument.h"
#include "GUI/View/Numeric/ScientificSpinBox.h"
#include "GUI/View/PropertyEditor/CustomEditors.h"
#include <QModelIndex>
#include <QSpinBox>

namespace {

double getStep(double val)
{
    return val == 0.0 ? 1.0 : val / 100.;
}

bool isDoubleProperty(const QVariant& variant)
{
    return variant.type() == QVariant::Double;
}

bool isComboProperty(const QVariant& variant)
{
    return variant.canConvert<ComboProperty>();
}

} // namespace


bool GUI::View::PropertyEditorFactory::hasStringRepresentation(const QModelIndex& index)
{
    auto variant = index.data();
    if (isComboProperty(variant))
        return true;
    if (isDoubleProperty(variant) && index.internalPointer())
        return true;

    return false;
}

QString GUI::View::PropertyEditorFactory::toString(const QModelIndex& index)
{
    auto variant = index.data();
    if (isComboProperty(variant))
        return variant.value<ComboProperty>().label();

    if (isDoubleProperty(variant) && index.internalPointer()) {
        auto* item = static_cast<QObject*>(index.internalPointer());
        FitDoubleItem* doubleItem = dynamic_cast<FitDoubleItem*>(item);
        // only "Scientific SpinBoxes" in Fit-Window
        return ScientificSpinBox::toString(doubleItem->value(), doubleItem->decimals());
    }
    return "";
}

QWidget* GUI::View::PropertyEditorFactory::CreateEditor(QObject* item, QWidget* parent)
{
    CustomEditor* result(nullptr);

    if (FitDoubleItem* doubleItem = dynamic_cast<FitDoubleItem*>(item)) {
        // only Scientific SpinBoxes in Fit-Window
        auto* editor = new ScientificSpinBoxEditor;
        editor->setLimits(doubleItem->limits());
        editor->setDecimals(doubleItem->decimals());
        editor->setSingleStep(getStep(doubleItem->value()));
        result = editor;
    } else if (dynamic_cast<FitTypeItem*>(item))
        result = new ComboPropertyEditor;

    if (parent && result) {
        result->setParent(parent);

        QObject::connect(result, &CustomEditor::dataChanged,
                         [=] { gProjectDocument.value()->setModified(); });
    }

    return result;
}
