#include "glew.h"
#include "MyGLWidget.hpp"
#include "Constants.hpp"
#include "DataSet.hpp"
#include "DataGroup.hpp"
#include "DataEntry.hpp"
#include "Chart.hpp"
#include "BarChart.hpp"

MyGLWidget::MyGLWidget(QWidget* pParent): QGLWidget(QGLFormat(QGL::SampleBuffers), pParent) {
  Initialize();

  pTransitionManager = TransitionManager::GetInstance();
  pTransitionManager->SetGLWidget(this);

  setAutoFillBackground(false);

  oTimer.setSingleShot(false);
  connect(&oTimer, SIGNAL(timeout()), this, SLOT(update()));
  oTimer.start(UPDATE_RATE_IN_MS);

  //insert hard-coded data
  DataSet* pNovemberDataSet = new DataSet("Video card usage - November 2010", "Percentage");
  pTransitionManager->AddDataSet(pNovemberDataSet);

  DataGroup* pNovemberNVidiaDataGroup = new DataGroup("NVidia");
  pNovemberDataSet->AddDataGroup(pNovemberNVidiaDataGroup);
  pNovemberNVidiaDataGroup->AddDataEntry(new DataEntry("GeForce 7", 1.59f / 0.7428f, 179.0f / 255.0f, 248.0f / 255.0f, 75.0f / 255.0f));
  pNovemberNVidiaDataGroup->AddDataEntry(new DataEntry("GeForce 8", 12.67f / 0.7428f, 133.0f / 255.0f, 206.0f / 255.0f, 25.0f / 255.0f));
  pNovemberNVidiaDataGroup->AddDataEntry(new DataEntry("GeForce 9", 13.87f / 0.7428f, 121.0f / 255.0f, 195.0f / 255.0f, 13.0f / 255.0f));
  pNovemberNVidiaDataGroup->AddDataEntry(new DataEntry("GeForce 100", 3.33f / 0.7428f, 156.0f / 255.0f, 227.0f / 255.0f, 50.0f / 255.0f));
  pNovemberNVidiaDataGroup->AddDataEntry(new DataEntry("GeForce 200", 10.25f / 0.7428f, 145.0f / 255.0f, 216.0f / 255.0f, 38.0f / 255.0f));
  pNovemberNVidiaDataGroup->AddDataEntry(new DataEntry("GeForce 400", 2.71f / 0.7428f, 168.0f / 255.0f, 237.0f / 255.0f, 63.0f / 255.0f));

  DataGroup* pNovemberNVidiaMobileDataGroup = new DataGroup("NVidia Mobile");
  pNovemberDataSet->AddDataGroup(pNovemberNVidiaMobileDataGroup);
  pNovemberNVidiaMobileDataGroup->AddDataEntry(new DataEntry("GeForce 8M", 2.38f / 0.7428f, 182.0f / 255.0f, 234.0f / 255.0f, 104.0f / 255.0f));
  pNovemberNVidiaMobileDataGroup->AddDataEntry(new DataEntry("GeForce 9M", 1.34f / 0.7428f, 205.0f / 255.0f, 240.0f / 255.0f, 153.0f / 255.0f));
  pNovemberNVidiaMobileDataGroup->AddDataEntry(new DataEntry("GeForce 200M", 0.0f, 209.0f / 255.0f, 252.0f / 255.0f, 143.0f / 255.0f));

  DataGroup* pNovemberATIDataGroup = new DataGroup("ATI");
  pNovemberDataSet->AddDataGroup(pNovemberATIDataGroup);
  pNovemberATIDataGroup->AddDataEntry(new DataEntry("Radeon 3000", 2.63f / 0.7428f, 245.0f / 255.0f, 66.0f / 255.0f, 74.0f / 255.0f));
  pNovemberATIDataGroup->AddDataEntry(new DataEntry("Radeon 4000", 10.71f / 0.7428f, 240.0f / 255.0f, 42.0f / 255.0f, 51.0f / 255.0f));
  pNovemberATIDataGroup->AddDataEntry(new DataEntry("Radeon 5000", 8.28f / 0.7428f, 242.0f / 255.0f, 54.0f / 255.0f, 62.0f / 255.0f));

  DataGroup* pNovemberATIMobileDataGroup = new DataGroup("ATI Mobile");
  pNovemberDataSet->AddDataGroup(pNovemberATIMobileDataGroup);
  pNovemberATIMobileDataGroup->AddDataEntry(new DataEntry("Radeon 3000M", 0.63f / 0.7428f, 241.0f / 255.0f, 134.0f / 255.0f, 140.0f / 255.0f));
  pNovemberATIMobileDataGroup->AddDataEntry(new DataEntry("Radeon 4000M", 2.05f / 0.7428f, 252.0f / 255.0f, 98.0f / 255.0f, 106.0f / 255.0f));

  DataGroup* pNovemberIntelMobileDataGroup = new DataGroup("Intel Mobile");
  pNovemberDataSet->AddDataGroup(pNovemberIntelMobileDataGroup);
  pNovemberIntelMobileDataGroup->AddDataEntry(new DataEntry("Intel 4E", 1.76f / 0.7428f, 30.0f / 255.0f, 111.0f / 255.0f, 176.0f / 255.0f));


  DataSet* pDecemberDataSet = new DataSet("Video card usage - December 2010", "Percentage");
  pTransitionManager->AddDataSet(pDecemberDataSet);

  DataGroup* pDecemberNVidiaDataGroup = new DataGroup("NVidia");
  pDecemberDataSet->AddDataGroup(pDecemberNVidiaDataGroup);
  pDecemberNVidiaDataGroup->AddDataEntry(new DataEntry("GeForce 7", 1.58f / 0.7451f, 179.0f / 255.0f, 248.0f / 255.0f, 75.0f / 255.0f));
  pDecemberNVidiaDataGroup->AddDataEntry(new DataEntry("GeForce 8", 11.21f / 0.7451f, 133.0f / 255.0f, 206.0f / 255.0f, 25.0f / 255.0f));
  pDecemberNVidiaDataGroup->AddDataEntry(new DataEntry("GeForce 9", 13.45f / 0.7451f, 121.0f / 255.0f, 195.0f / 255.0f, 13.0f / 255.0f));
  pDecemberNVidiaDataGroup->AddDataEntry(new DataEntry("GeForce 100", 3.14f / 0.7451f, 156.0f / 255.0f, 227.0f / 255.0f, 50.0f / 255.0f));
  pDecemberNVidiaDataGroup->AddDataEntry(new DataEntry("GeForce 200", 10.06f / 0.7451f, 145.0f / 255.0f, 216.0f / 255.0f, 38.0f / 255.0f));
  pDecemberNVidiaDataGroup->AddDataEntry(new DataEntry("GeForce 400", 3.12f / 0.7451f, 168.0f / 255.0f, 237.0f / 255.0f, 63.0f / 255.0f));

  DataGroup* pDecemberNVidiaMobileDataGroup = new DataGroup("NVidia Mobile");
  pDecemberDataSet->AddDataGroup(pDecemberNVidiaMobileDataGroup);
  pDecemberNVidiaMobileDataGroup->AddDataEntry(new DataEntry("GeForce 8M", 2.45f / 0.7451f, 182.0f / 255.0f, 234.0f / 255.0f, 104.0f / 255.0f));
  pDecemberNVidiaMobileDataGroup->AddDataEntry(new DataEntry("GeForce 9M", 1.36f / 0.7451f, 205.0f / 255.0f, 240.0f / 255.0f, 153.0f / 255.0f));
  pDecemberNVidiaMobileDataGroup->AddDataEntry(new DataEntry("GeForce 200M", 0.53f / 0.7451f, 209.0f / 255.0f, 252.0f / 255.0f, 143.0f / 255.0f));

  DataGroup* pDecemberATIDataGroup = new DataGroup("ATI");
  pDecemberDataSet->AddDataGroup(pDecemberATIDataGroup);
  pDecemberATIDataGroup->AddDataEntry(new DataEntry("Radeon 3000", 2.65f / 0.7451f, 245.0f / 255.0f, 66.0f / 255.0f, 74.0f / 255.0f));
  pDecemberATIDataGroup->AddDataEntry(new DataEntry("Radeon 4000", 10.8f / 0.7451f, 240.0f / 255.0f, 42.0f / 255.0f, 51.0f / 255.0f));
  pDecemberATIDataGroup->AddDataEntry(new DataEntry("Radeon 5000", 8.63f / 0.7451f, 242.0f / 255.0f, 54.0f / 255.0f, 62.0f / 255.0f));

  DataGroup* pDecemberATIMobileDataGroup = new DataGroup("ATI Mobile");
  pDecemberDataSet->AddDataGroup(pDecemberATIMobileDataGroup);
  pDecemberATIMobileDataGroup->AddDataEntry(new DataEntry("Radeon 3000M", 0.62f / 0.7451f, 241.0f / 255.0f, 134.0f / 255.0f, 140.0f / 255.0f));
  pDecemberATIMobileDataGroup->AddDataEntry(new DataEntry("Radeon 4000M", 2.1f / 0.7451f, 252.0f / 255.0f, 98.0f / 255.0f, 106.0f / 255.0f));

  DataGroup* pDecemberIntelMobileDataGroup = new DataGroup("Intel Mobile");
  pDecemberDataSet->AddDataGroup(pDecemberIntelMobileDataGroup);
  pDecemberIntelMobileDataGroup->AddDataEntry(new DataEntry("Intel 4E", 1.85f / 0.7451f, 30.0f / 255.0f, 111.0f / 255.0f, 176.0f / 255.0f));


  DataSet* pJanuaryDataSet = new DataSet("Video card usage - January 2011", "Percentage");
  pTransitionManager->AddDataSet(pJanuaryDataSet);

  DataGroup* pJanuaryNVidiaDataGroup = new DataGroup("NVidia");
  pJanuaryDataSet->AddDataGroup(pJanuaryNVidiaDataGroup);
  pJanuaryNVidiaDataGroup->AddDataEntry(new DataEntry("GeForce 7", 1.46f / 0.7492f, 179.0f / 255.0f, 248.0f / 255.0f, 75.0f / 255.0f));
  pJanuaryNVidiaDataGroup->AddDataEntry(new DataEntry("GeForce 8", 10.98f / 0.7492f, 133.0f / 255.0f, 206.0f / 255.0f, 25.0f / 255.0f));
  pJanuaryNVidiaDataGroup->AddDataEntry(new DataEntry("GeForce 9", 13.29f / 0.7492f, 121.0f / 255.0f, 195.0f / 255.0f, 13.0f / 255.0f));
  pJanuaryNVidiaDataGroup->AddDataEntry(new DataEntry("GeForce 100", 3.32f / 0.7492f, 156.0f / 255.0f, 227.0f / 255.0f, 50.0f / 255.0f));
  pJanuaryNVidiaDataGroup->AddDataEntry(new DataEntry("GeForce 200", 10.15f / 0.7492f, 145.0f / 255.0f, 216.0f / 255.0f, 38.0f / 255.0f));
  pJanuaryNVidiaDataGroup->AddDataEntry(new DataEntry("GeForce 400", 3.65f / 0.7492f, 168.0f / 255.0f, 237.0f / 255.0f, 63.0f / 255.0f));

  DataGroup* pJanuaryNVidiaMobileDataGroup = new DataGroup("NVidia Mobile");
  pJanuaryDataSet->AddDataGroup(pJanuaryNVidiaMobileDataGroup);
  pJanuaryNVidiaMobileDataGroup->AddDataEntry(new DataEntry("GeForce 8M", 2.39f / 0.7492f, 182.0f / 255.0f, 234.0f / 255.0f, 104.0f / 255.0f));
  pJanuaryNVidiaMobileDataGroup->AddDataEntry(new DataEntry("GeForce 9M", 1.33f / 0.7492f, 205.0f / 255.0f, 240.0f / 255.0f, 153.0f / 255.0f));
  pJanuaryNVidiaMobileDataGroup->AddDataEntry(new DataEntry("GeForce 200M", 0.0f, 209.0f / 255.0f, 252.0f / 255.0f, 143.0f / 255.0f));

  DataGroup* pJanuaryATIDataGroup = new DataGroup("ATI");
  pJanuaryDataSet->AddDataGroup(pJanuaryATIDataGroup);
  pJanuaryATIDataGroup->AddDataEntry(new DataEntry("Radeon 3000", 2.44f / 0.7492f, 245.0f / 255.0f, 66.0f / 255.0f, 74.0f / 255.0f));
  pJanuaryATIDataGroup->AddDataEntry(new DataEntry("Radeon 4000", 10.66f / 0.7492f, 240.0f / 255.0f, 42.0f / 255.0f, 51.0f / 255.0f));
  pJanuaryATIDataGroup->AddDataEntry(new DataEntry("Radeon 5000", 9.3f / 0.7492f, 242.0f / 255.0f, 54.0f / 255.0f, 62.0f / 255.0f));

  DataGroup* pJanuaryATIMobileDataGroup = new DataGroup("ATI Mobile");
  pJanuaryDataSet->AddDataGroup(pJanuaryATIMobileDataGroup);
  pJanuaryATIMobileDataGroup->AddDataEntry(new DataEntry("Radeon 3000M", 0.62f / 0.7492f, 241.0f / 255.0f, 134.0f / 255.0f, 140.0f / 255.0f));
  pJanuaryATIMobileDataGroup->AddDataEntry(new DataEntry("Radeon 4000M", 2.1f / 0.7492f, 252.0f / 255.0f, 98.0f / 255.0f, 106.0f / 255.0f));

  DataGroup* pJanuaryIntelMobileDataGroup = new DataGroup("Intel Mobile");
  pJanuaryDataSet->AddDataGroup(pJanuaryIntelMobileDataGroup);
  pJanuaryIntelMobileDataGroup->AddDataEntry(new DataEntry("Intel 4E", 1.85f / 0.7492f, 30.0f / 255.0f, 111.0f / 255.0f, 176.0f / 255.0f));


  DataSet* pFebruaryDataSet = new DataSet("Video card usage - February 2011", "Percentage");
  pTransitionManager->AddDataSet(pFebruaryDataSet);

  DataGroup* pFebruaryNVidiaDataGroup = new DataGroup("NVidia");
  pFebruaryDataSet->AddDataGroup(pFebruaryNVidiaDataGroup);
  pFebruaryNVidiaDataGroup->AddDataEntry(new DataEntry("GeForce 7", 1.32f / 0.7322f, 179.0f / 255.0f, 248.0f / 255.0f, 75.0f / 255.0f));
  pFebruaryNVidiaDataGroup->AddDataEntry(new DataEntry("GeForce 8", 10.39f / 0.7322f, 133.0f / 255.0f, 206.0f / 255.0f, 25.0f / 255.0f));
  pFebruaryNVidiaDataGroup->AddDataEntry(new DataEntry("GeForce 9", 12.94f / 0.7322f, 121.0f / 255.0f, 195.0f / 255.0f, 13.0f / 255.0f));
  pFebruaryNVidiaDataGroup->AddDataEntry(new DataEntry("GeForce 100", 3.29f / 0.7322f, 156.0f / 255.0f, 227.0f / 255.0f, 50.0f / 255.0f));
  pFebruaryNVidiaDataGroup->AddDataEntry(new DataEntry("GeForce 200", 10.61f / 0.7322f, 145.0f / 255.0f, 216.0f / 255.0f, 38.0f / 255.0f));
  pFebruaryNVidiaDataGroup->AddDataEntry(new DataEntry("GeForce 400", 4.2f / 0.7322f, 168.0f / 255.0f, 237.0f / 255.0f, 63.0f / 255.0f));

  DataGroup* pFebruaryNVidiaMobileDataGroup = new DataGroup("NVidia Mobile");
  pFebruaryDataSet->AddDataGroup(pFebruaryNVidiaMobileDataGroup);
  pFebruaryNVidiaMobileDataGroup->AddDataEntry(new DataEntry("GeForce 8M", 2.28f / 0.7322f, 182.0f / 255.0f, 234.0f / 255.0f, 104.0f / 255.0f));
  pFebruaryNVidiaMobileDataGroup->AddDataEntry(new DataEntry("GeForce 9M", 1.24f / 0.7322f, 205.0f / 255.0f, 240.0f / 255.0f, 153.0f / 255.0f));
  pFebruaryNVidiaMobileDataGroup->AddDataEntry(new DataEntry("GeForce 200M", 0.57f / 0.7322f, 209.0f / 255.0f, 252.0f / 255.0f, 143.0f / 255.0f));

  DataGroup* pFebruaryATIDataGroup = new DataGroup("ATI");
  pFebruaryDataSet->AddDataGroup(pFebruaryATIDataGroup);
  pFebruaryATIDataGroup->AddDataEntry(new DataEntry("Radeon 3000", 2.46f / 0.7322f, 245.0f / 255.0f, 66.0f / 255.0f, 74.0f / 255.0f));
  pFebruaryATIDataGroup->AddDataEntry(new DataEntry("Radeon 4000", 10.68f / 0.7322f, 240.0f / 255.0f, 42.0f / 255.0f, 51.0f / 255.0f));
  pFebruaryATIDataGroup->AddDataEntry(new DataEntry("Radeon 5000", 10.06f / 0.7322f, 242.0f / 255.0f, 54.0f / 255.0f, 62.0f / 255.0f));

  DataGroup* pFebruaryATIMobileDataGroup = new DataGroup("ATI Mobile");
  pFebruaryDataSet->AddDataGroup(pFebruaryATIMobileDataGroup);
  pFebruaryATIMobileDataGroup->AddDataEntry(new DataEntry("Radeon 3000M", 0.54f / 0.7322f, 241.0f / 255.0f, 134.0f / 255.0f, 140.0f / 255.0f));
  pFebruaryATIMobileDataGroup->AddDataEntry(new DataEntry("Radeon 4000M", 2.15f / 0.7322f, 252.0f / 255.0f, 98.0f / 255.0f, 106.0f / 255.0f));

  DataGroup* pFebruaryIntelMobileDataGroup = new DataGroup("Intel Mobile");
  pFebruaryDataSet->AddDataGroup(pFebruaryIntelMobileDataGroup);
  pFebruaryIntelMobileDataGroup->AddDataEntry(new DataEntry("Intel 4E", 1.76f / 0.7322f, 30.0f / 255.0f, 111.0f / 255.0f, 176.0f / 255.0f));


  DataSet* pMarchDataSet = new DataSet("Video card usage - March 2011", "Percentage");
  pTransitionManager->AddDataSet(pMarchDataSet);

  DataGroup* pMarchNVidiaDataGroup = new DataGroup("NVidia");
  pMarchDataSet->AddDataGroup(pMarchNVidiaDataGroup);
  pMarchNVidiaDataGroup->AddDataEntry(new DataEntry("GeForce 7", 1.29f / 0.7351f, 179.0f / 255.0f, 248.0f / 255.0f, 75.0f / 255.0f));
  pMarchNVidiaDataGroup->AddDataEntry(new DataEntry("GeForce 8", 10.32f / 0.7351f, 133.0f / 255.0f, 206.0f / 255.0f, 25.0f / 255.0f));
  pMarchNVidiaDataGroup->AddDataEntry(new DataEntry("GeForce 9", 12.74f / 0.7351f, 121.0f / 255.0f, 195.0f / 255.0f, 13.0f / 255.0f));
  pMarchNVidiaDataGroup->AddDataEntry(new DataEntry("GeForce 100", 3.22f / 0.7351f, 156.0f / 255.0f, 227.0f / 255.0f, 50.0f / 255.0f));
  pMarchNVidiaDataGroup->AddDataEntry(new DataEntry("GeForce 200", 10.75f / 0.7351f, 145.0f / 255.0f, 216.0f / 255.0f, 38.0f / 255.0f));
  pMarchNVidiaDataGroup->AddDataEntry(new DataEntry("GeForce 400", 4.86f / 0.7351f, 168.0f / 255.0f, 237.0f / 255.0f, 63.0f / 255.0f));

  DataGroup* pMarchNVidiaMobileDataGroup = new DataGroup("NVidia Mobile");
  pMarchDataSet->AddDataGroup(pMarchNVidiaMobileDataGroup);
  pMarchNVidiaMobileDataGroup->AddDataEntry(new DataEntry("GeForce 8M", 2.23f / 0.7351f, 182.0f / 255.0f, 234.0f / 255.0f, 104.0f / 255.0f));
  pMarchNVidiaMobileDataGroup->AddDataEntry(new DataEntry("GeForce 9M", 1.28f / 0.7351f, 205.0f / 255.0f, 240.0f / 255.0f, 153.0f / 255.0f));
  pMarchNVidiaMobileDataGroup->AddDataEntry(new DataEntry("GeForce 200M", 0.53f / 0.7351f, 209.0f / 255.0f, 252.0f / 255.0f, 143.0f / 255.0f));

  DataGroup* pMarchATIDataGroup = new DataGroup("ATI");
  pMarchDataSet->AddDataGroup(pMarchATIDataGroup);
  pMarchATIDataGroup->AddDataEntry(new DataEntry("Radeon 3000", 2.52f / 0.7351f, 245.0f / 255.0f, 66.0f / 255.0f, 74.0f / 255.0f));
  pMarchATIDataGroup->AddDataEntry(new DataEntry("Radeon 4000", 10.55f / 0.7351f, 240.0f / 255.0f, 42.0f / 255.0f, 51.0f / 255.0f));
  pMarchATIDataGroup->AddDataEntry(new DataEntry("Radeon 5000", 10.09f / 0.7351f, 242.0f / 255.0f, 54.0f / 255.0f, 62.0f / 255.0f));

  DataGroup* pMarchATIMobileDataGroup = new DataGroup("ATI Mobile");
  pMarchDataSet->AddDataGroup(pMarchATIMobileDataGroup);
  pMarchATIMobileDataGroup->AddDataEntry(new DataEntry("Radeon 3000M", 0.54f / 0.7351f, 241.0f / 255.0f, 134.0f / 255.0f, 140.0f / 255.0f));
  pMarchATIMobileDataGroup->AddDataEntry(new DataEntry("Radeon 4000M", 2.14f / 0.7351f, 252.0f / 255.0f, 98.0f / 255.0f, 106.0f / 255.0f));

  DataGroup* pMarchIntelMobileDataGroup = new DataGroup("Intel Mobile");
  pMarchDataSet->AddDataGroup(pMarchIntelMobileDataGroup);
  pMarchIntelMobileDataGroup->AddDataEntry(new DataEntry("Intel 4E", 1.72f / 0.7351f, 30.0f / 255.0f, 111.0f / 255.0f, 176.0f / 255.0f));

  pTransitionManager->InitializeChart();
}

