 //#####################################################################
// Copyright 2004, Eran Guendelman.
// This file is part of PhysBAM whose distribution is governed by the license contained in the accompanying file PHYSBAM_COPYRIGHT.txt.
//#####################################################################
// Class QT_FACE_FIELD
//##################################################################### 
#ifndef __QT_FACE_FIELD__
#define __QT_FACE_FIELD__
#include <Core/Grids/FACE_INDEX.h>
#include <Core/Interpolation/INTERPOLATED_COLOR_MAP.h>
#include "QT_GRID_COMPONENT.h"
#include <memory>
#include <string>

namespace PhysBAM{

template<class OBJ> class QT_OBJECT;
template<class T2> struct FACE_FIELD_OPTIONS;

template<class T,int d>
class QT_FACE_FIELD:public QT_GRID_COMPONENT<d>
{
public:
    typedef float S;typedef VECTOR<int,d> IV;
    typedef VECTOR<S,d> SV;typedef VECTOR<T,d> TV;
    typedef ARRAY<T,FACE_INDEX<d> > TYPE;

    typedef std::conditional_t<std::is_same<T,double>::value,float,T> TF;
    typedef FACE_FIELD_OPTIONS<TF> OPT;
    static constexpr bool is_f=!std::is_same<T,int>::value && !std::is_same<T,bool>::value;
private:
    OPT opt,raw_opt[4];
    std::shared_ptr<QT_OBJECT<TYPE>> obj;

    static const QT_COMPONENT_OPTION options[];
    static const int num_options;
    typedef QT_FACE_FIELD SELF;
    typedef QT_GRID_COMPONENT<d> BASE;
public:
    using typename BASE::COLOR;using typename BASE::FV;using BASE::grid;
    using BASE::name;using BASE::action;
    typedef FV T_VECTOR;
    typedef ARRAY<T,FACE_INDEX<d> > OBJ_TYPE;

    QT_FACE_FIELD(QT_WORLD& world,const std::string& name,const std::string& file,const std::string& grid_file);
    QT_FACE_FIELD(QT_WORLD& world,const std::string& name,const std::string& grid_file,const std::shared_ptr<QT_OBJECT<TYPE>>& obj);

    virtual ~QT_FACE_FIELD();

    void Render(QT_RENDER_UTILS& ru) override;
    void Read() override;
    void Invalidate(bool invalidate_common) override;
    RANGE<FV> Bounding_Box() override;

    void Print_Selection_Info(std::ostream& o,const IV& index,bool cell) const override;
    void Make_Dialog(QT_WINDOW& window) override;
    void Read_Option(std::istream& in,int level) override;
    void Set_Draw(bool draw) override;
    bool Draw() const override;
    void Save_Settings(std::ostream& out) override;
    void Clear_Settings() override;

    void Set_Range_From_Data();

    void Toggle_Velocity_Mode();
    void Toggle_Velocity_Mode_And_Draw();
    void Increase_Vector_Size();
    void Decrease_Vector_Size();
    void Set_Vector_Size(T scale);
    void Toggle_Arrowhead();
    void Toggle_Draw_Divergence();
    void Toggle_Draw_Streamlines();
    void Toggle_Use_Streamline_Seed();
    void Set_Streamline_Seed(const unsigned int seed=0);
    void Lengthen_Streamlines();
    void Shorten_Streamlines();
    void Toggle_Draw_Vorticity();
    void Normalize_Vorticity_Color_Map();
    const auto& Get_Object() const {return obj;}

private:
    COLOR Get_Color(T value) const;
    void Update_Divergence();
    void Update_Streamlines();
    void Update_Vorticity();
//#####################################################################
};
}
#endif
