//#####################################################################
// Copyright 2020, Craig Schroeder.
// This file is part of PhysBAM whose distribution is governed by the license contained in the accompanying file PHYSBAM_COPYRIGHT.txt.
//#####################################################################
#ifndef __QT_MAIN_WINDOW__
#define __QT_MAIN_WINDOW__

#include <Core/Data_Structures/HASHTABLE.h>
#include "QT_WINDOW.h"
#include <functional>
#include <QKeyEvent>
#include <QMainWindow>
#include <QWindow>

QT_BEGIN_NAMESPACE
class QPainter;
class QOpenGLContext;
class QOpenGLPaintDevice;
class QOpenGLShaderProgram;
class QOpenGLFunctions;
class QMenu;
QT_END_NAMESPACE

namespace PhysBAM{
class QT_CAMERA;
class QT_WORLD;
class QT_RENDER_UTILS;
class QT_COMPONENT;
class PARSE_ARGS;
class QT_SLICE_MODE;
template<class TV> class GRID;

class QT_MAIN_WINDOW : public QMainWindow
{
    Q_OBJECT

    typedef VECTOR<float,3> TV;

public:
    QT_WINDOW& window;
    QT_WORLD& world;
    QT_CAMERA& camera;

    QT_MAIN_WINDOW();
    virtual ~QT_MAIN_WINDOW();
    void Bind_Key(const std::function<void()>& f,int key,
        bool shift=false,bool ctrl=false,bool alt=false);
    const ARRAY<std::function<void()> >& Get_Key(int key,
        bool shift=false,bool ctrl=false,bool alt=false) const;
    void Create_Menus();
    void Update_Objects_Menu();
    void Options_Dialog(QT_COMPONENT* comp);
    void Render();
    void Set_2D_Mode(bool is_2d);
    void Stop_Play();
    void Set_Simulation_Directory(const std::string& dir);

public slots:
    void Quit();
    bool Prev_Frame();
    bool Next_Frame();
    void First_Frame();
    void Last_Frame();
    void Options_Selected();
    void Toggle_Wireframe();
    void Toggle_2D_Mode();
    void Scale_Up();
    void Scale_Down();
    void Scale_Reset();
    void Reset_View();
    void Increase_Substeps_Level();
    void Decrease_Substeps_Level();
    void Increase_Point_Size();
    void Decrease_Point_Size();
    void View_Bounding_Box();
    void Toggle_Play();
    void Toggle_Draw();
    void Update_Selected();
    void Show_All();
    void Hide_All();
    void Go_To_Frame();
    void Capture_Frames();
    void Slice_Mode(const std::string& grid_name,const GRID<TV>& grid);
    void Save_Settings();
    void Reload_Settings();
    void Clear_Settings();
    void Reset();
    void Toggle_Save_Select_Buffer();
    void Toggle_Render_Pick_Buffer();
protected:
    bool event(QEvent *event) override;
private:
    HASHTABLE<int,ARRAY<std::function<void()> > > key_bindings[2][2][2];
    ARRAY<std::function<void()> > no_bindings;

    QMenu* menu_file;
    QAction* action_save_settings;
    QAction* action_reload_settings;
    QAction* action_clear_settings;
    QAction* action_reset;
    QAction* action_quit;

    QMenu* menu_options;
    QAction* action_prev;
    QAction* action_next;
    QAction* action_first;
    QAction* action_last;
    QAction* action_wireframe;
    QAction* action_mode_2d;
    QAction* action_reset_view;
    QAction* action_inc_level;
    QAction* action_dec_level;
    QAction* action_inc_point_size;
    QAction* action_dec_point_size;
    QAction* action_view_bounding_box;
    QAction* action_toggle_loop;
    QAction* action_show_all;
    QAction* action_hide_all;
    QAction* action_goto_frame;
    QAction* action_capture_frames;
    QAction* action_save_select_buffer;
    QAction* action_render_pick_buffer;

    QMenu* menu_slice_mode;
    QT_SLICE_MODE* slice_mode=nullptr;

//    QMenu* menu_types;
    // QAction* action_triangulated_surface;
    // QAction* action_tetrahedralized_volume;
    // QAction* action_debug_particles;
    // QAction* action_deformable_body_collection;
    // QAction* action_face_scalar_field;
    // QAction* action_grid;
    // QAction* action_grid_based_vector_field;
    // QAction* action_levelset;
    // QAction* action_mac_velocity_field;
    // QAction* action_mpm_particles;
    // QAction* action_particles;
    // QAction* action_rigid_body_collection;
    // QAction* action_scalar_field;
    // QAction* action_triangulated_area;

    QMenu* menu_objects;
    ARRAY<QAction*> object_action_list;
    ARRAY<std::function<void()> > object_func_list;

    QAction* action_scale_up;
    QAction* action_scale_down;
    QAction* action_scale_reset;
    QAction* action_play;

    QMenu* menu_selection;
    QAction* action_draw;
    QAction* action_options;
    QAction* action_dump_info;

    QTimer *timer=nullptr;
    bool enable_loop=false;
};
}
#endif