MyGLWidget::~MyGLWidget() {
  //
}

void MyGLWidget::Initialize() {
  makeCurrent();

  GLenum err = glewInit();

  if (GLEW_OK != err) {
    return;
  }

  glEnable(GL_LINE_SMOOTH);
  glEnable(GL_POLYGON_SMOOTH);
  glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
  glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
  glShadeModel(GL_FLAT);
  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  glEnable(GL_MULTISAMPLE);

  qglClearColor(Qt::white);

  glDisable(GL_DEPTH_TEST);

  glViewport(0, 0, WIDTH, HEIGHT);
}

void MyGLWidget::paintEvent(QPaintEvent* pEvent) {
  UNREFERENCED(pEvent);

  pTransitionManager->Update();

  makeCurrent();

  glClear(GL_COLOR_BUFFER_BIT);

  QPainter pPainter(this);
  pPainter.setRenderHint(QPainter::Antialiasing);

  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  pTransitionManager->Draw(&pPainter);
  
  pPainter.end();
}

void MyGLWidget::resizeGL(int iWidth, int iHeight) {
  UNREFERENCED(iWidth);
  UNREFERENCED(iHeight);
}

QSize MyGLWidget::minimumSizeHint() const {
  return QSize(WIDTH, HEIGHT);
}

QSize MyGLWidget::sizeHint() const {
  return QSize(WIDTH, HEIGHT);
}

void MyGLWidget::mousePressEvent(QMouseEvent* pEvent) {
  UNREFERENCED(pEvent);
}

void MyGLWidget::wheelEvent(QWheelEvent* pEvent) {
  UNREFERENCED(pEvent);
}

void MyGLWidget::mouseReleaseEvent(QMouseEvent* pEvent) {	
  UNREFERENCED(pEvent);
}

void MyGLWidget::mouseMoveEvent(QMouseEvent* pEvent) {	
  UNREFERENCED(pEvent);
}