/***************************************************************************
 *   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 "electromask.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 <QFileInfo>
#include "general/errorreport.h"
#include "layout.h"
#include "macro/macro.h"
#include "filedialog.h"
#include <QDir>


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


electromask::~electromask()
{
}


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



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

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

void electromask::load(QString fileName,drawingField *d, fileOpenType typ){
 
  if (typ==fileImport) {
  	report.setTitle(tr("Import of Electromask-File \"")+fileName+"\"");}
  else  if (typ==fileOpen){
	report.setTitle(tr("Open of Electromask-File \"")+fileName+"\"");}
  else  if (typ==fileUpdate){
	report.setTitle(tr("Update with Elekromask-File \"")+fileName+"\"");}
try { 
#ifdef printtime
  setup::centralTimer.start();
#endif
  //cellList *firstcellhelp=d->firstCell;
  //double databaseunitshelp=d->databaseunits;
  QFile f( fileName );
  if ( !f.open( QIODevice::ReadOnly ) )
	  throw QString(tr("Can not open File: %1").arg(fileName));
  /*if ((typ==fileImport)||(typ==fileUpdate)) {
	d->firstCell=NULL;
  }*/
  QDataStream ds( &f );
  QString s="";
  cellList *cell_list=NULL;
  cell *cell_=NULL;
  if (typ==fileOpen){
	cell_list=d->addCell();
	cell_=cell_list->thisCell;
	d->currentCell=cell_;
  }
  else {
	cell_=d->currentCell;
	  
  }
  int layer=d->activeLayer;
  if ((typ==fileUpdate)){
	cell_->deselectAll();
	cell_->selectLayer(layer);
	cell_->deleteSelect();
  }
