#include "BarChart.hpp"
#include "Bar.hpp"

BarChart::BarChart(DataSet* pDataSet) {
  iType = BAR_CHART;
  this->pDataSet = pDataSet;

  //get the filtered and sorted data entries
  vVisibleDataEntries = pDataSet->GetAllDataEntries();
 
  QString sText = QObject::tr(pDataSet->GetName().c_str());

  //headline
  vLabels.push_back(new Label(sText, FONTSTYLE_HEADLINE, WIDTH / 2, 30, ORIENTATION_HORIZONTAL, Qt::AlignCenter));

  //x-axis
  vAxes.push_back(new Axis(ORIENTATION_HORIZONTAL));

  //y-axis
  vAxes.push_back(new Axis(ORIENTATION_VERTICAL, QObject::tr(pDataSet->GetUnit().c_str())));

  //grid
  double dHighestValue = GetHighestVisibleValue();
  double dHighestGridValue = 0.0;
  int iStepSize = 0;

  if (dHighestValue <= GRID_LOW_VALUE) {
    iStepSize = GRID_LOW_VALUE_STEP_SIZE;
    dHighestGridValue = GRID_LOW_VALUE;
  }
  else if (dHighestValue <= GRID_MID_VALUE) {
    iStepSize = GRID_MID_VALUE_STEP_SIZE;
    dHighestGridValue = GRID_MID_VALUE;
  }
  else if (dHighestValue <= GRID_SECOND_HIGH_VALUE) {
    iStepSize = GRID_SECOND_HIGH_VALUE_STEP_SIZE;
    dHighestGridValue = GRID_SECOND_HIGH_VALUE;
  }
  else {
    iStepSize = GRID_HIGH_VALUE_STEP_SIZE;
    dHighestGridValue = GRID_HIGH_VALUE;
  }

  for (int i = 1; i < GRID_LINES + 1; i++) {
    vGridLines.push_back(new GridLine(i * iStepSize, i));
  }

  //data elements
  float fWidth = 2.0f * (UPPER_X - ORIGIN_X - 2.0f * BIG_SPACE) / (3.0f * vVisibleDataEntries.size() - 1.0f);

  for (unsigned int i = 0; i < vVisibleDataEntries.size(); i++) {
    float fSpace = fWidth / 2.0f;
    float fTop = vVisibleDataEntries.at(i)->GetValue() / dHighestGridValue * (UPPER_Y - ORIGIN_Y) + ORIGIN_Y;
    float fLeft;

    if (i == 0) {
      fLeft = BIG_SPACE + ORIGIN_X;
    }
    else {
      fLeft = BIG_SPACE + i * (fWidth + fSpace) + ORIGIN_X;
    }

    vDataElements.push_back(new Bar(vVisibleDataEntries.at(i), fLeft, fTop, ORIGIN_Y, fWidth));
  }
}

BarChart::~BarChart() {
  while (vLabels.size() > 0) {
    std::vector<Label*>::iterator it = vLabels.begin();

    if (it != vLabels.end()) {
      delete *it;
      vLabels.erase(it);
    }
  }

  while (vAxes.size() > 0) {
    std::vector<Axis*>::iterator it = vAxes.begin();

    if (it != vAxes.end()) {
      delete *it;
      vAxes.erase(it);
    }
  }

  while (vGridLines.size() > 0) {
    std::vector<GridLine*>::iterator it = vGridLines.begin();

    if (it != vGridLines.end()) {
      delete *it;
      vGridLines.erase(it);
    }
  }

  while (vDataElements.size() > 0) {
    std::vector<DataElement*>::iterator it = vDataElements.begin();

    if (it != vDataElements.end()) {
      delete *it;
      vDataElements.erase(it);
    }
  }
}

void BarChart::Draw(QPainter* pPainter) {
  for (std::vector<GridLine*>::iterator it = vGridLines.begin(); it != vGridLines.end(); it++) {
    (*it)->Draw(pPainter);
  }

  if (pDataSet->GetSortingOrder()) {
    for (int i = (int) vDataElements.size() - 1; i >= 0; i--) {
      vDataElements.at(i)->Draw(pPainter);
    }
  }
  else {
    for (unsigned int i = 0; i < vDataElements.size(); i++) {
      vDataElements.at(i)->Draw(pPainter);
    }
  }

  for (std::vector<Axis*>::iterator it = vAxes.begin(); it != vAxes.end(); it++) {
    (*it)->Draw(pPainter);
  }
}

void BarChart::DrawLabels(QPainter* pPainter) {
  for (std::vector<GridLine*>::iterator it = vGridLines.begin(); it != vGridLines.end(); it++) {
    (*it)->DrawLabels(pPainter);
  }
  
  for (std::vector<Label*>::iterator it = vLabels.begin(); it != vLabels.end(); it++) {
    (*it)->Draw(pPainter);
  }

  for (std::vector<DataElement*>::iterator it = vDataElements.begin(); it != vDataElements.end(); it++) {
    (*it)->DrawLabels(pPainter);
  }

  for (std::vector<Axis*>::iterator it = vAxes.begin(); it != vAxes.end(); it++) {
    (*it)->DrawLabels(pPainter);
  }
}

void BarChart::ChangePosition(float fDeltaLeft, float fDeltaTop, float fDeltaBottom) {
  UNREFERENCED(fDeltaLeft);
  UNREFERENCED(fDeltaTop);
  UNREFERENCED(fDeltaBottom);
}

void BarChart::ChangeAlpha(float fDeltaAlpha) {
  UNREFERENCED(fDeltaAlpha);
}