//#####################################################################
// Copyright 2004-2009, Eran Guendelman, Andrew Selle.
// This file is part of PhysBAM whose distribution is governed by the license contained in the accompanying file PHYSBAM_COPYRIGHT.txt.
//#####################################################################
// Class QT_SCALAR_FIELD
//##################################################################### 
#ifndef __QT_SCALAR_FIELD__
#define __QT_SCALAR_FIELD__

#include <Core/Interpolation/INTERPOLATED_COLOR_MAP.h>
#include <Core/Meshes/MESHES_FORWARD.h>
#include "QT_COMPONENT.h"
#include "QT_GRID_COMPONENT.h"
#include <memory>
#include <string>

namespace PhysBAM
{
template<class OBJ> class QT_OBJECT;
template<class T2> struct SCALAR_FIELD_OPTIONS;

template<class T,int d>
class QT_SCALAR_FIELD:public QT_GRID_COMPONENT<d>
{
public:
    typedef VECTOR<int,d> IV;typedef ARRAY<T,IV> TYPE;
    typedef float F;typedef VECTOR<F,d> TV;

    static constexpr bool is_f=!std::is_same<T,int>::value && !std::is_same<T,bool>::value;
    typedef std::conditional_t<is_f,F,T> TF;
    typedef SCALAR_FIELD_OPTIONS<TF> OPT;
    int selected_isocontour=-1;
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_SCALAR_FIELD SELF;
    typedef QT_GRID_COMPONENT<d> BASE;

    mutable ARRAY<std::pair<MESH_OBJECT<VECTOR<T,d>,d-1>*,T>> cached_mesh;

public:
    using typename BASE::COLOR;using typename BASE::FV;using BASE::grid;
    using BASE::name;using BASE::action;
    typedef std::conditional_t<std::is_same<T,bool>::value,COLOR,
        std::conditional_t<std::is_same<T,int>::value,ARRAY<COLOR>,
            INTERPOLATED_COLOR_MAP<F>>> COLOR_MAP;

    QT_SCALAR_FIELD(QT_WORLD& world,const std::string& name,const std::string& file,const std::string& grid_file);
    QT_SCALAR_FIELD(QT_WORLD& world,const std::string& name,const std::string& grid_file,const std::shared_ptr<QT_OBJECT<TYPE>>& obj);
    virtual ~QT_SCALAR_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 Set_Selection(ARRAY_VIEW<int> selection) override;
    void Clear_Selection() 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();
    const auto& Get_Object() const {return obj;}

private:
    std::pair<COLOR,bool> Get_Color(T value) const;
    void Render_Isocontour(QT_RENDER_UTILS& ru,int countour_index,T value) const;
    void Invalidate_Cache() const;
};

}

#endif
