/***************************************************************************
 *   Copyright (C) 2004 by Juergen Thies                                   *
 *   layout@juergenthies.de                                                *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/


#include "polygonproperties.h"
#include "polygon.h"
#include "box.h"
#include "pointarray.h"
#include <qspinbox.h>
#include <qlineedit.h>
#include <QTableWidget>
#include <QTableWidgetItem>
#include "general/setup.h"
#include <qstring.h>
#include <qpushbutton.h>
#include <QStringList>
#include "general/userunitsvalidator.h"
#include "propertyedit.h"

polygonproperties::polygonproperties(double uunits)
: polygonpropertiesdialog()
{setupUi(this);
userunits=uunits;
userunitsValidator v(uunits,this);
decimals=v.decimals();
layerNr->setMaximum(layersMax-1);
layerNr->setMinimum(0);
QStringList l;
l<<"x";
l<<"y";
coordinates->setHorizontalHeaderLabels(l);
valid=new userunitsValidator(uunits,this);
centerX->setValidator(valid);
centerY->setValidator(valid);
radius->setValidator(valid);
centerSecX->setValidator(valid);
centerSecY->setValidator(valid);
radiusSec->setValidator(valid);
boxLeft->setValidator(valid);
boxRight->setValidator(valid);
boxTop->setValidator(valid);
boxBottom->setValidator(valid);
boxWidth->setValidator(valid);
boxHeight->setValidator(valid);
connect(layerNr,SIGNAL(valueChanged(int)),this,SLOT(setLayerName(int)));
connect(coordinates,SIGNAL( itemClicked(QTableWidgetItem *)),this,SLOT(setEdit(QTableWidgetItem *)));
connect(toBox,SIGNAL( clicked()),this,SLOT(DoneToBox()));
connect(deletePolygon,SIGNAL( clicked()),this,SLOT(DoneDeletePolygon()));
connect(coordinates,SIGNAL(  currentItemChanged ( QTableWidgetItem * , QTableWidgetItem * )),this,SLOT(updateItem(QTableWidgetItem *,QTableWidgetItem *)));
connect(editPoints,SIGNAL( clicked()),this,SLOT( editPoint()));
connect(editPoints2,SIGNAL( clicked()),this,SLOT( editPoint()));
connect(editPoints3,SIGNAL( clicked()),this,SLOT( editPoint()));
connect(toCircle,SIGNAL(clicked()),this,SLOT(convertToCircle()));
connect(centerX,SIGNAL(textChanged(const QString &)),this,SLOT(checkInput(const QString &)));
connect(centerY,SIGNAL(textChanged(const QString &)),this,SLOT(checkInput(const QString &)));
connect(radius,SIGNAL(textChanged(const QString &)),this,SLOT(checkInput(const QString &)));
connect(boxLeft,SIGNAL(textChanged(const QString &)),this,SLOT(checkInput(const QString &)));
connect(boxRight,SIGNAL(textChanged(const QString &)),this,SLOT(checkInput(const QString &)));
connect(boxBottom,SIGNAL(textChanged(const QString &)),this,SLOT(checkInput(const QString &)));
connect(boxTop,SIGNAL(textChanged(const QString &)),this,SLOT(checkInput(const QString &)));
connect(boxWidth,SIGNAL(textChanged(const QString &)),this,SLOT(checkInputWidth(const QString &)));
connect(boxHeight,SIGNAL(textChanged(const QString &)),this,SLOT(checkInputHeight(const QString &)));
editType-> setCurrentIndex(0);
connect(attributeButton,SIGNAL(clicked()),this,SLOT(showAttributes()));
connect(fullDisplay,SIGNAL( clicked()),this,SLOT(displayAll()));
connect(editPoints,SIGNAL( clicked()),this,SLOT( editPoint()));
connect(centerSecX,SIGNAL(textChanged(const QString &)),this,SLOT(checkInput(const QString &)));
connect(centerSecY,SIGNAL(textChanged(const QString &)),this,SLOT(checkInput(const QString &)));
connect(radiusSec,SIGNAL(textChanged(const QString &)),this,SLOT(checkInput(const QString &)));
setModal(true);
calcOperation=false;
}

polygonproperties::~polygonproperties()
{
centerX->setValidator(NULL);
centerY->setValidator(NULL);
radius->setValidator(NULL);
centerSecX->setValidator(NULL);
centerSecY->setValidator(NULL);
radiusSec->setValidator(NULL);
boxTop->setValidator(NULL);
boxBottom->setValidator(NULL);
boxLeft->setValidator(NULL);
boxRight->setValidator(NULL);
boxWidth->setValidator(NULL);
boxHeight->setValidator(NULL);
delete valid;
}

void polygonproperties::setEdit(QTableWidgetItem *i){
 coordinates->editItem(i);
 }


void polygonproperties::reject()
{
  QDialog::reject();
}

void polygonproperties::accept()
{ updateElement();
  QDialog::accept();
}

void polygonproperties::updateElement(){
  if (editType-> currentIndex()!=0) editPoint();
  coordinates->setCurrentItem(NULL);
  element->layerNum=layerNr->value();
  element->datatype=datatype->value();
  if (array.size()>0) element->pointarray=array;
  element->clean();
}

void polygonproperties::setElement(polygon *p,bool basicEditing){
 element=p;
   layerNr->setValue(p->layerNum);
   datatype->setValue(p->datatype);
   bool hide_=true;
   if (p->datatype==0) {datatypeBox->hide();hide_=false;}
   setLayerName(p->layerNum);
   array=p->pointarray;
   if (array.size()>MAXITEMS/2-1) array.resize(0);
   coordinates->resizeColumnToContents(1);
   coordinates->resizeColumnToContents(0);
   setCoordinates();
   box *boxHelp=p->convertToBox();
   if (boxHelp==NULL){toBox->setEnabled(false);}
   if (!basicEditing){
	if (boxHelp!=NULL) {
		setBox(boxHelp);
		delete boxHelp;
		}
	else if (p->isCircle(&center, &radiusValue)){
		numCirclePoints=array.size()-1;
		setCircle();
		toCircle->setEnabled(false);
		}
	else if (p->isSector(&center,&radiusValue,&startAngle,&endAngle)) {
	//printf("arc\n");
	numCirclePoints=array.size()-2;
	setSector();
	}
   }
   OK->setFocus();
   if (element->property.size()==0) attributeButton->hide();
   else if (hide_) fullDisplay->hide();
}

 void polygonproperties::displayAll(){
fullDisplay->hide();
datatypeBox->show();
attributeButton->show();
}

void polygonproperties::setCircle(){
   editType-> setCurrentIndex(1);
   QString s;
   s.setNum((double)(center.x())*userunits,'f',decimals);
   centerX->setText(s);
   s.setNum((double)(center.y())*userunits,'f',decimals);
   centerY->setText(s);
   s.setNum((double)(radiusValue)*userunits,'f',decimals);
   radius->setText(s);
   numPoints->setValue(numCirclePoints);
/* QPoint center;
 int radiusValue;
 int numCirclePoints;*/
}

