//#####################################################################
// Copyright 2012.
// This file is part of PhysBAM whose distribution is governed by the license contained in the accompanying file PHYSBAM_COPYRIGHT.txt.
//#####################################################################
// Class VIEWER_OPTIONS
//#####################################################################
#ifndef __VIEWER_OPTIONS__
#define __VIEWER_OPTIONS__

#include <Core/Interpolation/INTERPOLATED_COLOR_MAP.h>
#include <Core/Matrices/FRAME.h>
#include <Core/Matrices/MATRIX.h>
#include <Core/Vectors/VECTOR.h>
namespace PhysBAM{
template<class T>
class OPTION
{
    T value;
    bool valid=false;

public:
    OPTION():valid(false){}
    OPTION(const T& x):value(x),valid(true){}
    OPTION& operator=(const T& x){valid=true;value=x;return *this;}
    bool Valid() const{return valid;}
    const T& Value() const {assert(valid);return value;}
    T& Value() {assert(valid);return value;}
    operator const T& () const{assert(valid);return value;}
    void Set(const T& x){valid=true;value=x;}
    void Invalidate(){valid=false;}
};

struct GLOBAL_OPTIONS
{
    static GLOBAL_OPTIONS def;
    static const char* st_type_prefix;
    OPTION<bool> draw;
    OPTION<std::string> name;
    OPTION<bool> is_2d;
    OPTION<float> scale;
    OPTION<float> point_size;
    OPTION<float> view_scale;
    OPTION<int> substeps_level;
    OPTION<VECTOR<int,2>> window_size;
    OPTION<VECTOR<float,3>> target_position;
    OPTION<MATRIX<float,3>> rotation_matrix;
    void Read_Entry(std::istream& in);
    void Write(std::ostream& out,const std::string& obj_name) const;
    void Merge(const GLOBAL_OPTIONS& o);
};

struct VECTOR_FIELD_OPTIONS
{
    static VECTOR_FIELD_OPTIONS def;
    static const char* st_type_prefix;
    typedef VECTOR<float,3> COLOR;
    OPTION<bool> draw;
    OPTION<std::string> name;
    OPTION<COLOR> color;
    OPTION<bool> cell_centered;
    OPTION<bool> node_selectors;
    OPTION<bool> face_selectors;
    OPTION<bool> cell_selectors;
    void Read_Entry(std::istream& in);
    void Write(std::ostream& out,const std::string& obj_name) const;
    void Merge(const VECTOR_FIELD_OPTIONS& o);
};

struct AXES_OPTIONS
{
    static AXES_OPTIONS def;
    static const char* st_type_prefix;
    OPTION<bool> draw;
    OPTION<std::string> name;
    OPTION<float> length;
    void Read_Entry(std::istream& in);
    void Write(std::ostream& out,const std::string& obj_name) const;
    void Merge(const AXES_OPTIONS& o);
};

struct DEBUG_PARTICLES_OPTIONS
{
    static DEBUG_PARTICLES_OPTIONS def;
    static const char* st_type_prefix;
    OPTION<bool> draw;
    OPTION<std::string> name;
    void Read_Entry(std::istream& in);
    void Write(std::ostream& out,const std::string& obj_name) const;
    void Merge(const DEBUG_PARTICLES_OPTIONS& o);
};

template<class T2> struct FACE_FIELD_OPTIONS;
template<> struct FACE_FIELD_OPTIONS<bool>
{
    static FACE_FIELD_OPTIONS def;
    static const char* st_type_prefix;
    typedef VECTOR<float,3> COLOR;
    OPTION<bool> draw;
    OPTION<std::string> name;
    OPTION<bool> cell_centered;
    OPTION<bool> draw_points;
    OPTION<bool> draw_diamonds;
    OPTION<COLOR> color;
    void Read_Entry(std::istream& in);
    void Write(std::ostream& out,const std::string& obj_name) const;
    void Merge(const FACE_FIELD_OPTIONS& o);
};

template<> struct FACE_FIELD_OPTIONS<int>
{
    static FACE_FIELD_OPTIONS def;
    static const char* st_type_prefix;
    typedef VECTOR<float,3> COLOR;
    OPTION<bool> draw;
    OPTION<std::string> name;
    OPTION<bool> cell_centered;
    OPTION<bool> draw_points;
    OPTION<bool> draw_diamonds;
    OPTION<ARRAY<COLOR>> color_map;
    void Read_Entry(std::istream& in);
    void Write(std::ostream& out,const std::string& obj_name) const;
    void Merge(const FACE_FIELD_OPTIONS& o);
};

template<> struct FACE_FIELD_OPTIONS<float>
{
    static FACE_FIELD_OPTIONS def;
    static const char* st_type_prefix;
    typedef VECTOR<float,3> COLOR;
    OPTION<bool> draw;
    OPTION<std::string> name;
    OPTION<bool> cell_centered;
    OPTION<bool> draw_vorticity;
    OPTION<bool> draw_divergence;
    OPTION<bool> draw_streamlines;
    OPTION<bool> use_seed_for_streamlines;
    OPTION<bool> draw_arrows;
    OPTION<bool> draw_points;
    OPTION<bool> draw_diamonds;
    OPTION<bool> use_fixed_color;
    OPTION<COLOR> color;
    OPTION<float> min;
    OPTION<float> max;
    OPTION<INTERPOLATED_COLOR_MAP<float>> color_map;
    OPTION<int> number_of_steps;
    OPTION<float> min_vorticity;
    OPTION<float> max_vorticity;
    OPTION<int> streamline_seed;
    void Read_Entry(std::istream& in);
    void Write(std::ostream& out,const std::string& obj_name) const;
    void Merge(const FACE_FIELD_OPTIONS& o);
};

struct GRID_OPTIONS
{
    static GRID_OPTIONS def;
    static const char* st_type_prefix;
    typedef VECTOR<float,3> COLOR;
    OPTION<bool> draw;
    OPTION<std::string> name;
    OPTION<COLOR> color;
    OPTION<int> ghost;
    void Read_Entry(std::istream& in);
    void Write(std::ostream& out,const std::string& obj_name) const;
    void Merge(const GRID_OPTIONS& o);
};

struct GROUP_OPTIONS
{
    static GROUP_OPTIONS def;
    static const char* st_type_prefix;
    OPTION<bool> draw;
    OPTION<std::string> name;
    OPTION<ARRAY<std::string>> add;
    OPTION<std::string> source;
    OPTION<std::string> attr;
    OPTION<int> particle_id;
    OPTION<FRAME<VECTOR<float,3>>> frame;
    void Read_Entry(std::istream& in);
    void Write(std::ostream& out,const std::string& obj_name) const;
    void Merge(const GROUP_OPTIONS& o);
};

struct PARTICLES_OPTIONS
{
    static PARTICLES_OPTIONS def;
    static const char* st_type_prefix;
    typedef VECTOR<float,3> COLOR;
    OPTION<bool> draw;
    OPTION<std::string> name;
    OPTION<bool> draw_vectors;
    OPTION<COLOR> default_color;
    OPTION<float> min;
    OPTION<float> max;
    OPTION<INTERPOLATED_COLOR_MAP<float>> color_map;
    OPTION<bool> use_vector_color;
    OPTION<COLOR> vector_color;
    OPTION<bool> visualize_matrix;
    OPTION<std::string> position_attr;
    OPTION<std::string> color_attr;
    OPTION<std::string> vector_attr;
    OPTION<std::string> matrix_attr;
    OPTION<bool> use_color_prog;
    OPTION<std::string> color_prog;
    void Read_Entry(std::istream& in);
    void Write(std::ostream& out,const std::string& obj_name) const;
    void Merge(const PARTICLES_OPTIONS& o);
};

template<class T2> struct SCALAR_FIELD_OPTIONS;
template<> struct SCALAR_FIELD_OPTIONS<bool>
{
    static SCALAR_FIELD_OPTIONS def;
    static const char* st_type_prefix;
    typedef VECTOR<float,3> COLOR;
    OPTION<bool> draw;
    OPTION<std::string> name;
    OPTION<bool> draw_cell_colors;
    OPTION<bool> draw_points;
    OPTION<COLOR> color;
    OPTION<bool> cell_centered;
    void Read_Entry(std::istream& in);
    void Write(std::ostream& out,const std::string& obj_name) const;
    void Merge(const SCALAR_FIELD_OPTIONS& o);
};

template<> struct SCALAR_FIELD_OPTIONS<int>
{
    static SCALAR_FIELD_OPTIONS def;
    static const char* st_type_prefix;
    typedef VECTOR<float,3> COLOR;
    OPTION<bool> draw;
    OPTION<std::string> name;
    OPTION<bool> draw_cell_colors;
    OPTION<bool> draw_points;
    OPTION<ARRAY<COLOR>> color_map;
    OPTION<bool> cell_centered;
    void Read_Entry(std::istream& in);
    void Write(std::ostream& out,const std::string& obj_name) const;
    void Merge(const SCALAR_FIELD_OPTIONS& o);
};

template<> struct SCALAR_FIELD_OPTIONS<float>
{
    static SCALAR_FIELD_OPTIONS def;
    static const char* st_type_prefix;
    OPTION<bool> draw;
    OPTION<std::string> name;
    OPTION<float> min;
    OPTION<float> max;
    OPTION<bool> draw_cell_colors;
    OPTION<bool> draw_smooth_field;
    OPTION<bool> draw_points;
    OPTION<INTERPOLATED_COLOR_MAP<float>> color_map;
    OPTION<bool> draw_contours;
    OPTION<int> num_contours;
    OPTION<bool> cell_centered;
    void Read_Entry(std::istream& in);
    void Write(std::ostream& out,const std::string& obj_name) const;
    void Merge(const SCALAR_FIELD_OPTIONS& o);
};

template<int d> struct MESH_OPTIONS;
template<> struct MESH_OPTIONS<1>
{
    static MESH_OPTIONS def;
    static const char* st_type_prefix;
    typedef VECTOR<float,3> COLOR;
    OPTION<bool> draw;
    OPTION<std::string> name;
    OPTION<COLOR> vertex_color;
    OPTION<bool> draw_vertices;
    OPTION<COLOR> color;
    OPTION<COLOR> velocity_color;
    OPTION<bool> draw_velocities;
    void Read_Entry(std::istream& in);
    void Write(std::ostream& out,const std::string& obj_name) const;
    void Merge(const MESH_OPTIONS& o);
};

template<> struct MESH_OPTIONS<2>
{
    static MESH_OPTIONS def;
    static const char* st_type_prefix;
    typedef VECTOR<float,3> COLOR;
    OPTION<bool> draw;
    OPTION<std::string> name;
    OPTION<COLOR> vertex_color;
    OPTION<bool> draw_vertices;
    OPTION<COLOR> edge_color;
    OPTION<bool> draw_edges;
    OPTION<COLOR> color;
    OPTION<COLOR> bgcolor;
    OPTION<bool> two_sided;
    OPTION<COLOR> velocity_color;
    OPTION<bool> draw_velocities;
    void Read_Entry(std::istream& in);
    void Write(std::ostream& out,const std::string& obj_name) const;
    void Merge(const MESH_OPTIONS& o);
};

template<> struct MESH_OPTIONS<3>
{
    static MESH_OPTIONS def;
    static const char* st_type_prefix;
    typedef VECTOR<float,3> COLOR;
    OPTION<bool> draw;
    OPTION<std::string> name;
    OPTION<COLOR> vertex_color;
    OPTION<bool> draw_vertices;
    OPTION<COLOR> edge_color;
    OPTION<bool> draw_edges;
    OPTION<COLOR> color;
    OPTION<COLOR> bgcolor;
    OPTION<bool> two_sided;
    OPTION<COLOR> velocity_color;
    OPTION<bool> draw_velocities;
    void Read_Entry(std::istream& in);
    void Write(std::ostream& out,const std::string& obj_name) const;
    void Merge(const MESH_OPTIONS& o);
};

INTERPOLATED_COLOR_MAP<float> Color_Map_Const(const VECTOR<float,3>& color);
INTERPOLATED_COLOR_MAP<float> Color_Map_Ramp(const VECTOR<float,3>& c0,const VECTOR<float,3>& c1);
INTERPOLATED_COLOR_MAP<float> Color_Map_Rainbow(bool log_scale=false,bool reverse=false,bool two_sets=false);
INTERPOLATED_COLOR_MAP<float> Color_Map_Jet(bool log_scale=false,bool reverse=false);
INTERPOLATED_COLOR_MAP<float> Color_Map_Hot(bool log_scale=false,bool reverse=false);
}
#endif
