//#####################################################################
// 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_WORLD__
#define __QT_WORLD__

#include <Core/Data_Structures/HASHTABLE.h>
#include <Core/Log/LOG.h>
#include <Core/Math_Tools/RANGE.h>
#include <Core/Matrices/MATRIX.h>
#include <Core/Vectors/VECTOR.h>
#include <Core/Viewer/VIEWER_OPTIONS.h>
#include <map>
#include <memory>

namespace PhysBAM{

class QT_COMPONENT;
class QT_RENDER_UTILS;
class QT_MAIN_WINDOW;
class QT_WINDOW;
struct VIEWER_DIR;
class PARSE_ARGS;
template<class TV> class RAY;

class QT_WORLD
{
    friend class QT_MAIN_WINDOW;
    friend class QT_WINDOW;
    typedef float T;
    typedef VECTOR<T,3> TV;

    std::string frame_string;
    HASHTABLE<std::string,void(*)(QT_WORLD& world,const std::string& name,bool common,std::stringstream& ss)> component_factory;
    QT_MAIN_WINDOW& main_window;
    typedef GLOBAL_OPTIONS OPT;

    OPT opt,raw_opt[4];
public:
    // 0 = persistent
    // 1 = temporary
    VECTOR<std::map<std::string,std::shared_ptr<QT_COMPONENT>>,2> objects;
    VIEWER_DIR& viewer_dir;

    QT_COMPONENT* selected = nullptr;

    QT_WORLD(QT_MAIN_WINDOW& main_window);
    ~QT_WORLD();

    void Initialize();
    void Reset();
    void Read();
    void Read_Manifest(bool common_only);
    void Read_Settings();
    RANGE<TV> Bounding_Box();
    void Render(QT_RENDER_UTILS& ru,bool select);

    bool Next_Frame(bool use_substeps=true);
    bool Prev_Frame();
    void First_Frame();
    void Last_Frame();
    void Set_Frame(int frame);
    void Set_Frame(const std::string& frame);

    std::shared_ptr<QT_COMPONENT> Find_Component(const std::string& name) const;
    void Remove_Component(const std::string& name);
    void Add_Object(const std::shared_ptr<QT_COMPONENT>& o,bool common);
    void Save_Settings(std::ostream& out);
    void Clear_Settings();
    void Read_Option(std::istream& in,int level);
    void Update_Settings();
};
}
#endif
