#pragma once

#include "Chart.hpp"

/*
   Class: StackedBarChart

     Implements a stacked bar chart.
     A stacked bar chart contains a set of stacked bar data elements, grid lines, two axes and a headline label.

     *Inherits* from <Chart>.
*/
class StackedBarChart: public Chart {
  public:
    /*
       Constructor: StackedBarChart

         Initializes the object.

       Parameters:

         pDataSet - Pointer to the data set object that shall be represented by the chart.
    */
    StackedBarChart(DataSet* pDataSet);

    /*
       Destructor: ~StackedBarChart

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


    /*
       Function: Draw

         Draws the chart. *Inherited* from <AlterableObject>.

       Parameters:

         pPainter - The QPainter object that shall be used for painting.
    */
    void Draw(QPainter* pPainter);

    /*
       Function: DrawLabels

         Draws the label assigned to the chart. *Inherited* from <AlterableObject>.

       Parameters:

         pPainter - The QPainter object that shall be used for painting.
    */
    void DrawLabels(QPainter* pPainter);

    /*
       Function: ChangePosition

         Unused function. *Inherited* from <AlterableObject>.

       Parameters:

         fDeltaLeft - Unused parameter.
         fDeltaTop - Unused parameter.
         fDeltaBottom - Unused parameter.
    */
    void ChangePosition(float fDeltaLeft, float fDeltaTop, float fDeltaBottom);

    /*
       Function: ChangeAlpha

         Unused function. *Inherited* from <AlterableObject>.

       Parameters:

         fDeltaAlpha - Unused parameter.
    */
    void ChangeAlpha(float fDeltaAlpha);

    /*
       Function: GetConnectedDataElementByDataGroup

         Returns the stacked bar which represents the given data group. If no such stacked bar exists, NULL is returned.

       Parameters:

         pDataGroup - Pointer to the data group to be searched.

       Returns:

         The stacked bar which represents the given data group if present, else NULL.
    */
    DataElement* GetConnectedDataElementByDataGroup(DataGroup* pDataGroup);

    /*
       Function: GetConnectedBar

         Returns the bar data element which represents the given data entry. If no such bar exists among all stacked bars, NULL is returned.

       Parameters:

         pDataEntry - Pointer to the data entry to be searched.

       Returns:

         The bar data element which represents the given data entry if present, else NULL.
    */
    DataElement* GetConnectedBar(DataEntry* pDataEntry);

    /*
       Function: GetAllBars

         Returns a vector containing all visible (not filtered) bars of all stacked bars of the chart.

       Returns:

         A vector containing all visible bars of all stacked bars of the chart.
    */
    std::vector<DataElement*> GetAllBars();

    /*
       Function: GetHighestVisibleSum

         Returns the highest sum of values of a stacked bar among all visible (not filtered) stacked bars.

       Returns:

         The highest sum of values of a stacked bar among all visible stacked bars.
    */
    double GetHighestVisibleSum();

    /*
       Function: GetIndexOfBar

         Returns the index of a given bar in its stacked bar, counting from the bottom up.

       Parameters:

         pDataElement - The bar whose index is to be returned.

       Returns:

         The index of a given bar in its stacked bar.
    */
    unsigned int GetIndexOfBar(DataElement* pDataElement);

  private:
    /*
       Function: GetVisibleDataGroups

         Returns a vector containing all visible data groups of the given data groups, i.e. all data groups with at least one unfiltered data entry.

       Parameters:

         vAllDataGroups - A vector containing all data groups of a data set.

       Returns:

         A vector containing all visible data groups of the given data groups.
    */
    std::vector<DataGroup*> GetVisibleDataGroups(std::vector<DataGroup*> vAllDataGroups);

    /*
       Function: ContainsDataEntry

         Lookup function which checks the existence of a given data entry pointer in a given vector.

       Parameters:

         vDataEntries - A vector of data entry pointers.
         pDataEntry - A data entry pointer to be searched.

       Returns:

         A boolean value indicating if the vector contains the data entry.
    */
    bool ContainsDataEntry(std::vector<DataEntry*> vDataEntries, DataEntry* pDataEntry);

    std::vector<DataGroup*> vVisibleDataGroups;
};