#ifndef CORRELATIONOUTPUT_H
#define CORRELATIONOUTPUT_H

#include "output.h"
#include "../recognition/correlation.h"
#include "../microadam.h"
#include <iostream>

using namespace std;

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

namespace seemicro
{

class CorrelationOutput : public OutputModule
{
  CorrelationModule& c;
  Micro& micro;
  MicroAdam *adam;
  IplImage *back;

  /**
    * for highgui callbacks
    */
  static CorrelationOutput *home;

  int back_threshold;

  /**
    * radius trackbar, up to half image height
    */
  int radius;

  /**
    * alpha trackbar, 0 to 359 degrees
    */
  int ialpha;

  /**
    * beta trackbar, 0 to 359 degrees, where beta=180-ibeta so as to allow it to be nagative
    */
  int ibeta;

public:
  CorrelationOutput(CorrelationModule& Ac) :
    c(Ac), micro(c.micro)
  {
    home = this;
    adam = dynamic_cast<MicroAdam*>(&micro);
    back_threshold = 1;
    radius = int(c.kparams->radius);
    ialpha = int(c.kparams->alpha*180/M_PI);
    back = cvCreateImage(cvSize(c.src.img->width,
      c.src.img->height), IPL_DEPTH_8U, 3);

    if(1 != cvNamedWindow("Correlation", 1))
    { cerr << "cvNamedWindow(Correlation): error" << endl; }
    if(DEBUGLEVEL>=2) cerr << "c.arm_auch=" << c.arm_auch
      << " radius=" << radius
      << " ialpha=" << ialpha << endl;

    cvCreateTrackbar("Rad-Radius", "Correlation", &radius,
      c.src.img->height/2, callback);
    cvCreateTrackbar("Alpha", "Correlation", &ialpha, 360, callback);

    if(adam)
    {
      ibeta = int(c.kparams->alpha*180/M_PI+180);
      cvCreateTrackbar("Beta", "Correlation", &ibeta, 360, callback);
      int ret = cvCreateTrackbar("Kern mit Arm(en)?", "Correlation",
        &c.arm_auch, 1, callback);
      if(DEBUGLEVEL>=2) cerr << "Rückgabe: " << ret << endl;
    }

    cvCreateTrackbar("Grün-Schwellwert", "Correlation", &back_threshold, 50,
      callback);

    if(DEBUGLEVEL>=2) cerr << " created.";
  }

  ~CorrelationOutput()
  {
    cvReleaseImage(&back);
    cvDestroyWindow("Correlation");
  }

  void output(bool keyframe)
  {
    if(!c.outputChanged) return;
    if(!keyframe) return;
    doubles2IplImage(1/150.0, back, (double*)c.ffback,
	back->width, back->height, above_threshold);
    cvShowImage("Correlation", back);
    radius = int(c.micro.radius);
    cvSetTrackbarPos("Rad-Radius", "Correlation", radius);
    cvResizeWindow("Correlation", back->width+15, back->height+280);
    c.outputChanged = false;// sollte eigentlich erst zurückgesetzt werden,
    // wenn alle Module durchgelaufen sind, sonst können unsere
    // Nachfolger nicht reagieren
  }

  void parametrize(void)
  {
    c.kparams->radius = radius;
    c.kparams->alpha = double(ialpha)*M_PI/180.0;
    if(adam)
    {
      MicroAdam *kadam = dynamic_cast<MicroAdam*>(c.kparams);
      kadam->beta = double(ibeta-180)/180*M_PI;
      adam->beta = kadam->beta;
    }

    // damit beim Einzeichnen die Kernel-Parameter verwendet werden
    micro.mitte = c.kparams->mitte;
    micro.mitteValid = true;
    micro.alpha = c.kparams->alpha;

    c.paramChanged = true;
  }

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

  static double threshold_value(void)
  {
    return exp(home->back_threshold*0.05)*255;
  }

  static int above_threshold(double v)
  {
    return v > home->threshold_value();
  }

}; // CorrelationOutput

} // seemicro

#endif