//  databaseunits=d->databaseunits;
  

  int x=0,y=0,h=0,w=0;
  double a=0.0;
  bool ende=false;
  quint8 val; 
  bool ebcdic=true;
  double factor=0.000001/d->databaseunits;
  while (!ds.atEnd()&&(ende==false)){
  ds>>val;
  
  if (ebcdic){
    //printf("%d %d\n",val/16,val%16);
    switch (val){
      case 0x00 : s+="\n"; break;
      case 0x0A : s+="\n"; break;
      case 0x0D : s+="\n"; break;
      case 0x15 : s+="\n"; break;
      case 0x16 : s+="\n"; break;
      case 0x40 : s+=" "; break;
      case 0x4A : s+="["; break;
      case 0x4B : s+="."; break;
      case 0x5A : s+="]"; break;
      case 0x5B : s+="$"; break;
      case 0x5E : s+=";"; break;
      case 0x60 : s+="-"; break;
      case 0x6A : s+="|"; break;
      case 0x6B : s+=","; break;
      case 0x6D : s+="_"; break;
      case 0x7A : s+=":"; break;
      case 0x7F : s+="\""; break;
      case 0xBA : s+="["; break;
      case 0xBB : s+="]"; break;
      case 0xBF : s+="*"; break;
      case 0xC1 : s+="A"; break;
      case 0xC2 : s+="B"; break;
      case 0xC3 : s+="C"; break;
      case 0xC4 : s+="D"; break;
      case 0xC5 : s+="E"; break;
      case 0xC6 : s+="F"; break;
      case 0xC7 : s+="G"; break;
      case 0xC8 : s+="H"; break;
      case 0xC9 : s+="I"; break;
      case 0xCA : s+=" "; break;
      case 0xD1 : s+="J"; break;
      case 0xD2 : s+="K"; break;
      case 0xD3 : s+="L"; break;
      case 0xD4 : s+="M"; break;
      case 0xD5 : s+="N"; break;
      case 0xD6 : s+="O"; break;
      case 0xD7 : s+="P"; break;
      case 0xD8 : s+="Q"; break;
      case 0xD9 : s+="R"; break;
      case 0xE2 : s+="S"; break;
      case 0xE3 : s+="T"; break;
      case 0xE4 : s+="U"; break;
      case 0xE5 : s+="V"; break;
      case 0xE6 : s+="W"; break;
      case 0xE7 : s+="X"; break;
      case 0xE8 : s+="Y"; break;
      case 0xE9 : s+="Z"; break;
      case 0xF0 : s+="0"; break;
      case 0xF1 : s+="1"; break;
      case 0xF2 : s+="2"; break;
      case 0xF3 : s+="3"; break;
      case 0xF4 : s+="4"; break;
      case 0xF5 : s+="5"; break;
      case 0xF6 : s+="6"; break;
      case 0xF7 : s+="7"; break;
      case 0xF8 : s+="8"; break;
      case 0xF9 : s+="9"; break;
      default: //printf("%d %d\n",val/16,val%16);
        if (val<130){
        ebcdic=false;
	s.append(QChar::fromAscii(val));
	report.addItem(tr("use ascii encoding"),4);
	}
	else s+="?"; break;
    }
    
  }
  else 
    s.append(QChar::fromAscii(val));
 
	//   ende=true;
  //printf("\n-> (%s)\n",s.toAscii().data());
  //printf("%s",s.right(1).toAscii().data());
  if (s.right(1)=="\n")s="";
  if (s.right(1)==";"){
    if (s.left(1)=="\"") s="";
    else if (s.length()>2){
      s.remove(";");
      if (layout::debug) printf("-> %s\n",s.toAscii().data());
      while (s.size()>1){
        int pos=s.indexOf(QRegExp("[AHWXY]"),2);
	QString part=s;
	if (pos>1){
	  part=s.left(pos);
	  s=s.mid(pos);
	}
	int num=element::runden(factor*part.mid(1).toInt());
	if (part.left(1)=="X") x=num;
	if (part.left(1)=="Y") y=num;
	if (part.left(1)=="H") h=num;
	if (part.left(1)=="W") w=num;
	if (part.left(1)=="A") a=0.1*part.mid(1).toInt();
	//printf("part %s\n",part.toAscii().data());
	if (pos<0) s="";
      }
	if (layout::debug)
	  printf("X %d Y %d W %d H %d A %f\n",x,y,w,h,a);
	
	if (a==0){
	  cell_->addBox(x-w/2,y-h/2,w,h,layer);
	}else {
	  pointArray pa;
	  int dwx=element::runden(cos(a/360*2*M_PI)*w/2);
	  int dhx=element::runden(cos(a/360*2*M_PI)*h/2);
	  int dhy=element::runden(sin(a/360*2*M_PI)*h/2);
	  int dwy=element::runden(sin(a/360*2*M_PI)*w/2);
	  pa<<QPoint(x+dwx+dhy,y-dhx+dwy);
	  pa<<QPoint(x+dwx-dhy,y+dhx+dwy);
	  pa<<QPoint(x-dwx-dhy,y+dhx-dwy);
	  pa<<QPoint(x-dwx+dhy,y-dhx-dwy);
	  pa<<QPoint(x+dwx+dhy,y-dhx+dwy);
	  cell_->addPolygon(pa,layer);
	}
      
    }
    s="";
  }
  //ts.atEnd()
  }
  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;
					//printf("addCell %s\n",e->thisElement->getName().toAscii().data());
  					c=d->addCell();
  					c->this_cell->cellName=e->thisElement->getName();
					e->thisElement->setCellRef(d->findCell(e->thisElement->getName()));
					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("electromask 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());

}


void electromask::save(QString fileName,drawingField *d){
errorreport report;
report.setTitle(tr("Save of Electromask-File \"")+fileName+"\"");
try { 
  throw ("Not supported!");
}
catch (QString s){
  report.addItem(tr("Aborted. "),0);
  report.addItem(s,1);
 }
  //report.showReport();   
  QString s=report.getReport();
  d->showReport(s,report.getLastRang());

}

