/*
 ** This file is part of the ViTE project.
 **
 ** This software is governed by the CeCILL-A license under French law
 ** and abiding by the rules of distribution of free software. You can
 ** use, modify and/or redistribute the software under the terms of the
 ** CeCILL-A license as circulated by CEA, CNRS and INRIA at the following
 ** URL: "http://www.cecill.info".
 **
 ** As a counterpart to the access to the source code and rights to copy,
 ** modify and redistribute granted by the license, users are provided
 ** only with a limited warranty and the software's author, the holder of
 ** the economic rights, and the successive licensors have only limited
 ** liability.
 **
 ** In this respect, the user's attention is drawn to the risks associated
 ** with loading, using, modifying and/or developing or reproducing the
 ** software by the user in light of its specific status of free software,
 ** that may mean that it is complicated to manipulate, and that also
 ** therefore means that it is reserved for developers and experienced
 ** professionals having in-depth computer knowledge. Users are therefore
 ** encouraged to load and test the software's suitability as regards
 ** their requirements in conditions enabling the security of their
 ** systems and/or data to be ensured and, more generally, to use and
 ** operate it in the same conditions as regards security.
 **
 ** The fact that you are presently reading this means that you have had
 ** knowledge of the CeCILL-A license and that you accept its terms.
 **
 **
 ** ViTE developers are (for version 0.* to 1.0):
 **
 **        - COULOMB Kevin
 **        - FAVERGE Mathieu
 **        - JAZEIX Johnny
 **        - LAGRASSE Olivier
 **        - MARCOUEILLE Jule
 **        - NOISETTE Pascal
 **        - REDONDY Arthur
 **        - VUCHENER Clément
 **
 */
/*!
 *\file Core.hpp
 */

#ifndef CORE_HPP
#define CORE_HPP

#include "common/common.hpp"

class Core;
class Interface_graphic;

#ifdef VITE_ENABLE_VBO
class Render_alternate;
#else
class Render_opengl;
#endif

class Trace;
class Variable;
class QApplication;
class QCoreApplication;
class QString;
class QMutex;
class Parser;
class QWaitCondition;
class QEventLoop;

#include <interface/Interface_graphic.hpp>

#include <QObject>

#ifdef USE_MPI
#include <boost/mpi/environment.hpp>
#include <boost/mpi/communicator.hpp>
#endif
//#include "render/GanttDiagram.hpp"
//#include "interface/Interface.hpp"

/*!
 *\brief This class is an terminal interface, it inherited from the Interface interface.
 */
class Core : public QObject, public Interface {
    Q_OBJECT
    public:

    /***********************************
     *
     * The command line parameter processing functions.
     *
     **********************************/

    /*!
     *\brief An error state.
     */
    static const int _STATE_UNKNOWN = -1;

    /*!
     *\brief A state which corresponds to display a help text.
     */
    static const int _STATE_DISPLAY_HELP = 0;

    /*!
     *\brief A state which corresponds to display the trace within a time.
     */
    static const int _STATE_IN_AN_INTERVAL = 1; // 2^0

    /*!
     *\brief A state which corresponds to display a the ViTE window and opening a file.
     */
    static const int _STATE_OPEN_FILE = 2; // 2^1

    /*!
     *\brief A state which corresponds to display the trace within a time.
     */
    static const int _STATE_OPEN_FILE_IN_AN_INTERVAL = 3;

    /*!
     *\brief A state which corresponds to an export of file.
     */
    static const int _STATE_EXPORT_FILE = 4; // 2^2

    /*!
     *\brief A state which corresponds to an export of file.
     */
    static const int _STATE_EXPORT_FILE_IN_INTERVAL = 5;

    /*!
     *\brief A state which corresponds to release the OpenGL render area (display the wait screen).
     */
    static const int _STATE_RELEASE_RENDER_AREA = 6;

    /*!
     *\brief A state which corresponds to change the render area translation.
     */
    static const int _STATE_RENDER_AREA_CHANGE_TRANSLATE = 7;

    /*!
     *\brief A state which corresponds to change the render area scale.
     */
    static const int _STATE_RENDER_AREA_CHANGE_SCALE = 8;

    /*!
     *\brief A state which corresponds to change the render area container/state scale.
     */
    static const int _STATE_RENDER_AREA_CHANGE_CONTAINER_SCALE = 9;

    /*!
     *\brief Informs that a trace has to be parsed and displayed in the main window.
     */
    static const int _DRAW_OPENGL = 10;

    /*!
     *\brief  Informs that a trace has to be exported in svg format.
     */
    static const int _DRAW_SVG = 11;

    /*!
     *\brief A state which corresponds to display the ViTE window.
     */
    static const int _STATE_LAUNCH_GRAPHICAL_INTERFACE = 12;

