#pragma once

#include <windows.h>
#include <stdlib.h>
#include <string>
#include <vector>
#include <glm.hpp>
#include "Constants.hpp"
#include "AlterableObjectTypes.hpp"
#include "CompoundTransition.hpp"
#include "Chart.hpp"
#include "DataSet.hpp"

class MyGLWidget;
class QPainter;

/*
   Class: TransitionManager

     Implements the core class of the program which handles chart and transition objects in a centralized way.
*/
class TransitionManager {
  public:
    /*
       Function: GetInstance

         *Static* function to get the singleton instance. If a instance is not yet created, it will be created.

       Returns:

         The singleton instance.
    */
    static TransitionManager* GetInstance();

    /*
       Function: Destroy

         Destroys the singleton instance.
    */
    static void Destroy();


    /*
       Constructor: TransitionManager

         Initializes the object.
    */
    TransitionManager();

    /*
       Destructor: ~TransitionManager

         Releases all allocated resources.
    */
    ~TransitionManager();


    /*
       Function: SetGLWidget

         Sets the given MyGLWidget.

       Parameters:

         pGLWidget - MyGLWidget instance to be set.
    */
    void SetGLWidget(MyGLWidget* pGLWidget);

    /*
       Function: Update

         Updates the active transition.
         
    */
    void Update();

    /*
       Function: Draw

         Draws the active transition (active chart with ongoing alterations) if present, else the active chart.

       Parameters:

         pPainter - The QPainter object to be used for drawing.
    */
    void Draw(QPainter* pPainter);

    /*
       Function: CreateChart

         Creates and returns a chart of the given chart type for the active data set.

       Parameters:

         iChartType - <BAR_CHART>, <GROUPED_BAR_CHART>, <STACKED_BAR_CHART> or <PIE_CHART>.

       Returns:

         The created chart of the desired chart type.
    */
    Chart* CreateChart(int iChartType);

    /*
       Function: InitializeChart

         Creates an initial chart on startup.
    */
    void InitializeChart();


    /*
       Function: AddDataSet

         Adds the data set to the list of data sets.

       Parameters:

         pDataSet - Pointer to the data set to be added.
    */
    void AddDataSet(DataSet* pDataSet);

    /*
       Function: NextDataSet

         Changes the active data set to the successor if present, else no change is applied.
    */
    void NextDataSet();

    /*
       Function: PreviousDataSet

         Changes the active data set to the predecessor if present, else no change is applied.
    */
    void PreviousDataSet();

    /*
       Function: SetSortingOrder

         Changes the sorting order in all data sets according to the given parameter.

       Parameters:

         bDescending - Indicates if the sorting order is changed to descending (true) or ascending (false).
    */
    void SetSortingOrder(bool bDescending);

    /*
       Function: SetChart

         Changes the chart type according to the parameter.

       Parameters:

         iChartIndex - <BAR_CHART>, <GROUPED_BAR_CHART>, <STACKED_BAR_CHART> or <PIE_CHART>.
    */
    void SetChart(int iChartIndex);

    /*
       Function: SetFilter

         Sets the filtering behavior for all data sets accoring to the parameter.

       Parameters:

         bShowAll - Indicates if all data entries are shown (true) or if the filtering is applied (false).
    */
    void SetFilter(bool bShowAll);

  private:
    static TransitionManager* pInstance;

    MyGLWidget* pGLWidget;
    Chart* pActiveChart;
    std::vector<CompoundTransition*> vActiveTransitions;
    std::vector<DataSet*> vDataSets;
    unsigned int uActiveDataSetIndex;
    DataSet* pActiveDataSet;
};