//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include <math.h>
#include "QDrawHSVGraph.h"

//---------------------------------------------------------------------------
#pragma package(smart_init)
//---------------------------------------------------------------------------
/**
 * Constructor
**/
QDrawHSVGraph::QDrawHSVGraph(TCanvas *_canvas) {
  Canvas = _canvas;
  ColumnNumber = 16;
  LeftMargin = 150;
  SetSize(32);
}
//---------------------------------------------------------------------------
void QDrawHSVGraph::SetSize(int BoxSize) {
  BoxWidth = BoxSize;
  BoxDepth = int(0.4 * BoxWidth);
  BoxMaxHeight = 2 * BoxWidth;
  BoxOffset = (0.2 * BoxWidth);

  TopMargin = BoxMaxHeight + 10;
}

//---------------------------------------------------------------------------
/**
 * Draw a box
**/
void QDrawHSVGraph::DrawBox(int _x, int _y, int height, double theta) {
  TColor c1 = GetColor(theta, 1.0);
  TColor c2 = GetColor(theta, 0.8);
  TColor c3 = GetColor(theta, 0.6);

  SetPenColor(clDkGray);
  //Draw rightside surface
  Canvas->MoveTo(_x + BoxWidth            , _y);
  Canvas->LineTo(_x + BoxWidth - BoxOffset, _y + BoxDepth);
  Canvas->LineTo(_x + BoxWidth - BoxOffset, _y + BoxDepth - height);
  Canvas->LineTo(_x + BoxWidth            , _y            - height);
  Canvas->LineTo(_x + BoxWidth            , _y);
  SetBrushColor(c2);
  Canvas->FloodFill(_x + BoxWidth - 1, _y - 1, clDkGray, fsBorder);
  SetPenColor(clBlack);
  Canvas->LineTo(_x + BoxWidth - BoxOffset, _y + BoxDepth);
  Canvas->LineTo(_x + BoxWidth - BoxOffset, _y + BoxDepth - height);
  Canvas->LineTo(_x + BoxWidth            , _y            - height);
  Canvas->LineTo(_x + BoxWidth            , _y);

  //Draw front surface
  SetBrushColor(c1);
  TRect rc(_x - BoxOffset,                _y + BoxDepth - height,
           _x - BoxOffset + BoxWidth + 1, _y + BoxDepth + 1);
  Canvas->FillRect(rc);
  SetBrushColor(clBlack);
  Canvas->FrameRect(rc);

  //Draw top surface
  SetPenColor(clDkGray);
  Canvas->MoveTo(_x                       , _y - height);
  Canvas->LineTo(_x + BoxWidth            , _y - height);
  Canvas->LineTo(_x + BoxWidth - BoxOffset, _y - height + BoxDepth);
  Canvas->LineTo(_x            - BoxOffset, _y - height + BoxDepth);
  Canvas->LineTo(_x                       , _y - height);
  SetBrushColor(c3);
  Canvas->FloodFill(_x + 1, _y - height + 1, clDkGray, fsBorder);
  SetPenColor(clBlack);
  Canvas->LineTo(_x + BoxWidth            , _y - height);
  Canvas->LineTo(_x + BoxWidth - BoxOffset, _y - height + BoxDepth);
  Canvas->LineTo(_x            - BoxOffset, _y - height + BoxDepth);
  Canvas->LineTo(_x                       , _y - height);

}
//---------------------------------------------------------------------------
void QDrawHSVGraph::DrawBoxBase(int _x, int _y) {
  TColor cl = clLtGray;

  SetPenColor(clBlack);
  Canvas->MoveTo(_x                       , _y);
  Canvas->LineTo(_x + BoxWidth            , _y);
  Canvas->LineTo(_x + BoxWidth - BoxOffset, _y + BoxDepth);
  Canvas->LineTo(_x            - BoxOffset, _y + BoxDepth);
  Canvas->LineTo(_x, _y);
  SetBrushColor(cl);
  Canvas->FloodFill(_x + 1, _y + 1, clBlack, fsBorder);
}

