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

Profile1DItem* Profile1DCatalog::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<Profile1DCatalog::Type> Profile1DCatalog::types()
{
    return {Type::Cauchy, Type::Gauss, Type::Gate, Type::Triangle, Type::Cosine, Type::Voigt};
}

UiInfo Profile1DCatalog::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;
    }
}

Profile1DCatalog::Type Profile1DCatalog::type(const Profile1DItem* 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;
}

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

Profile2DItem* Profile2DCatalog::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<Profile2DCatalog::Type> Profile2DCatalog::types()
{
    return {Type::Cauchy, Type::Gauss, Type::Gate, Type::Cone, Type::Voigt};
}

UiInfo Profile2DCatalog::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;
    }
}

Profile2DCatalog::Type Profile2DCatalog::type(const Profile2DItem* 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;
}
