//  ************************************************************************************************
//
//  BornAgain: simulate and fit reflection and scattering
//
//! @file      Img3D/Model/ParticleFromFF.cpp
//! @brief     Implements namespace GUI::View::TransformTo3D.
//!
//! @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 "Img3D/Model/ParticleFromFF.h"
#include "Img3D/Model/Particles.h"
#include "Sample/HardParticle/HardParticles.h"

std::unique_ptr<Img3D::PlotParticle> Img3D::particle3DfromFF(const IFormFactor* ff)
{
    if (const auto* f = dynamic_cast<const Pyramid2*>(ff)) {
        double length = f->length();
        double width = f->width();
        double height = f->height();
        double alpha = f->alpha();
        return std::make_unique<Img3D::Particles::Pyramid2>(length, width, height, alpha);
    }
    if (const auto* f = dynamic_cast<const BarGauss*>(ff)) {
        double length = f->length();
        double width = f->width();
        double height = f->height();
        return std::make_unique<Img3D::Particles::BarGauss>(length, width, height);
    }
    if (const auto* f = dynamic_cast<const BarLorentz*>(ff)) {
        double length = f->length();
        double width = f->width();
        double height = f->height();
        return std::make_unique<Img3D::Particles::BarLorentz>(length, width, height);
    }
    if (const auto* f = dynamic_cast<const Box*>(ff)) {
        double length = f->length();
        double width = f->width();
        double height = f->height();
        return std::make_unique<Img3D::Particles::Box>(length, width, height);
    }
    if (const auto* f = dynamic_cast<const Cone*>(ff)) {
        double radius = f->radius();
        double height = f->height();
        double alpha = f->alpha();
        return std::make_unique<Img3D::Particles::Cone>(radius, height, alpha);
    }
    if (const auto* f = dynamic_cast<const Pyramid6*>(ff)) {
        double baseedge = f->baseEdge();
        double height = f->height();
        double alpha = f->alpha();
        return std::make_unique<Img3D::Particles::Pyramid6>(baseedge, height, alpha);
    }
    if (const auto* f = dynamic_cast<const Bipyramid4*>(ff)) {
        double length = f->length();
        double base_height = f->base_height();
        double height_ratio = f->heightRatio();
        double alpha = f->alpha();
        return std::make_unique<Img3D::Particles::Bipyramid4>(length, base_height, height_ratio,
                                                              alpha);
    }
    if (const auto* f = dynamic_cast<const Cylinder*>(ff)) {
        double radius = f->radius();
        double height = f->height();
        return std::make_unique<Img3D::Particles::Cylinder>(radius, height);
    }
    if (const auto* f = dynamic_cast<const Dodecahedron*>(ff)) {
        double edge = f->edge();
        return std::make_unique<Img3D::Particles::Dodecahedron>(edge);
    }
    if (const auto* f = dynamic_cast<const EllipsoidalCylinder*>(ff)) {
        double radius_x = f->radiusX();
        double radius_y = f->radiusY();
        double height = f->height();
        return std::make_unique<Img3D::Particles::EllipsoidalCylinder>(radius_x, radius_y, height);
    }
    if (const auto* f = dynamic_cast<const Sphere*>(ff)) {
        double radius = f->radius();
        return std::make_unique<Img3D::Particles::Sphere>(radius);
    }
    if (const auto* f = dynamic_cast<const Spheroid*>(ff)) {
        double radius = f->radius();
        double height = f->height();
        return std::make_unique<Img3D::Particles::Spheroid>(radius, height);
    }
    if (const auto* f = dynamic_cast<const HemiEllipsoid*>(ff)) {
        double radius_x = f->radiusX();
        double radius_y = f->radiusY();
        double height = f->height();
        return std::make_unique<Img3D::Particles::HemiEllipsoid>(radius_x, radius_y, height);
    }
    if (const auto* f = dynamic_cast<const Icosahedron*>(ff)) {
        double edge = f->edge();
        return std::make_unique<Img3D::Particles::Icosahedron>(edge);
    }
    if (const auto* f = dynamic_cast<const Prism3*>(ff)) {
        double baseedge = f->baseEdge();
        double height = f->height();
        return std::make_unique<Img3D::Particles::Prism3>(baseedge, height);
    }
    if (const auto* f = dynamic_cast<const Prism6*>(ff)) {
        double baseedge = f->baseEdge();
        double height = f->height();
        return std::make_unique<Img3D::Particles::Prism6>(baseedge, height);
    }
    if (const auto* f = dynamic_cast<const Pyramid4*>(ff)) {
        double baseedge = f->baseEdge();
        double height = f->height();
        double alpha = f->alpha();
        return std::make_unique<Img3D::Particles::Pyramid4>(baseedge, height, alpha);
    }
    if (const auto* f = dynamic_cast<const CosineRippleBox*>(ff)) {
        double length = f->length();
        double width = f->width();
        double height = f->height();
        return std::make_unique<Img3D::Particles::CosineRippleBox>(length, width, height);
    }
    if (const auto* f = dynamic_cast<const CosineRippleGauss*>(ff)) {
        double length = f->length();
        double width = f->width();
        double height = f->height();
        return std::make_unique<Img3D::Particles::CosineRippleGauss>(length, width, height);
    }
    if (const auto* f = dynamic_cast<const CosineRippleLorentz*>(ff)) {
        double length = f->length();
        double width = f->width();
        double height = f->height();
        return std::make_unique<Img3D::Particles::CosineRippleLorentz>(length, width, height);
    }
    if (const auto* f = dynamic_cast<const SawtoothRippleBox*>(ff)) {
        double length = f->length();
        double width = f->width();
        double height = f->height();
        return std::make_unique<Img3D::Particles::SawtoothRippleBox>(length, width, height);
    }
    if (const auto* f = dynamic_cast<const SawtoothRippleGauss*>(ff)) {
        double length = f->length();
        double width = f->width();
        double height = f->height();
        return std::make_unique<Img3D::Particles::SawtoothRippleGauss>(length, width, height);
    }
    if (const auto* f = dynamic_cast<const SawtoothRippleLorentz*>(ff)) {
        double length = f->length();
        double width = f->width();
        double height = f->height();
        return std::make_unique<Img3D::Particles::SawtoothRippleLorentz>(length, width, height);
    }
    if (const auto* f = dynamic_cast<const Pyramid3*>(ff)) {
        double baseedge = f->baseEdge();
        double height = f->height();
        double alpha = f->alpha();
        return std::make_unique<Img3D::Particles::Pyramid3>(baseedge, height, alpha);
    }
    if (const auto* f = dynamic_cast<const TruncatedCube*>(ff)) {
        double length = f->length();
        double removed_length = f->removedLength();
        return std::make_unique<Img3D::Particles::TruncatedCube>(length, removed_length);
    }
    if (const auto* f = dynamic_cast<const TruncatedSphere*>(ff)) {
        double radius = f->radius();
        double untruncated_height = f->untruncated_height();
        double deltaH = f->removedTop();
        return std::make_unique<Img3D::Particles::TruncatedSphere>(radius, untruncated_height,
                                                                   deltaH);
    }
    if (const auto* f = dynamic_cast<const TruncatedSpheroid*>(ff)) {
        double radius = f->radius();
        double untruncated_height = f->untruncated_height();
        double hfc = f->heightFlattening();
        double deltaH = f->removedTop();
        return std::make_unique<Img3D::Particles::TruncatedSpheroid>(radius, untruncated_height,
                                                                     hfc, deltaH);
    }
    if (const auto* f = dynamic_cast<const CantellatedCube*>(ff)) {
        double length = f->length();
        double removed_length = f->removedLength();
        return std::make_unique<Img3D::Particles::CantellatedCube>(length, removed_length);
    }
    if (const auto* f = dynamic_cast<const HorizontalCylinder*>(ff)) {
        double radius = f->radius();
        double length = f->length();
        double slice_bottom = f->slice_bottom();
        double slice_top = f->slice_top();
        return std::make_unique<Img3D::Particles::HorizontalCylinder>(radius, length, slice_bottom,
                                                                      slice_top);
    }
    if (const auto* f = dynamic_cast<const PlatonicOctahedron*>(ff)) {
        double edge = f->edge();
        return std::make_unique<Img3D::Particles::PlatonicOctahedron>(edge);
    }
    if (const auto* f = dynamic_cast<const PlatonicTetrahedron*>(ff)) {
        double edge = f->edge();
        return std::make_unique<Img3D::Particles::PlatonicTetrahedron>(edge);
    }
    return {};
}
