#ifndef HSVCOLORCHOOSER_H
#define HSVCOLORCHOOSER_H

#include <iostream>
#include "output.h"
#include "../image.h"
#include "../opencvext.h"
#include "../recognition/hsvrange.h"

extern"C"
{
  #include <opencv/highgui.h>
}

using namespace std;

namespace seemicro
{

struct HSVColorChooser : public OutputModule
{
  HSVRange& range;
  static HSVColorChooser *home;
  IplImage *img;

  HSVColorChooser(HSVRange& Arange) : range(Arange)
  {
    home = this;
    cvNamedWindow("HSVColorChooser", 1);
    img = cvCreateImage(cvSize(200, 220), IPL_DEPTH_8U, 3);
    cvCreateTrackbar("H min", "HSVColorChooser", &range.hmin, 360, callback);
    cvCreateTrackbar("H max", "HSVColorChooser", &range.hmax, 360, callback);
    cvCreateTrackbar("S min", "HSVColorChooser", &range.smin, 255, callback);
    cvCreateTrackbar("S max", "HSVColorChooser", &range.smax, 255, callback);
    cvCreateTrackbar("V min", "HSVColorChooser", &range.vmin, 255, callback);
    cvCreateTrackbar("V max", "HSVColorChooser", &range.vmax, 255, callback);
  }

  ~HSVColorChooser()
  {
    cvReleaseImage(&img);
    cvDestroyWindow("HSVColorChooser");
  }

  virtual void output(bool keyframe)
  {
#ifdef DEBUG
    if(DEBUGLEVEL>=3) cerr << "->HSVColorChooser::output()\n";
#endif
    if(!keyframe) return;

    if(range.hmin>range.hmax)
    {
      range.hmin=range.hmax;
      cvSetTrackbarPos("H min", "HSVColorChooser", range.hmin);
    }
    if(range.smin>range.smax)
    {
      range.smin=range.hmax;
      cvSetTrackbarPos("S min", "HSVColorChooser", range.smin);
    }
    if(range.vmin>range.vmax)
    {
      range.vmin=range.hmax;
      cvSetTrackbarPos("V min", "HSVColorChooser", range.vmin);
    }

    int h = (range.hmax+range.hmin)/2;
    //cerr << "h: " << h << endl;
    for(int x=0; x<200; x++)
      for(int y=0; y<200; y++)
      {
        int s = int(x*255/200);
	int v = int(y*255/200);
        int c = hsv2rgb(h, s, v);
	putPixel8u_3(img, x, y, c);
      }

    cvRectangle(img, cvPoint(range.smin*200/255, range.vmin*200/255),
                cvPoint(range.smax*200/255, range.vmax*200/255),
		CV_RGB(255, 255, 255));

    // Hue-Balken
    for(int x=0; x<200; x++)
    {
      int c = hsv2rgb(x*360/255, 255, 255);
      cvLine(img, cvPoint(x,200), cvPoint(x, 219), c);
    }

    const int nSpecialColors = 22;
    int specialColor[nSpecialColors] = {
      0x2c3311,
      0x2a3519,
      0x30391e,
      0x374628,
      0x3b421e,
      0x3d4c0a,
      0x434231,
      0x43552d,
      0x444537, // ziemlich grau...
      0x4c4d3f, // ziemlich grau...
      0x525a31,
      0x555c38,
      0x5b5539,
      0x606d27,
      0x646442,
      0x687e41,
      0x696a5a, // ziemlich grau...
      0x6d7a34,
      0x6d6e5e, // ziemlich grau...
      0x7c7a47,
      0x7d9356,
      0xa3b270,
      };
    for(int i=0;i<nSpecialColors; i++)
    {
      ushort hs, ss, vs;
      rgb2hsv(specialColor[i], &hs, &ss, &vs);

      cvCircle(img, cvPoint(ss*200/255, vs*200/255),
        3, CV_RGB(255, 255, 255), CV_FILLED);
      int hdiff = hs-h;
      if(hdiff>0)
        cvLine(img, cvPoint(ss*200/255, vs*200/255),
	            cvPoint(ss*200/255, vs*200/255+hdiff*2),
		    CV_RGB(255, 255, 255));
      else
        cvLine(img, cvPoint(ss*200/255, vs*200/255+hdiff*2),
	            cvPoint(ss*200/255, vs*200/255),
		    CV_RGB(255, 255, 255));
      // Kreis in HueBalken
      cvCircle(img, cvPoint(hs*200/360, 210),
        2, CV_RGB(255, 255, 255), CV_FILLED);
    }

    // hmin/hmax in HueBalken einzeichnen
    cvLine(img, cvPoint(range.hmin*200/360,200), cvPoint(range.hmin*200/360, 219),
      CV_RGB(255, 255, 255), 2);
    cvLine(img, cvPoint(range.hmax*200/360,200), cvPoint(range.hmax*200/360, 219),
      CV_RGB(255, 255, 255), 2);

    cvShowImage("HSVColorChooser", img);
    cvResizeWindow("HSVColorChooser", 200+5, 200+350);
  } // output()

  static void callback(int dummy=0)
  {
    if(!home) return;
    home->output(true);
    home->range.paramChanged = true;
    home->range.outputChanged = true;// könnte range selbst machen
  }

}; // HSVColorChooser

} // seemicro

#endif