    /*!
     *\brief A state which corresponds to replace the render area scale.
     */
    static const int _STATE_RENDER_AREA_REPLACE_SCALE = 13;

    /*!
     *\brief A state which corresponds to replace the render area translate.
     */
    static const int _STATE_RENDER_AREA_REPLACE_TRANSLATE = 14;

    /*!
     *\brief A state which corresponds to replace the render area translate.
     */
    static const int _STATE_RENDER_AREA_REPLACE_TRANSLATE_Y = 15;

    /*!
     *\brief A state which corresponds to the registered render area translate.
     */
    static const int _STATE_RENDER_AREA_REGISTERED_TRANSLATE = 16;

    /*!
     *\brief A state which corresponds to change the render area scale.
     */
    static const int _STATE_RENDER_AREA_CHANGE_SCALE_Y = 17;

    /*!
     *\brief A state which corresponds to set new scroll bar length.
     */
    static const int _STATE_AJUST_SCROLL_BARS = 18;

    /*!
     *\brief A state which corresponds to a scroll modification of the render area.
     */
    static const int _STATE_REFRESH_SCROLL_BARS = 19;

    /*!
     *\brief Allow render area to change the graphical interface zoom box value.
     */
    static const int _STATE_ZOOM_BOX_VALUE = 20;

    /*!
     *\brief Display information about a selected entity.
     */
    static const int _STATE_RENDER_DISPLAY_INFORMATION = 21;

    /*!
     *\brief Update the render area.
     */
    static const int _STATE_RENDER_UPDATE = 22;

    /*!
     *\brief Show or hide the minimap of the render area.
     */
    static const int _STATE_RENDER_SHOW_MINIMAP = 23;


    /*!
     *\brief To draw a part of the drace (without all the containers)
     */
    static const int _DRAW_OPENGL_PARTIAL = 24;

    static const int _STATE_CLEAN_RENDER_AREA = 25;

    static const int _STATE_ZOOM_IN_AN_INTERVAL=26;

    static const int _STATE_SPLITTING=27;

    static const int _LOAD_DATA = 28;

    static const int _STATE_SWITCH_CONTAINERS = 29;

    static const int _STATE_UPDATE_VARVALUES = 30;

    /*!
     * \brief Launch an action according to the argument state value.
     * \param state An integer corresponding to a kind of action which must be executed.
     * \param arg Contains necessary arguments needed for the action to launch.
     *
     * This functions triggers an action of ViTE according to its argument. state can takes some values :
     * <ul><li><b>STATE_DISPLAY_HELP</b> -> this value means that the console interface must be displayed
     * in the terminal the help text, then wait until user specify another command.</li>
     * <li><b>STATE_LAUNCH_GRAPHICAL_INTERFACE</b> -> this value means that the console interface will let
     * user to use the graphical interface: in that case, ViTE displays the window and all
     * of the warning or error messages will be displayed in dialog boxes.</li>
     * </ul>
     */
    void launch_action(int state, void* arg = nullptr);

    QEventLoop *waitGUIInit;

protected:


    /***********************************
     *
     * Control attributes
     *
     **********************************/

    /*!
     * \brief Use to know if a window is displayed or not.
     *
     * This attributes control if the Qt managing event function exec() is executed,
     * or if ViTE must quit after some operations without graphical interface
     * are processed. (exportation for example)
     */
    bool _is_window_displayed;


    /*!
     * \brief Use to know if a trace is loaded.
     *
     * This attributes is used to know for an export if a trace has already been parsed.
     */
    bool _is_trace_loaded;



    /***********************************
     *
     * Window interface instance.
     *
     **********************************/

    /*!
     * \brief Contains the instance of the window class.
     */
    Interface_graphic* _main_window;

    /*!
     * \brief Contains the OpenGL render instance.
     */
    /* MOD */
#ifdef VITE_ENABLE_VBO
    Render_alternate* _render_opengl;
#else
    Render_opengl* _render_opengl;
#endif

    void* _render;
    //Render<Render_opengl>* _render_opengl;

#ifdef USE_MPI
    boost::mpi::communicator _world;
#endif

    /*!
     * \brief Contains the main Qt application instance.
     */
    QApplication*     graphic_app;

    /*!
     * \brief Contains the main Qt if no interface is loaded
     */
    QCoreApplication* console_app;
    /*!
     * \brief Contains the trace instance.
     */
    Trace* _trace;

    QMutex*         _mutex;
    Parser*         parser;
    QWaitCondition* _finished;
    QWaitCondition* _closed;

    /*!
     *\brief This attributes contains the launching current directory (_run_env[0]) and the first argument of the running command (_run_env[1]).
     */
    QString*        _run_env[2];

