  //#####################################################################
// 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.
//#####################################################################
#include <Core/Grids/GRID.h>
#include <Core/Math_Tools/RANGE_ITERATOR.h>
#include <Core/Read_Write/FILE_UTILITIES.h>
#include <Core/Utilities/VIEWER_DIR.h>
#include "../QT_RENDER_UTILS.h"
#include "../QT_WORLD.h"
#include "QT_COMPONENT_OPTIONS.h"
#include "QT_GRID.h"
#include "QT_OBJECT.h"
#include "QT_VECTOR_FIELD.h"
#include <QAction>
namespace PhysBAM{
#define SET(name,value) (opt.name.Set(value),raw_opt[0].name=opt.name)
#define GET(name) opt.name.Value()
//#####################################################################
// Constructor
//#####################################################################
template<class TV> QT_VECTOR_FIELD<TV>::
QT_VECTOR_FIELD(QT_WORLD& world,const std::string& name,const std::string& grid_file,
    const std::shared_ptr<QT_OBJECT<TYPE>>& obj)
    :QT_GRID_COMPONENT<TV::m>(world,name,grid_file),
    opt(OPT::def),raw_opt{{},{},{},OPT::def},obj(obj)
{
}
//#####################################################################
// Constructor
//#####################################################################
template<class TV> QT_VECTOR_FIELD<TV>::
QT_VECTOR_FIELD(QT_WORLD& world,const std::string& name,const std::string& file,const std::string& grid_file)
    :QT_VECTOR_FIELD(world,name,grid_file,QT_FILE_OBJECT<TYPE>::Make(world.viewer_dir,file))
{
}
//#####################################################################
// Destructor
//#####################################################################
template<class TV> QT_VECTOR_FIELD<TV>::
~QT_VECTOR_FIELD()
{
}
//#####################################################################
// Function Render
//#####################################################################
template<class TV> void QT_VECTOR_FIELD<TV>::
Render(QT_RENDER_UTILS& ru)
{
    if(!GET(draw)) return;
    Read();
    if(!obj->valid || ru.select) return;
    auto& a=obj->Obj();
    
    ARRAY<TV> pts;
    for(RANGE_ITERATOR<TV::m> it(a.domain);it.Valid();it.Next())
        pts.Append(TV(GET(cell_centered)?grid.Cell_X(it.index):grid.Node_X(it.index)));
    ru.Render_Arrows<TV>(pts,a.array,GET(color));
    if(selected_index>=0 && selected_index<a.array.m)
        LOG::fprintf(ru.info_text,"%P: %P\n",this->name,a.array(selected_index));
}
//#####################################################################
// Function Read
//#####################################################################
template<class TV> void QT_VECTOR_FIELD<TV>::
Read()
{
    this->ptr->Read();
    obj->Read();
}
//#####################################################################
// Function Invalidate
//#####################################################################
template<class TV> void QT_VECTOR_FIELD<TV>::
Invalidate(bool invalidate_common)
{
    obj->Invalidate(invalidate_common);
}
//#####################################################################
// Bounding_Box
//#####################################################################
template<class TV> auto QT_VECTOR_FIELD<TV>::
Bounding_Box() -> RANGE<FV>
{
    if(!GET(draw)) return RANGE<FV>::Empty_Box();
    Read();
    if(!obj->valid) return RANGE<FV>::Empty_Box();
    return this->Bounding_Box_Helper(obj->Obj().domain);
}
//#####################################################################
// Function Print_Cell_Selection_Info
//#####################################################################
template<class TV> void QT_VECTOR_FIELD<TV>::
Print_Selection_Info(std::ostream& o,const IV& index,bool cell) const
{
    if(cell!=GET(cell_centered) || !obj->valid) return;
    auto& a=obj->Obj();
    if(!a.Valid_Index(index)) return;
    LOG::fprintf(o,"%P: %P\n",this->name,a(index));
}
//#####################################################################
// Function Make_Dialog
//#####################################################################
template<class TV> void QT_VECTOR_FIELD<TV>::
Make_Dialog(QT_WINDOW& window)
{
    QT_COMPONENT_OPTIONS* dialog=new QT_COMPONENT_OPTIONS(window,*this);
    dialog->setWindowTitle(QString::fromStdString(name));
    OPT opt2,raw_opt2;
    opt2=opt;
    raw_opt2=raw_opt[0];
    dialog->Add("Show object in viewer",opt.draw,raw_opt[0].draw);
    dialog->Add("Name to display in viewer",opt.name,raw_opt[0].name);
    dialog->Add("color",opt.color,raw_opt[0].color);
    dialog->Add("data is stored at cells",opt.cell_centered,raw_opt[0].cell_centered);
    dialog->Add("Show node selection guides",opt.node_selectors,raw_opt[0].node_selectors);
    dialog->Add("Show face selection guides",opt.face_selectors,raw_opt[0].face_selectors);
    dialog->Add("Show cell selection guides",opt.cell_selectors,raw_opt[0].cell_selectors);
    dialog->Add_End_Buttons();
    int result=dialog->exec();
    if(result!=QDialog::Accepted)
    {
        opt=opt2;
        raw_opt[0]=raw_opt2;
    }
    window.update();
}
//#####################################################################
// Function Read_Option
//#####################################################################
template<class TV> void QT_VECTOR_FIELD<TV>::
Read_Option(std::istream& in,int level)
{
    auto& o=raw_opt[level];
    o.Read_Entry(in);
    opt=raw_opt[3];
    opt.Merge(raw_opt[2]);
    opt.Merge(raw_opt[1]);
    opt.Merge(raw_opt[0]);
}
//#####################################################################
// Function Set_Draw
//#####################################################################
template<class TV> void QT_VECTOR_FIELD<TV>::
Set_Draw(bool draw)
{
    SET(draw,draw);
    action->setChecked(Draw());
}
//#####################################################################
// Function Draw
//#####################################################################
template<class TV> bool QT_VECTOR_FIELD<TV>::
Draw() const
{
    return GET(draw);
}
//#####################################################################
// Function Save_Settings
//#####################################################################
template<class TV> void QT_VECTOR_FIELD<TV>::
Save_Settings(std::ostream& out)
{
    raw_opt[0].Write(out,name);
}
//#####################################################################
// Function Clear_Settings
//#####################################################################
template<class TV> void QT_VECTOR_FIELD<TV>::
Clear_Settings()
{
    raw_opt[0]={};
    opt=raw_opt[3];
    opt.Merge(raw_opt[2]);
    opt.Merge(raw_opt[1]);
    opt.Merge(raw_opt[0]);
}
//#####################################################################
template class QT_VECTOR_FIELD<VECTOR<float,2>>;
template class QT_VECTOR_FIELD<VECTOR<float,3>>;
template class QT_VECTOR_FIELD<VECTOR<double,2>>;
template class QT_VECTOR_FIELD<VECTOR<double,3>>;
}
