#include <QFile>
#include <QColor>
#include <QTextStream>
#include <QJsonObject>
#include <QJsonArray>
#include <QJsonDocument>

#include <QDebug>
#include <QStringList>

#include "WorkArea.hpp"

#include "StrengthLine.hpp"

WorkArea::WorkArea (int screenSizeX, int screenSizeY, QWidget * parent):
  QWidget(parent)
{
  this->screenSizeX = screenSizeX;
  this->screenSizeY = screenSizeY;
  readOnly = false;
  img = NULL;
  resizeFactor = 1;
  indexPointClicked = -1;
  maxLines = 0;
}

WorkArea::WorkArea (int screenSizeX, int screenSizeY, const std::string & filename, QWidget * parent):QWidget(parent)
{
  this->screenSizeX = screenSizeX;
  this->screenSizeY = screenSizeY;
  readOnly = false;
  img = NULL;
  resizeFactor = 1;
  indexPointClicked = -1;
  maxLines = 0;
  loadImage(filename);
}

WorkArea::WorkArea (int screenSizeX, int screenSizeY, const std::string & imageFilename, const std::string & SLFilename, bool readOnly, QWidget * parent):QWidget(parent)
{
  this->screenSizeX = screenSizeX;
  this->screenSizeY = screenSizeY;
  img = NULL;
  resizeFactor = 1;
  indexPointClicked = -1;
  maxLines = 0;
  loadImage(imageFilename);
  this->readOnly = readOnly;
  loadSL(SLFilename);  
}

WorkArea::~WorkArea ()
{
}

void
WorkArea::loadImage (const std::string & filename)
{
  QImage opened (QString::fromStdString (filename));
  img =
    new QImage (opened. scaled (screenSizeX, screenSizeY - this->geometry ().y (),
		Qt::KeepAspectRatio, Qt::FastTransformation));
  
  resizeFactor = (img->width()*1.0)/opened.width();
  liste_points.clear ();
  
  setFixedSize (img->width (), img->height ());
}

void
WorkArea::loadSL (const std::string & filename)
{
  liste_points.clear();

  QFile fin(QString::fromStdString (filename));
  fin.open(QIODevice::ReadOnly);
  QByteArray ba2 = fin.readAll();
  QJsonParseError parseError;
  QJsonDocument doc2 = QJsonDocument::fromJson(ba2, &parseError);
  QJsonArray lines = doc2["lines"].toArray();
  for(unsigned int i=0; i<lines.size(); i++){
    QJsonArray line = lines[i].toArray();
    QJsonArray point1 = line[0].toArray();
    QJsonArray point2 = line[1].toArray();
    liste_points << new QPoint((int)(point1[0].toDouble()*resizeFactor), (int)(point1[1].toDouble()*resizeFactor));
    liste_points << new QPoint((int)(point2[0].toDouble()*resizeFactor), (int)(point2[1].toDouble()*resizeFactor));
  }
}

void
WorkArea::saveStrengthLine (const std::string & filename)
{
  QJsonObject root;
  QJsonArray lines;
  
  for (int i = 0; i < liste_points.size () / 2; i++){
    QJsonArray line;
    QJsonArray point1;
    point1.push_back(liste_points[i*2]->x ()/resizeFactor);
    point1.push_back(liste_points[i*2]->y ()/resizeFactor);
    line.push_back(point1);
    QJsonArray point2;
    point2.push_back(liste_points[i*2+1]->x ()/resizeFactor);
    point2.push_back(liste_points[i*2+1]->y ()/resizeFactor);
    line.push_back(point2);

    lines.push_back(line);
  }
  
  root["lines"] = lines;

  QByteArray ba = QJsonDocument(root).toJson();
  QFile fout(QString::fromStdString (filename));
  fout.open(QIODevice::WriteOnly);
  fout.write(ba);
}

void
WorkArea::setReadOnly(bool readOnly){
  this->readOnly = readOnly;
}


void
WorkArea::paintEvent (QPaintEvent * event)
{
  QPainter painter (this);
  paint (painter);
}

void
WorkArea::paint (QPainter & painter)
{
  if (img != NULL)
    painter.drawImage (0, 0, *img);

  for (int i = 0; i < liste_points.length (); i++)
    {
      if(readOnly==false)
	{
	  painter.setBrush (QBrush (Qt::green));
	  painter.setPen (QPen (Qt::black));
	  painter.drawEllipse (liste_points[i]->x () - taillePoint / 2,
			       liste_points[i]->y () - taillePoint / 2,
			       taillePoint, taillePoint);
	}


      if ((i % 2) == 1)
	{
	  painter.setPen (QPen (Qt::red, epaisseurLigne));
	  std::pair < QPoint *, QPoint * >endPoints =
	    StrengthLine (liste_points[i - 1], liste_points[i]).toDraw (img);
	  painter.drawLine (*(std::get < 0 > (endPoints)),
			    *(std::get < 1 > (endPoints)));
	}

    }

}

void
WorkArea::mousePressEvent (QMouseEvent * event)
{
  if(readOnly==false)
    {
      if (img != NULL)
	{
	  // Est ce qu'on a cliqué sur un point existant ?
	  indexPointClicked = -1;
	  for (int i = 0; i < liste_points.length (); i++)
	    {
	      QPoint point = event->pos () - *(liste_points[i]);
	      if (point.manhattanLength () < taillePoint)
		{
		  indexPointClicked = i;
		}
	    }

	  // Clic gauche
	  if (event->button () == Qt::LeftButton)
	    {
	      if (indexPointClicked == -1)
		{
		  if((maxLines == 0) || (liste_points.size()<(maxLines*2))){
		    indexPointClicked = liste_points.size ();
		    liste_points << new QPoint (event->x (), event->y ());
		  }
		}
	    }
	  // Clic droit
	  if (event->button () == Qt::RightButton)
	    {
	      if (indexPointClicked != -1)
		{
		  if (indexPointClicked == (liste_points.size () - 1))
		    liste_points.removeAt (indexPointClicked);
		  else
		    {
		      if ((indexPointClicked % 2) == 0)
			{
			  QPoint *single =
			    liste_points.takeAt (indexPointClicked + 1);
			  liste_points.removeAt (indexPointClicked);
			  liste_points << single;
			}
		      else
			{
			  QPoint *single =
			    liste_points.takeAt (indexPointClicked - 1);
			  liste_points.removeAt (indexPointClicked - 1);
			  liste_points << single;
			}
		    }
		  indexPointClicked = -1;
		}
	    }
	}
    }
  repaint ();
}

void
WorkArea::mouseMoveEvent (QMouseEvent * event)
{
  if(readOnly==false)
    {
      if (indexPointClicked != -1)
	{
	  liste_points[indexPointClicked]->setX (event->x ());
	  liste_points[indexPointClicked]->setY (event->y ());
	}
    }
  repaint ();
}

void
WorkArea::mouseReleaseEvent (QMouseEvent * event)
{
  indexPointClicked = -1;
}
