/***************************************************************************
 *   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.             *
 ***************************************************************************/
#define _USE_MATH_DEFINES
#include "ap.h"
#include <qfile.h>
#include <qstring.h>
#include <qtextstream.h>
#include "general/drawingfield.h"
//#include <q3pointarray.h>
#include "general/layers.h"
#include "elements/celllist.h"
#include "elements/cell.h"
#include "elements/path.h"
#include "elements/polygon.h"
#include "elements/strans.h"
#include <qmessagebox.h>
#include "general/setup.h"
#include "elements/element.h"
#include <qstringlist.h>
#include "layout.h"
#include <math.h>
#include "general/errorreport.h"


ap::ap(QObject *parent, const char *)
 : QObject(parent)
{
}


ap::~ap()
{
}


void ap::open(QString fileName,drawingField *d){
  ap apClass;
  apClass.load(fileName,d,fileOpen);
}

void ap::import(QString fileName,drawingField *d){
  ap apClass;
  apClass.load(fileName,d,fileImport);
}

void ap::update(QString fileName,drawingField *d){
  ap apClass;
  apClass.load(fileName,d,fileUpdate);
}

void ap::load(QString fileName,drawingField *d, fileOpenType typ){

  if (typ==fileImport) {
  	report.setTitle(tr("Import of AP-File \"")+fileName+"\"");}
  else  if (typ==fileOpen){
	report.setTitle(tr("Open of AP-File \"")+fileName+"\"");}
  else  if (typ==fileUpdate){
	report.setTitle(tr("Update with AP-File \"")+fileName+"\"");}
try { 
#ifdef printtime
  setup::centralTimer.start();
#endif
  cellList *firstcellhelp=d->firstCell;
  double databaseunitshelp=d->databaseunits;
  report.addItem(tr("AP-File is not converted to the real layout. See documentation for details."),2,QString(""));
  double scale=1.0/d->userunits*setup::apLamda;
  int lamda=element::round(1.0/d->userunits*setup::apLamda);
  int lamdaHalf=lamda/2;
//printf("%f\n",scale);
//printf("uu %f\n",d->userunits);
//printf("lamda %f\n",setup::apLamda);
  QFile f( fileName );
  if ( !f.open( QIODevice::ReadOnly ) )
	throw QString(tr("Can not open File."));
  QTextStream ts( &f );
  if ((typ==fileImport)||(typ==fileUpdate)) {
	d->firstCell=NULL;
  }
  for (int i=0; i<layersMax;i++){
  	 layerused[i]=false;
  	 if ((typ==fileImport)||(typ==fileUpdate)) {
		if (firstcellhelp->useLayer(i)) layerused[i]=true;
  }}
  QString s="";
  cellList *cell_list=NULL;
  cell *cell_=NULL;
  int layer=1;
  s=ts.readLine();
  s=ts.readLine();
  while (!ts.atEnd()&&(s.left(3)!="EOF")){
  QString s1=s.mid(2);
  QStringList sl=s1.split(",");
 // if (layout::debug)
 //printf("%s (%s)\n",s.left(1).toAscii().data(),s1.toAscii().data());
	if (s[0]=='R') {
		//ignore
		}
	else if (s[0]=='H')
		{
		//header
		if (sl.size()>0) {
			cell_list=d->addCell();
			cell_=cell_list->thisCell;
			cell_->cellName=sl[0];
		}
		if (sl.size()>=4) {
		scale/=sl[3].toInt();
		//printf("%f\n",scale);
		}
		}
	else if (s[0]=='A'){
		if (cell_==NULL) {
			report.addItem(tr("Invalid Header"),0,s);
			}
		else if (sl.size()==4) {
		cell_->addBox(element::round(sl[0].toInt()*scale),
				element::round(	sl[1].toInt()*scale),
				element::round(	sl[2].toInt()*scale),
				element::round(	sl[3].toInt()*scale),0);
		}else
		report.addItem(tr("Unknow entry"),3,s);
		}
	else if (s[0]=='S'){
		if (cell_==NULL) {
			report.addItem(tr("Invalid Header"),0,s);
			}
		else if (sl.size()==8) {
		layer=getLayer(sl[7]);
		pointArray pa;
		QPoint p;
		int x,y;
		x=element::round(sl[0].toInt()*scale);
		y=element::round(sl[1].toInt()*scale);
		if ((sl[6]=="LEFT")||(sl[6]=="RIGHT")){
			x-=lamdaHalf;
			}
		if ((sl[6]=="UP")||(sl[6]=="DOWN")){
			y-=lamdaHalf;
			}
		p=QPoint(x,y);
		pa<<p;
		x=element::round(sl[2].toInt()*scale);
		y=element::round(sl[3].toInt()*scale);
		if ((sl[6]=="LEFT")||(sl[6]=="RIGHT")){
			x+=lamdaHalf;
			}
		if ((sl[6]=="UP")||(sl[6]=="DOWN")){
			y+=lamdaHalf;
			}
		p=QPoint(x,y);
		pa<<p;
		element *e=cell_->addPath(pa,layer);
		e->setWidth(element::round(sl[4].toInt()*scale));
		if (sl[5]!="*") {
			cell_->addText(layer,p,sl[5]);
			}
		}else
		report.addItem(tr("Unknow entry"),3,s);}
	else if (s[0]=='V'){
		if (cell_==NULL) {
			report.addItem(tr("Invalid Header"),0,s);
			}
		else if (sl.size()==4) {
		layer=getLayer(sl[2]);
		pointArray pa;
		QPoint p=QPoint(element::round(sl[0].toInt()*scale),
			element::round(sl[1].toInt()*scale));
		pa<<p;
		cell_->addBox(element::round(sl[0].toInt()*scale)
				-lamdaHalf,element::round(sl[1].toInt()*scale)
				-lamdaHalf,lamda,lamda,layer);
		if (sl[3]!="*") {
			cell_->addText(layer,p,sl[3]);
			}
		}else
		report.addItem(tr("Unknow entry"),3,s);}
	else
		{report.addItem(tr("Unknow entry"),3,s);}
	s=ts.readLine();
  }
  f.close();

  // resolving cellrefs
  for (cellList *f =d->firstCell; f!=NULL;f=f->nextCell) {
  	if (f->thisCell!=NULL){
  		for (elementList *e=f->thisCell->firstElement;e!=NULL;e=e->nextElement){
			if (e->thisElement->isCellref()||e->thisElement->isCellrefArray()) {
				 if (e->thisElement->depend()==NULL){e->thisElement->setCellRef(d->findCell(e->thisElement->getName()));}
				 if ((e->thisElement->depend()==NULL)&&(typ==fileImport)){  //refs to before existing cells
						cellList *c=d->firstCell;
						d->firstCell=firstcellhelp;
				 		e->thisElement->setCellRef(d->findCell(e->thisElement->getName()));
						d->firstCell=c;}
				 if (e->thisElement->depend()==NULL){
				 	//add empty cells
					cellList *c;
  					c=d->addCell();
  					c->this_cell->cellName=e->thisElement->getName();
					e->thisElement->setCellRef(d->findCell(e->thisElement->getName()));
				 	//f->this_cell->deleteElement(e->this_element);
				 	//e=f->this_cell->first_element;
					report.addItem(tr("Cellref(s) can not be resolved. Empty cell added."),1,e->thisElement->getName());}
			}
			if (e==0) {break;}
			
		}
	f->thisCell->clean();
  	}
  }
  d->currentCell=d->findTopCell();
  if (d->currentCell==NULL) d->currentCell=d->firstCell->thisCell;
  if ((typ==fileImport)||(typ==fileUpdate)) {
	if (d->databaseunits!=databaseunitshelp) {
		report.addItem(tr("Databaseunits are different.Import is fitted."),3,s.setNum(d->databaseunits,'g',10));
		for (cellList *f =d->firstCell; f!=NULL;f=f->nextCell) {f->thisCell->resize(d->databaseunits/databaseunitshelp);}
		d->databaseunits=databaseunitshelp;}
		}
  if (typ==fileImport) filegeneral::import(&report,d,firstcellhelp);
  if (typ==fileUpdate) filegeneral::update(&report,d,firstcellhelp);

#ifdef printtime
  printf("ap load: %d ms\n", setup::centralTimer.elapsed());
#endif
  }
catch (QString s){
  report.addItem(tr("Aborted. "),0);
  report.addItem(s,1);
 }
  //report.showReport(); 
  QString  s=report.getReport();
  d->showReport(s,report.getLastRang());
}


 int ap::getLayer(QString s1){
		int layer=layers::findLayer(s1);
		if (layer==-1) {
				 int layerNum=1;
				 while ( layerused[layerNum]) layerNum++;
				 if (layerNum<layersMax){
				 	layers::num[layerNum].name=s1;
				 	layerused[layerNum]=true;
				 	report.addItem(tr("Add layer"),4,s1);
				 	layer=layerNum;}
				 else {
				 	layer=1;
					report.addItem(tr("unknow layer"),2,s1);
				 	}
				}
		else layerused[layer]=true;
		if (layout::debug) printf("Layer %d\n",layer);
return layer;
}


