#include "TransitionManager.hpp"
#include <QPainter>
#include "InfoVisUI.h"
#include "BarChart.hpp"
#include "GroupedBarChart.hpp"
#include "StackedBarChart.hpp"
#include "PieChart.hpp"
#include "CompoundSequentialTransition.hpp"
#include "SortingTransition.hpp"
#include "ValueChangeTransition.hpp"
#include "FilteringTransition.hpp"
#include "ChangeChartTypeTransition.hpp"

TransitionManager* TransitionManager::pInstance = NULL;

TransitionManager::TransitionManager() {
  pGLWidget = NULL;
  pActiveChart = NULL;
  uActiveDataSetIndex = 0;
  pActiveDataSet = NULL;
}

TransitionManager::~TransitionManager() {
  //
}

TransitionManager* TransitionManager::GetInstance() {
  if (pInstance == NULL) {
    pInstance = new TransitionManager();
  }

  return pInstance;
}

void TransitionManager::Destroy() {
  if (pInstance != NULL) {
    if (pInstance->pActiveChart != NULL) {
      delete pInstance->pActiveChart;
    }

    while (pInstance->vActiveTransitions.size() > 0) {
      std::vector<CompoundTransition*>::iterator it = pInstance->vActiveTransitions.begin();

      if (it != pInstance->vActiveTransitions.end()) {
        delete *it;
        pInstance->vActiveTransitions.erase(it);
      }
    }

    while (pInstance->vDataSets.size() > 0) {
      std::vector<DataSet*>::iterator it = pInstance->vDataSets.begin();

      if (it != pInstance->vDataSets.end()) {
        delete *it;
        pInstance->vDataSets.erase(it);
      }
    }

    delete pInstance;
    pInstance = NULL;
  }
}

void TransitionManager::InitializeChart() {
  pActiveChart = CreateChart(BAR_CHART);
}

Chart* TransitionManager::CreateChart(int iChartType) {
  Chart* pChart = NULL;

  switch (iChartType) {
    case BAR_CHART: {
      pChart = new BarChart(pActiveDataSet);

      break;
    }
    case GROUPED_BAR_CHART: {
      pChart = new GroupedBarChart(pActiveDataSet);

      break;
    }
    case STACKED_BAR_CHART: {
      pChart = new StackedBarChart(pActiveDataSet);

      break;
    }
    case PIE_CHART: {
      pChart = new PieChart(pActiveDataSet);

      break;
    }
    default: {
      return NULL;
    }
  }

  return pChart;
}

void TransitionManager::SetGLWidget(MyGLWidget* pGLWidget) {
  this->pGLWidget = pGLWidget;
}

void TransitionManager::Update() {
  if (vActiveTransitions.size() > 0) {
    vActiveTransitions.at(0)->Update();
    pActiveChart = vActiveTransitions.at(0)->GetActiveChart();

    if (vActiveTransitions.at(0)->Complete()) {
      delete pActiveChart;
      pActiveChart = vActiveTransitions.at(0)->GetResultChart();
      
      delete vActiveTransitions.at(0);
      vActiveTransitions.erase(vActiveTransitions.begin());
    }
  }
}

void TransitionManager::Draw(QPainter* pPainter) {
  if (pActiveChart != NULL) {
    if (vActiveTransitions.size() > 0) {
      (*vActiveTransitions.begin())->Draw(pPainter);
    }
    else {
      pActiveChart->Draw(pPainter);
      pActiveChart->DrawLabels(pPainter);
    }
  }
}

void TransitionManager::AddDataSet(DataSet* pDataSet) {
  vDataSets.push_back(pDataSet);

  if (pActiveDataSet == NULL) {
    pActiveDataSet = pDataSet;
    uActiveDataSetIndex = 0;
  }
}

void TransitionManager::NextDataSet() {
  if ((vActiveTransitions.size() == 0) && (uActiveDataSetIndex < vDataSets.size() - 1)) {
    pActiveDataSet = vDataSets.at(uActiveDataSetIndex + 1);
    uActiveDataSetIndex += 1;

    if (vDataSets.size() > 0) {
      CompoundSequentialTransition* pSequentialTransition = new CompoundSequentialTransition(pActiveChart);
      pSequentialTransition->AddTransition(new ValueChangeTransition(pActiveChart, pActiveDataSet));

      vActiveTransitions.push_back(pSequentialTransition);
    }
  }
}

void TransitionManager::PreviousDataSet() {
  if ((vActiveTransitions.size() == 0) && (uActiveDataSetIndex > 0)) {
    pActiveDataSet = vDataSets.at(uActiveDataSetIndex - 1);
    uActiveDataSetIndex -= 1;

    if (vDataSets.size() > 0) {
      CompoundSequentialTransition* pSequentialTransition = new CompoundSequentialTransition(pActiveChart);
      pSequentialTransition->AddTransition(new ValueChangeTransition(pActiveChart, pActiveDataSet));

      vActiveTransitions.push_back(pSequentialTransition);
    }
  }
}

void TransitionManager::SetSortingOrder(bool bDescending) {
  if (vActiveTransitions.size() == 0) {
    for (unsigned int i = 0; i < vDataSets.size(); i++) {
      vDataSets.at(i)->SetSortingOrder(bDescending);
    }

    if (vDataSets.size() > 0) {
      CompoundSequentialTransition* pSequentialTransition = new CompoundSequentialTransition(pActiveChart);
      pSequentialTransition->AddTransition(new SortingTransition(pActiveChart));

      vActiveTransitions.push_back(pSequentialTransition);
    }
  }
}

void TransitionManager::SetChart(int iChartIndex) {
  if (vActiveTransitions.size() == 0) {
    CompoundSequentialTransition* pSequentialTransition = new CompoundSequentialTransition(pActiveChart);
    pSequentialTransition->AddTransition(new ChangeChartTypeTransition(pActiveChart, iChartIndex));

    vActiveTransitions.push_back(pSequentialTransition);
  }
}

void TransitionManager::SetFilter(bool bShowAll) {
  if (vActiveTransitions.size() == 0) {
    for (unsigned int i = 0; i < vDataSets.size(); i++) {
      vDataSets.at(i)->SetFiltering(bShowAll);
    }

    if (vDataSets.size() > 0) {
      CompoundSequentialTransition* pSequentialTransition = new CompoundSequentialTransition(pActiveChart);
      pSequentialTransition->AddTransition(new FilteringTransition(pActiveChart));

      vActiveTransitions.push_back(pSequentialTransition);
    }
  }
}