#include "DetectionClient.hh"
#include <sstream>
#include <tinyxml2.h>
#include <stdexcept>
#include "ZMQClient.hh"
#include <chrono>

DetectionClient::DetectionClient() :
  ZMQClient()
{}

DetectionClient::~DetectionClient() {
    cancel = 1;
}

// Gibt die Polygone aller gefundenen Objekte zurück
//  image: Das Bild das nach Objekten durchsucht werden soll
std::vector< std::vector<cv::Point> > *DetectionClient::getContours(cv::Mat image){

    cv::Mat segmentImage = cv::Mat::zeros(image.rows,image.cols,CV_8U);

    std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();


    sendStringToServer("array", true);
    std::string replyMessage = sendImageToServer(image, false);
    std::stringstream sstream(replyMessage);

    std::chrono::steady_clock::time_point end= std::chrono::steady_clock::now();

    std::cout << "Time get Contour = "
              << (static_cast<float>(std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count())/1000.f)
              << " sec" << std::endl;

    if(!segmentImage.isContinuous()){
      segmentImage = segmentImage.clone();
    }
    sstream.read((char *)segmentImage.data, image.cols * image.rows);
    std::vector< std::vector<cv::Point> > *contours = new std::vector< std::vector<cv::Point> >();
    double mind, maxd;
//  cv::imshow("Test", segmentImage * 10);
    cv::minMaxIdx(segmentImage, &mind, &maxd);
    unsigned int max = static_cast<unsigned int>(maxd);

    // the segments are scanned individually with compare and then added to contours, because findContours looks for non zero segments
    for(unsigned int j = 1; j <= max; j++){
      std::vector< std::vector<cv::Point> > contour;
      cv::Mat singleSegment = cv::Mat::zeros(image.rows, image.cols, CV_8U);
      cv::compare(segmentImage, j, singleSegment, cv::CMP_EQ);
      cv::findContours(singleSegment, contour, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
      if (!contour.empty()) {
        contours->push_back(contour[0]);
      }
    }

    return contours;
}

// Gibt das Segemtierte Bild zurück
//  image: Das Bild, welches segmentiert werden soll
cv::Mat DetectionClient::getSegmentation(cv::Mat image)
{
  cv::Mat segmentImage = cv::Mat::zeros(image.rows,image.cols,CV_8U);
  sendStringToServer("array", true);
  std::string replyMessage = sendImageToServer(image, false);
  std::stringstream sstream(replyMessage);
  if(!segmentImage.isContinuous()){
    segmentImage = segmentImage.clone();
  }
  sstream.read((char *)segmentImage.data, image.cols * image.rows);
  return segmentImage;
}