//---------------------------------------------------------------------------
TColor QDrawHSVGraph::GetColor(double theta, double abVal) {
  double value = theta*56;
  double h,s,v;

  h = value;
  s = abVal;
  v = 1;

  float r = 0;
  float g = 0;
  float b = 0;
  if (s < 0) s = 0;
  if (s > 1) s = 1;
  if (v < 0) v = 0;
  if (v > 1) v = 1;

  h = h / 60;
  int i = int(h);
  float f = h - i;
  float p1 = v * (1 - s);
  float p2 = v * (1 - s*f);
  float p3 = v * (1 - s*(1 - f));
if (i == 0) { r = v; g = p3; b = p1; }
  if (i == 1) { r = p2;g = v;  b = p1; }
  if (i == 2) { r = p1;g = v;  b = p3; }
  if (i == 3) { r = p1;g = p2; b = v;  }
  if (i == 4) { r = p3;g = p1; b = v;  }
  if (i == 5) { r = v; g = p1; b = p2; }

  int R = (int)(r*255);
  int G = (int)(g*255);
  int B = (int)(b*255);

  TColor Color = TColor(0x10000*R+0x100*G+B);
  return Color;
}
//------------------------------------------------------------------------
void QDrawHSVGraph::DrawTest(void) {
//DrawBox(100, 100, 50, 0);
  DrawBoxBase(100, 100);
}
//------------------------------------------------------------------------
void QDrawHSVGraph::DrawAll(QBits * qBits) {
// clear canvas
  SetBrushColor(clWhite);
  Canvas->FloodFill(1, 1, clDkGray, fsBorder);

  const int N = qBits->GetNumberOfStates();
  const double eps = 1.0e-20;

  for (int i = 0; i < N; i++) {
    double im = qBits->NthStateI(i);
    double re = qBits->NthStateR(i);
    double R  = sqrt(im * im + re * re);
    double theta = 3.1416 + atan2(im, re + eps);

    int ix = i % ColumnNumber;
    int iy = (i - ix) / ColumnNumber;
    int x  = LeftMargin + ix * BoxWidth - iy * BoxOffset;
    int y  = TopMargin  + iy * BoxDepth;

    if (R == 0) {
      DrawBoxBase(x, y);
    } else {
      DrawBox(x, y, int(R * BoxMaxHeight), theta);
    }
  }

// draw HSV sumple
  for (int i = 0; i < 208; i++) {
    SetPenColor(GetColor(0.03 * i, 1.0));
    Canvas->MoveTo(10, TopMargin + i);
    Canvas->LineTo(10 + BoxDepth, TopMargin + i);
  }
}
//-----------------------------------------------------------------------
void QDrawHSVGraph::DrawAll2D(QBits * qBits) {
// clear canvas
  SetBrushColor(clWhite);
  Canvas->FloodFill(1, 1, clDkGray, fsBorder);

  const int N = qBits->GetNumberOfStates();
  const double eps = 1.0e-20;

  for (int i = 0; i < N; i++) {
    double im = qBits->NthStateI(i);
    double re = qBits->NthStateR(i);
    double R  = sqrt(im * im + re * re);
    double theta = 3.1416 + atan2(im, re + eps);

    int ix = i % ColumnNumber;
    int iy = (i - ix) / ColumnNumber;
    int x  = 50 + ix * BoxWidth;
    int y  = 20 + iy * BoxWidth;

    TRect rc(x, y, x + BoxWidth + 1, y + BoxWidth + 1);
    SetBrushColor(GetColor(theta, R));
    Canvas->FillRect(rc);
    SetBrushColor(clBlack);
    Canvas->FrameRect(rc);
  }

// draw HSV sumple
  for (int i = 0; i < 208; i++) {
    SetPenColor(GetColor(0.03 * i, 1.0));
    Canvas->MoveTo(10, TopMargin + i);
    Canvas->LineTo(10 + BoxDepth, TopMargin + i);
  }

}

