//  ************************************************************************************************
//
//  BornAgain: simulate and fit reflection and scattering
//
//! @file      GUI/Model/Sample/ProfilesCatalogs.cpp
//! @brief     Implements classes Profile1DItemCatalog, Profile2DItemCatalog.
//!
//! @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/Model/Sample/ProfilesCatalogs.h"
#include "Base/Util/Assert.h"
#include "GUI/Model/Sample/ProfileItems.h"

Profile1DItemCatalog::BaseType* Profile1DItemCatalog::create(Type type)
{
    switch (type) {
    case Type::Cauchy:
        return new Profile1DCauchyItem();
    case Type::Gauss:
        return new Profile1DGaussItem();
    case Type::Gate:
        return new Profile1DGateItem();
    case Type::Triangle:
        return new Profile1DTriangleItem();
    case Type::Cosine:
        return new Profile1DCosineItem();
    case Type::Voigt:
        return new Profile1DVoigtItem();
    default:
        ASSERT_NEVER;
    }
}

QVector<Profile1DItemCatalog::Type> Profile1DItemCatalog::types()
{
    return {Type::Cauchy, Type::Gauss, Type::Gate, Type::Triangle, Type::Cosine, Type::Voigt};
}

UiInfo Profile1DItemCatalog::uiInfo(Type type)
{
    switch (type) {
    case Type::Cauchy:
        return {"Cauchy 1D", "One-dimensional Cauchy probability distribution", ""};
    case Type::Gauss:
        return {"Gauss 1D", "One-dimensional Gauss probability distribution", ""};
    case Type::Gate:
        return {"Gate 1D", "One-dimensional Gate probability distribution", ""};
    case Type::Triangle:
        return {"Triangle 1D", "One-dimensional triangle probability distribution", ""};
    case Type::Cosine:
        return {"Cosine 1D", "One-dimensional Cosine probability distribution", ""};
    case Type::Voigt:
        return {"Voigt 1D", "One-dimensional pseudo-Voigt probability distribution", ""};
    default:
        ASSERT_NEVER;
    }
}

Profile1DItemCatalog::Type Profile1DItemCatalog::type(const BaseType* item)
{
    ASSERT(item);

#define RETURN_IF(type)                                                                            \
    if (dynamic_cast<const Profile1D##type##Item*>(item))                                          \
    return Type::type

    RETURN_IF(Cauchy);
    RETURN_IF(Gauss);
    RETURN_IF(Gate);
    RETURN_IF(Triangle);
    RETURN_IF(Cosine);
    RETURN_IF(Voigt);
#undef RETURN_IF

    ASSERT_NEVER;
}

/* --------------------------------------------------------------------------------------------- */

Profile2DItemCatalog::BaseType* Profile2DItemCatalog::create(Type type)
{
    switch (type) {
    case Type::Cauchy:
        return new Profile2DCauchyItem();
    case Type::Gauss:
        return new Profile2DGaussItem();
    case Type::Gate:
        return new Profile2DGateItem();
    case Type::Cone:
        return new Profile2DConeItem();
    case Type::Voigt:
        return new Profile2DVoigtItem();
    default:
        ASSERT_NEVER;
    }
}

QVector<Profile2DItemCatalog::Type> Profile2DItemCatalog::types()
{
    return {Type::Cauchy, Type::Gauss, Type::Gate, Type::Cone, Type::Voigt};
}

Profile2DItemCatalog::UiInfo Profile2DItemCatalog::uiInfo(Type type)
{
    switch (type) {
    case Type::Cauchy:
        return {"Cauchy 2D", "Two-dimensional Cauchy probability distribution", ""};
    case Type::Gauss:
        return {"Gauss 2D", "Two-dimensional Gauss probability distribution", ""};
    case Type::Gate:
        return {"Gate 2D", "Two-dimensional Gate probability distribution", ""};
    case Type::Cone:
        return {"Cone 2D", "Two-dimensional Cone probability distribution", ""};
    case Type::Voigt:
        return {"Voigt 2D", "Two-dimensional pseudo-Voigt probability distribution", ""};
    default:
        ASSERT_NEVER;
    }
}

Profile2DItemCatalog::Type Profile2DItemCatalog::type(const BaseType* item)
{
    ASSERT(item);

    if (dynamic_cast<const Profile2DCauchyItem*>(item))
        return Type::Cauchy;
    if (dynamic_cast<const Profile2DGaussItem*>(item))
        return Type::Gauss;
    if (dynamic_cast<const Profile2DGateItem*>(item))
        return Type::Gate;
    if (dynamic_cast<const Profile2DConeItem*>(item))
        return Type::Cone;
    if (dynamic_cast<const Profile2DVoigtItem*>(item))
        return Type::Voigt;

    ASSERT_NEVER;
}
