// Listing 9.2. Prosty program, w którym za pomocą myszy można rysować prostokąty na ekranie
#include <opencv2/opencv.hpp>

// definicja funkcji zwrotnej, którą zainstalujemy dla zdarzeń myszy
//
void my_mouse_callback(

  int event, int x, int y, int flags, void* param
);
cv::Rect box;
bool drawing_box = false;


// mała podprocedura rysująca prostokąt na obrazie
//
void draw_box( cv::Mat& img, cv::Rect box ) {
  cv::rectangle(
    img,
    box.tl(),
    box.br(),

    cv::Scalar(0x00,0x00,0xff)    /* red */
  );
}
void help(char** argv) {
  std::cout << "Listing 9.2. Prosty program, w którym za pomocą myszy można rysować prostokąty na ekranie"
     << "\nWywołanie:\n" << argv[0] <<
    "\n\npokazuje, jak za pomocą myszy rysować obszary na obrazie.\n" << std::endl;
}
int main( int argc, char** argv ) {
  help(argv);
  box = cv::Rect(-1,-1,0,0);
  cv::Mat image(200, 200, CV_8UC3), temp;
  image.copyTo(temp);
  box   = cv::Rect(-1,-1,0,0);
  image = cv::Scalar::all(0);
  cv::namedWindow( "Box Example" );
  // To jest kluczowe miejsce, w którym instalujemy funkcję zwrotną.
  // Zwróć uwagę na to, że argument params został ustawiony na obraz, z którym pracujemy,
  // dzięki czemu funkcja zwrotna będzie mogła go edytować.
  //
 cv::setMouseCallback(
   "Box Example",
   my_mouse_callback,
   (void*)&image
 );
 // Główna pętla programu. W tym miejscu kopiujemy obraz roboczy do obrazu tymczasowego
 // i jeśli użytkownik rysuje, wstawiamy aktualnie tworzony prostokąt na ten obraz tymczasowy.
 // Wyświetlamy obraz tymczasowy i czekamy 15 ms na naciśnięcie klawisza, a następnie powtarzamy czynność.
 //
 for(;;) {
    image.copyTo(temp);
    if( drawing_box ) draw_box( temp, box );
    cv::imshow( "Box Example", temp );
    if( cv::waitKey( 15 ) == 27 ) break;
  }
  return 0;
}

// To jest nasza funkcja zwrotna obsługi myszy. Jeżeli użytkownik naciśnie lewy przycisk, zaczynamy rysowanie prostokąta.
// Gdy użytkownik puści przycisk myszy, dodajemy prostokąt do bieżącego obrazu. 
// Kiedy użytkownik przeciągnie myszą (z naciśniętym przyciskiem), zmieniamy rozmiar prostokąta.
//
void my_mouse_callback(
int event, int x, int y, int flags, void* param) 
{
  cv::Mat& image = *(cv::Mat*) param;
  switch( event ) {
    case cv::EVENT_MOUSEMOVE: {
      if( drawing_box ) {
        box.width  = x-box.x;
        box.height = y-box.y;
      }
    }
    break;
 case cv::EVENT_LBUTTONDOWN: {
      drawing_box = true;
      box = cv::Rect( x, y, 0, 0 );
    }
    break;
    case cv::EVENT_LBUTTONUP: {
      drawing_box = false;
      if( box.width < 0  ) {

        box.x += box.width;
        box.width *= -1;
      }
      if( box.height < 0 ) {
        box.y += box.height;
        box.height *= -1;
      }
      draw_box( image, box );
    }
    break;
  }

}
