//  ************************************************************************************************
//
//  BornAgain: simulate and fit reflection and scattering
//
//! @file      Sim/Export/SceneGeometry.h
//! @brief     Declares the complete 3D scene description exported by buildScene3D.
//!
//! @homepage  http://www.bornagainproject.org
//! @license   GNU General Public License v3 or higher (see COPYING)
//! @copyright Forschungszentrum Jülich GmbH 2026
//! @authors   Scientific Computing Group at MLZ (see CITATION, AUTHORS)
//
//  ************************************************************************************************

#ifndef BORNAGAIN_SIM_EXPORT_SCENEGEOMETRY_H
#define BORNAGAIN_SIM_EXPORT_SCENEGEOMETRY_H

#include <string>
#include <vector>

class Sample;

//! RGBA color with float components in [0, 1]. Plain struct, no Qt dependency.
struct ColorRgba {
    float r = 0.0f;
    float g = 0.0f;
    float b = 0.0f;
    float a = 1.0f;
};

//! Describes a single particle in the 3D scene.
struct ParticleData {
    std::string shape;
    std::vector<std::string> param_names;
    std::vector<double> param_values;
    double pos_x;
    double pos_y;
    double pos_z;
    double euler_alpha;
    double euler_beta;
    double euler_gamma;
    std::string material;
    ColorRgba color;
    int alignment;
    //! Polyhedron geometry: parallel coordinate arrays (empty for smooth shapes).
    std::vector<double> vert_x, vert_y, vert_z;
    //! Polyhedron faces: face_vertex_counts[i] gives the number of vertices in face i;
    //! face_vertex_indices is the flattened list of vertex indices for all faces.
    std::vector<int> face_vertex_counts;
    std::vector<int> face_vertex_indices;
    //! Mixture activation path: the particle is visible only if each group picked its variant.
    std::vector<int> mixture_groups;
    std::vector<int> mixture_variants;
#ifndef SWIG
    ParticleData()
        : pos_x(0)
        , pos_y(0)
        , pos_z(0)
        , euler_alpha(0)
        , euler_beta(0)
        , euler_gamma(0)
        , alignment(0)
    {
    }
#endif
};

//! Describes a particle layout (struct) in the 3D scene.
struct StructData {
    std::string type;      //!< "Crystal2D", "FiniteCrystal2D", "Dilute2D", etc.
    std::string placement; //!< "deposit" (bottom), "suspend" (top), or "fill" (volume)
    double ref_z;
    std::vector<double> pos_x, pos_y, pos_z; //!< generated layout positions
    std::vector<ParticleData> particles;
    //! Per-mixture-group normalized variant weights, indexed as [group_id][variant_id].
    std::vector<std::vector<double>> mixture_weights;
#ifndef SWIG
    StructData()
        : ref_z(0)
    {
    }
#endif
};

//! Describes a layer in the 3D scene.
struct LayerData {
    std::string material;
    ColorRgba color;
    double z_top;
    double z_bottom;
    bool semi_infinite;
    unsigned roughness_nx;
    unsigned roughness_ny;
    //! Row-major height offsets, in nm, for the layer top interface. Empty means flat.
    std::vector<double> top_roughness;
#ifndef SWIG
    LayerData()
        : z_top(0)
        , z_bottom(0)
        , semi_infinite(false)
        , roughness_nx(0)
        , roughness_ny(0)
    {
    }
#endif
};

//! Complete 3D scene geometry for a sample, ready for Python rendering.
struct SceneDescription {
    std::vector<LayerData> layers;
    std::vector<StructData> structs;
    double lateral_half_extent = 0.0;
};

//! Returns the 3D scene description for the given sample.
//! @param lateral_half_extent  Half side length of the visible sample patch.
//! @param seed                 Base seed for random particle positions (disordered layouts).
//!                             Different seeds produce different position configurations.
//! @param roughness_points     Points along each axis for rough interface maps; 0 disables them.
//!                             Values above the supported display range are limited with a warning.
SceneDescription buildScene3D(const Sample& sample, double lateral_half_extent, unsigned seed = 0,
                              unsigned roughness_points = 0);

#endif // BORNAGAIN_SIM_EXPORT_SCENEGEOMETRY_H