void polygonproperties::setBox(box *b){
   calcOperation=true;
   editType-> setCurrentIndex(2);
   QString s;
   s.setNum((double)(b->rect.left())*userunits,'f',decimals);
   boxLeft->setText(s);
   s.setNum((double)(b->rect.right())*userunits,'f',decimals);
   boxRight->setText(s);
   s.setNum((double)(b->rect.top())*userunits,'f',decimals);
   boxTop->setText(s);
   s.setNum((double)(b->rect.bottom())*userunits,'f',decimals);
   boxBottom->setText(s);
   calcOperation=false;
   setBoxWidthHeight();
}

void polygonproperties::setSector(){
   editType-> setCurrentIndex(3);
   QString s;
   s.setNum((double)(center.x())*userunits,'f',decimals);
   centerSecX->setText(s);
   s.setNum((double)(center.y())*userunits,'f',decimals);
   centerSecY->setText(s);
   s.setNum((double)(radiusValue)*userunits,'f',decimals);
   radiusSec->setText(s);
   numPointsSec->setValue(numCirclePoints);
   angleStart->setValue(startAngle);
   angleEnd->setValue(endAngle);
}

void polygonproperties::editPoint(){
   for (int i=0; i<array.size();i++){
	if (item[i*2].tableWidget()!=NULL)coordinates->takeItem(i,0);
	if (item[i*2+1].tableWidget()!=NULL)coordinates->takeItem(i,1);
   }
  if (editType->currentIndex()==1){
	center=QPoint(element::round(centerX->text().toDouble()/userunits), element::round(centerY->text().toDouble()/userunits));
	radiusValue=element::round(radius->text().toDouble()/userunits);
	numCirclePoints=numPoints->value();
	array=element::spirale(center,center+QPoint(radiusValue,0), center+QPoint(radiusValue,0),360.0/numCirclePoints);
	}
  else if (editType->currentIndex()==2){
 	array.resize(5);
    	array.setPoint(0,element::round(boxLeft->text().toDouble()/userunits), element::round(boxTop->text().toDouble()/userunits));
    	array.setPoint(1,element::round(boxLeft->text().toDouble()/userunits), element::round(boxBottom->text().toDouble()/userunits));
    	array.setPoint(2,element::round(boxRight->text().toDouble()/userunits), element::round(boxBottom->text().toDouble()/userunits));
    	array.setPoint(3,element::round(boxRight->text().toDouble()/userunits), element::round(boxTop->text().toDouble()/userunits));
    	array.setPoint(4,element::round(boxLeft->text().toDouble()/userunits), element::round(boxTop->text().toDouble()/userunits));
	}
  else if (editType->currentIndex()==3){
	center=QPoint(element::round(centerSecX->text().toDouble()/userunits), element::round(centerSecY->text().toDouble()/userunits));
	radiusValue=element::round(radiusSec->text().toDouble()/userunits);
	numCirclePoints=numPointsSec->value();
	startAngle=angleStart->value();
	endAngle=angleEnd->value();
	QMatrix m1,m2;
	m1.rotate(startAngle);
	m2.rotate(endAngle);
	double l=endAngle-startAngle;
	if (l<=0) l+=360;
	array=element::spirale(center,center+m1.map(QPoint(radiusValue,0)), center+m2.map(QPoint(radiusValue,0)),l/(numCirclePoints-1));;
	int i=array.size();
	array.resize(i+2);
	array.setPoint(i,center);
	array.setPoint(i+1,array.point(0));
	}
  editType-> setCurrentIndex(0);
  setCoordinates();
}

