#ifndef EINZEICHNEN_H
#define EINZEICHNEN_H

#include <iostream>
#include "output.h"
#include "../micro.h"
#include "../microadam.h"
#include "../recognition/imagesource.h"
#include "../recognition/searchanglesadam.h"
#include "../polarline.h"
extern "C"
{
  #include <opencv/highgui.h>
}

using namespace std;

namespace seemicro
{

/**
  * Zeichnet micro.Adam entsprechend der gefundenen Parameter
  * über das Bild aus \c src.
  */
class EinzeichnenOutput : public OutputModule
{
  ImageSource& src;
  SearchAnglesAdam& sa;
  Micro& m;
  MicroAdam *adam;
  CvFont *font;
  static EinzeichnenOutput *home;
  IplImage *eingezeichnet;
  int drawHoughLines;

public:
  EinzeichnenOutput(ImageSource& As, SearchAnglesAdam& Asa, CvFont *Af) :
    src(As), sa(Asa), m(sa.adam), font(Af)
  {
    home = this;
    adam = dynamic_cast<MicroAdam*>(&m);
    drawHoughLines = 0;
    if(1 != cvNamedWindow("SearchAnglesAdam", 1))
    { cerr << "cvNamedWindow(SearchAnglesAdam): error" << endl; }

if(DEBUGLEVEL>=2) cerr << "EO:TBs\n";
    cvCreateTrackbar("Hough: Distance Resolution", "SearchAnglesAdam", &sa.distres, 400,
      callback);
    cvCreateTrackbar("Hough: Angle Resolution", "SearchAnglesAdam", &sa.angres, 360,
      callback);
    cvCreateTrackbar("Hough-Schwellwert", "SearchAnglesAdam", &sa.hough_threshold, 250,
      callback);
    cvCreateTrackbar("Hough: Max Gap", "SearchAnglesAdam", &sa.houghMaxGap, 200,
      callback);
    cvCreateTrackbar("Draw Hough Lines?", "SearchAnglesAdam", &drawHoughLines, 1,
      callback);
if(DEBUGLEVEL>=2) cerr << "EinzeichnenOutput:Trackbars created\n";

    eingezeichnet = cvCreateImage(cvSize(src.img->width,src.img->height),
       IPL_DEPTH_8U, 3);

  };

  ~EinzeichnenOutput()
  {
    cvReleaseImage(&eingezeichnet);
    cvDestroyWindow("SearchAnglesAdam");
  }

  void output(bool keyframe)
  {
    // trackbarvariablen müssen von hand gesetzt
    // werden, da SetTrackbarPos die Callbackfunktion nicht aufruft
    einzeichnen(m);
  }

  void einzeichnen(Micro& p)
  {
#ifdef DEBUG
    if(DEBUGLEVEL>=3) cerr << "->einzeichnen\n";
#endif

    // gray2rgb
    cvConvertImage(src.img, eingezeichnet);// takes ~10000 usecs
    cvScale(eingezeichnet, eingezeichnet, 0.5);// takes ~4000 usecs
    
    // Invertieren
    cvConvertScale(eingezeichnet, eingezeichnet, -1, 255);

    if(p.mitteValid)
    {
      p.draw(eingezeichnet, false, double(CV_RGB(230, 70, 70)), false);
      // arme_auch?

      cvRectangle(eingezeichnet,
	  cvPoint(int(p.mitte.p.x-p.radius),
	    int(p.mitte.p.y-p.radius)),
	  cvPoint(int(p.mitte.p.x+p.radius),
	    int(p.mitte.p.y+p.radius)), 255);
      //    cout << "Mitte: " << p.mitte
      //      << " value: " << adam->correlationStrength << "\r";

      cvCircle(eingezeichnet, p.mitte, 4, CV_RGB(200,255,255));
//      polarLine mline2 = adam->mline;
//      mline2.r-=adam->dr2;
//      mline2.draw(eingezeichnet, CV_RGB(0, 255, 0));

      char line[50];
      sprintf(line, "alpha= %2.0f", p.alpha*180/M_PI);
      cvPutText(eingezeichnet, line, cvPoint(src.img->width-100, 30), font,
	    CV_RGB(0, 0, 0));
//	    CV_RGB(255, 255, 255));
      if(adam)
      {
        sprintf(line, "beta= %2.0f", adam->beta*180/M_PI);
        cvPutText(eingezeichnet, line, cvPoint(src.img->width-100, 60), font,
//	    CV_RGB(255, 255, 255));
	    CV_RGB(0, 0, 0));
      }

      // falls mitte nicht stimmt (z.b. lange keine
      // korrelation durchgeführt), wird folgende
      // gelbe linie an falscher stelle eingezeichnet

      // searchStatus: 0 = OK, -1 = weniger als 2 Geraden gefunden,
      //    -2 = keine passenden Geraden im Bild
      if(sa.searchStatus==0)
        cvLine(eingezeichnet, sa.p1+p.mitte,
//	  sa.p2+p.mitte, CV_RGB(255, 255, 0));// gelb
	  sa.p2+p.mitte, CV_RGB(128, 128, 0));// dunkleres gelb
    }
    if(!p.mitteValid || drawHoughLines)
    {
      // von hough transform erkannte linien einzeichnen
      if(sa.lines) for(int i = 0; i < sa.lines->total; i++)
      {
	CvPoint* line = (CvPoint*)cvGetSeqElem(sa.lines, i);
	cvLine(eingezeichnet, line[0], line[1], CV_RGB(255, 0, 255), 1);
      }
    }

    mypoint bildmitte = mypoint(src.img->width, src.img->height);
    cvCircle(eingezeichnet, bildmitte, 4, CV_RGB(200,255,255));
    cvShowImage("SearchAnglesAdam", eingezeichnet);//10000 usecs?
    cvResizeWindow("SearchAnglesAdam", src.img->width+15, src.img->height+280);
#ifdef DEBUG
    if(DEBUGLEVEL>=3) cerr << "<-einzeichnen\n";
#endif
  }

  void parametrize(void)
  {
    sa.paramChanged = true;
  }

  static void callback(int dummy=0)
  {
    if(!home) return;
    home->parametrize();
  }

}; // EinzeichnenOutput

} // seemicro

#endif