    /*!
     *\brief If a file must be opened, this attribute contains its path.
     */
    std::string _file_opened;

    /*!
     *\brief If a container's config file has to be opened, this attribute contains its path.
     */
    std::string _xml_config_file;

    /*!
     *\brief If a file must be exported, this attribute contains its path.
     */
    std::string _path_to_export;

    /*!
     *\brief The time where we start to watch the trace.
     */
    double _time_start;

    /*!
     *\brief The time where we stop to watch the trace.
     */
    double _time_end;

    /*!
     *\brief The interface_console state is specified by a command line arguments combinaison which influence the launch. _state is computed by get_state() and retrieved by int get_status().
     */
    int _state;

    /*!
     * \brief Return the state of ViTE according to the arguments.
     * \param argc The number of parameters given when the program was called.
     * \param argv A set of strings which contains each parameter.
     * \return An integer corresponding to a command which will be processed by ViTE.
     */
    int get_options(int& argc, char** argv);

    /*!
     * \brief Extracts the times of start and end in the string.
     * \param name The string where we extract times.
     */
    void extract_times(const char* name);

    /*!
     * \brief Displays in the terminal the help text.
     */
    void display_help();

public:

    /***********************************
     *
     * Constructor and destructor.
     *
     **********************************/

    /*!
     * \brief The default constructor of the class.
     * \param argc The number of parameters given when the program was called.
     * \param argv A set of strings which contains each parameter.
     */
    Core(int &argc, char** argv);

    /*!
     * \brief The destructor.
     */
    ~Core() override;



    /***********************************
     *
     * Running function.
     *
     **********************************/

    /*!
     * \brief This function launch trace drawing.
     * \param filename Path of the trace file.
     * \param format Format of the render output between: Core::_DRAW_OPENGL and Core::_DRAW_SVG.
     *
     * \return true if no errors occurs.
     */
    bool draw_trace(const std::string & filename, const int format);

    /*!
     * \brief This function launch Qt event loop.
     */
    int run();


    /*!
     * \brief Get the name of the current trace file.
     *
     */
    const std::string get_filename() const override;

    /*!
     * \brief Set the name of the output file for SVG export.
     * \param path Path of the output file.
     *
     */
    void set_path_to_export(const std::string& path);

    /*!
     * \brief Get the _run_env matrix.
     *
     */
    const QString** get_runenv() const;


    /***********************************
     *
     * Informative message functions.
     *
     **********************************/

    /*!
     * \brief The function takes a string then displayed it into the terminal, then killed the application.
     * \param string The string to be displayed.
     */
    void error(const std::string &string) const override;


    /*!
     \brief The function takes a string then displayed it into the terminal, then the program go on with an indeterminated behaviour.
     \param string The string to be displayed.
     */
    void warning(const std::string &string) const override;


    /*!
     * \brief The function takes a strings then displayed it into the terminal, then the program go on.
     * \param string The string to be displayed.
     */
    void information(const std::string &string) const override;

    /*!
     * \brief Only use in graphic interface.
     */
    void selection_information(const std::string &) const override{
    }


    /*!
     *\brief Set the minimum for export
     *\param d The double.
     */
    void set_min_value_for_export(const double d);

    /*!
     *\brief Set the minimum for export
     *\param d The double.
     */
    void set_max_value_for_export(const double d);

    /*!
     * \fn get_trace() const
     *\brief Accessor to the trace
     */
    Trace *get_trace() const;

    /*!
     *\brief Export a counter
     * Need to choose a counter, and a filename
     */
    void export_variable(Variable *var, const std::string &filename);

    /*!
     * \brief Change the color corresponding to an EntityValue
     */
    void change_entity_color(std::string entity, Element_col r, Element_col g, Element_col b);

    void change_event_color(std::string event, Element_col r, Element_col g, Element_col b);

    void change_link_color(std::string link, Element_col r, Element_col g, Element_col b);

    void change_entity_visible(std::string entity, bool visible);

    void change_event_visible(std::string event, bool visible);

    void change_link_visible(std::string link, bool visible);

    /*!
     * \brief reload state color from trace file
     */
    void reload_states();

    void reload_links();

    void reload_events();

    //Qt signals fo the Parsing Thread
signals:

    /*!
     *\brief run_parsing()
     * signal to launch the parsing
     */
    void run_parsing();

    /*!
     *\brief build_finished()
     * signal to wait for the end of event loop
     */
    void build_finished(bool finish_trace_after_parse);

    /*!
     *\brief dump())
     * signal to dump last IntervalOfContainers and wait for the end of event loop
     */
    void dump(std::string, std::string);

    /*!
     *\brief close_windows())
     * signal to close windows when parsing is cancelled by an external event
     */
    void close_windows();

    void quit_app();
};


#endif