void polygonproperties::convertToCircle(){
  pointArray points=element::fitToCircle(array,false);
  polygon *poly= new polygon(points,0);
  poly->isCircle(&center, &radiusValue);
  setCircle();
  numCirclePoints=points.size()-1;
 for (int i=0; i<array.size();i++){
	if (item[i*2].tableWidget()!=NULL)coordinates->takeItem(i,0);
	if (item[i*2+1].tableWidget()!=NULL)coordinates->takeItem(i,1);
 }
  array=points;
  delete poly;
  setCircle();
}

void polygonproperties::checkInput(const QString &){
if (editType->currentIndex()==1){
	QString s;
	bool b=true;
	int i=0;
	s=centerX->text();
	if (centerX->validator()->validate(s,i)!=QValidator::Acceptable){b=false;}
	s=centerY->text();
	if (centerY->validator()->validate(s,i)!=QValidator::Acceptable){b=false;}
	s=radius->text();
	if (radius->validator()->validate(s,i)!=QValidator::Acceptable){b=false;}
	OK->setEnabled(b);
	}
else if (editType->currentIndex()==2){
	checkBox();
	if (OK->isEnabled()&&(!calcOperation)) setBoxWidthHeight();
	}
}

void polygonproperties::checkInputWidth(const QString&){
checkBox();
if (OK->isEnabled()&&(!calcOperation)){
	calcOperation=true;
	int width= element::round(boxWidth->text().toDouble()/userunits);
	int left_=center.x()-width/2;
	QString s;
   	s.setNum((double)(left_)*userunits,'f',decimals);
   	boxLeft->setText(s);
   	s.setNum((double)(left_+width)*userunits,'f',decimals);
   	boxRight->setText(s);
	calcOperation=false;
}
}
void polygonproperties::checkInputHeight(const QString&){
checkBox();
if (OK->isEnabled()&&(!calcOperation)){
	calcOperation=true;
	int height= element::round(boxHeight->text().toDouble()/userunits);
	int bottom_=center.y()-height/2;
	QString s;
   	s.setNum((double)(bottom_)*userunits,'f',decimals);
   	boxBottom->setText(s);
   	s.setNum((double)(bottom_+height)*userunits,'f',decimals);
   	boxTop->setText(s);
	calcOperation=false;
}
}
void polygonproperties::checkBox(){
	QString s;
	bool b=true;
	int i=0;
	s=boxLeft->text();
	if (boxLeft->validator()->validate(s,i)!=QValidator::Acceptable){b=false;}
	s=boxTop->text();
	if (boxTop->validator()->validate(s,i)!=QValidator::Acceptable){b=false;}
	s=boxRight->text();
	if (boxRight->validator()->validate(s,i)!=QValidator::Acceptable){b=false;}
	s=boxBottom->text();
	if (boxBottom->validator()->validate(s,i)!=QValidator::Acceptable){b=false;}
	s=boxWidth->text();
	if (boxWidth->validator()->validate(s,i)!=QValidator::Acceptable){b=false;}
	s=boxHeight->text();
	if (boxHeight->validator()->validate(s,i)!=QValidator::Acceptable){b=false;}
	OK->setEnabled(b);
}