void ap::save(QString fileName,drawingField *d){
errorreport report;
report.setTitle(tr("Save of AP-File \"")+fileName+"\"");
try { 
  throw QString(tr("AP file format can not be saved. Choose an other format!"));
  QFile f( fileName );
  if ( !f.open( QIODevice::WriteOnly ) ) {
	throw QString(tr("Can not open File."));
  }
 
  QTextStream stream( &f );
  ap apClass;
  apClass.save(&stream,d,&report);
  f.close();
}
catch (QString s){
  report.addItem(tr("Aborted. "),0);
  report.addItem(s,1);
 }
  //report.showReport();   
  QString s=report.getReport();
  d->showReport(s,report.getLastRang());

}
void ap::save(QTextStream *,drawingField *, errorreport *){
  /*
  stream = streamPtr;
  reportSave = error;
  double factor=d->databaseunits*(double)100000000;
  a=1;
  b=1;
  if (factor>1) a=element::runden(factor);
  else b=element::runden(1/factor);
  cellNum=1;
  cellList *e;
  for(e=d->firstCell;e!=NULL;e=e->nextCell){
	e->thisCell->saved=false;}
  bool saved=false;
  while (!saved){
	saved=true;
	for(e=d->firstCell;e!=NULL;e=e->nextCell){
		if (e->thisCell->saved==false){
			if (!e->thisCell->dependNotSaved()){e->thisCell->saveCIF(this);}
			else{saved=false;}};
		}}
 *stream<<(QString)("E\r\n");*/
}