void polygonproperties::setBoxWidthHeight(){
  calcOperation=true;
  int x=(element::round(boxLeft->text().toDouble()/userunits)+element::round(boxRight->text().toDouble()/userunits))/2;
  int y=(element::round(boxTop->text().toDouble()/userunits)+element::round(boxBottom->text().toDouble()/userunits))/2;
  int width= (-element::round(boxLeft->text().toDouble()/userunits)+ element::round(boxRight->text().toDouble()/userunits));
  int height= (element::round(boxTop->text().toDouble()/userunits) -element::round(boxBottom->text().toDouble()/userunits));
  center=QPoint(x,y);
  QString s;
  s.setNum((double)(height)*userunits,'f',decimals);
  boxHeight->setText(s);
  s.setNum((double)(width)*userunits,'f',decimals);
  boxWidth->setText(s);
  calcOperation=false;
}

void polygonproperties::setCoordinates(){

 QString s;
 coordinates->setRowCount(array.size());
 coordinates->setColumnCount(2);
 for (int i=0; i<array.size();i++){
 	s.setNum((double)(array.point(i).x())*userunits,'f',decimals);
	item[i*2].setText(s);
	if (item[i*2].tableWidget()==NULL)coordinates->setItem(i,0,&item[i*2]);
	s.setNum((double)(array.point(i).y())*userunits,'f',decimals);
	item[i*2+1].setText(s);
	if (item[i*2+1].tableWidget()==NULL)coordinates->setItem(i,1,&item[i*2+1]);
 }
 coordinates->resizeColumnToContents(1);
 coordinates->resizeColumnToContents(0);
}

void polygonproperties::updateItem(QTableWidgetItem *,QTableWidgetItem *c){
if (c!=NULL){
  if ( coordinates->column(c)==0)
  array.setPoint(coordinates->row(c),element::round(c->text().toDouble()/userunits),array.point(coordinates->row(c)).y());
  else 
  array.setPoint(coordinates->row(c),array.point(coordinates->row(c)).x(),element::round(c->text().toDouble()/userunits));
  if (coordinates->row(c)==(array.size()-1)) array.setPoint(0,array.point(array.size()-1));
  if (coordinates->row(c)==0) array.setPoint(array.size()-1,array.point(0));
  setCoordinates();}

}


void polygonproperties::setLayerName(int val){
   layerName->setText(layers::num[val].name);
}
void polygonproperties::showAttributes(){
propertyEdit pe(&element->property);
pe.exec();
}
