/***************************************************************************
 *   Copyright (C) 2005 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 "guiworkthread.h"
#include "layout.h"
#include "macro/macro.h"
#include "bool/booleanhandler.h"
#ifdef netlistutility
#include "net/netlistmodule.h"
#endif
#include "general/drc.h"
#ifdef USE_3d
#include "3d/view3dmodule.h"
#endif
guiWorkThread::guiWorkThread(layout *la)
 : QThread()
{
  l=la;
}


guiWorkThread::~guiWorkThread()
{
	if (isRunning()){
	terminate();
	wait();
   	}
}



void guiWorkThread::startOperation(QString f,QString p,QString p2,int parameterI1,int parameterI2,int parameterI3,int parameterI4,int parameterI5, bool parameterB){


     if (isRunning()) {
			emit showMessage(tr("A Operation is still running!!!"));
			//printf("%s\n",f.toAscii().data());
			return;}
    mutex.lock();
    function=f;
    parameter=p;
    parameter2=p2;
    parameterInt1=parameterI1;
    parameterInt2=parameterI2;
    parameterInt3=parameterI3;
    parameterInt4=parameterI4;
    parameterInt5=parameterI5;
    parameterBool=parameterB;
    mutex.unlock();
//#ifndef Q_OS_WIN32
 //   start(QThread::HighestPriority);
//#else
    start(QThread::InheritPriority);
//#endif

}

void guiWorkThread::abortOperation(){
  if (isRunning()){
	wait(10000);
	terminate();
   	}
}

void guiWorkThread::run(){
   QString func,para;
   mutex.lock();
   func=function;
   para=parameter;
   mutex.unlock();
   timer.start();
 if (func=="openFile"){
        if (l->drawing->mutexChangeGuiTryLock()){;
		l->choose();
		l->drawing->mutexChangeUnlock();
		emit operationIcon(":/icons/fileopen.xpm");
		emit operationTime(timer.elapsed());
		emit cellsUpdate();
		emit updateSetupLayerbutton();
		l->drawing->paint();
	}}
 else if (func=="open"){
	if (l->drawing->mutexChangeGuiTryLock()){;
		l->open(para);
		l->drawing->mutexChangeUnlock();
		emit operationIcon(":/icons/fileopen.xpm");
		emit operationTime(timer.elapsed());
		emit cellsUpdate();
		emit updateSetupLayerbutton();
		l->drawing->paint();
	}}
 else if (func=="saveFile"){
        if (l->drawing->mutexReadGuiTryLock()) {
  		l->save();
  		l->drawing->mutexReadUnlock();
		emit operationIcon(":/icons/filesave.xpm");
		emit operationTime(timer.elapsed());
  		}
	}
 else if (func=="saveAsFile"){
        if (l->drawing->mutexReadGuiTryLock()) {
  		l->saveAs();
  		l->drawing->mutexReadUnlock();
		emit operationIcon(":/icons/filesaveas.xpm");
		emit operationTime(timer.elapsed());
		}
	}
 else if (func=="importFile"){
	if (l->drawing->mutexChangeGuiTryLock()) {
  		l->chooseImport();
  		l->drawing->mutexChangeUnlock();
		emit operationIcon(":/icons/importicon.xpm");
		emit operationTime(timer.elapsed());
		emit cellsUpdate();
		emit updateSetupLayerbutton();
  		l->drawing->paint();
  		}
	}
 else if (func=="updateFile"){
	if (l->drawing->mutexChangeGuiTryLock()) {
  		l->chooseUpdate();
  		l->drawing->mutexChangeUnlock();
		emit operationIcon(":/icons/updateicon.xpm");
		emit operationTime(timer.elapsed());
		emit cellsUpdate();
		emit updateSetupLayerbutton();
  		l->drawing->paint();
  		}
	}
 else if (func=="macro"){
     if (l->drawing->mutexChangeGuiTryLock()) {
#ifdef netlistutility
	if (l->netlistTool->netMutex.tryLock()){
		l->drawing->autorepaint=false;
		bool macrorecord=l->drawing->record;
		l->drawing->record=false;
		macro m;
		errorreport error;
		QString name,s2;
		macro::isMacro(&parameter,&name,&s2);
		QString s="Executing Macro \""+name+"\" ("+parameter+").";
		error.setTitle(s);
		m.load(&parameter);
		m.setLayout(l);
		int ret=1;
		ret=m.execute(&error,parameter2);
		if (ret!=0) {error.addItem(tr("main function exit code: ")+s.setNum(ret),2);}
		QString rep=error.getReport();
		int errnum=error.getLastRang();
		l->drawing->showReport(rep,errnum);
		//error.showReport();
		l->drawing->autorepaint=true;
		emit setWindowTitle( l->filename );
		if (macrorecord) l->drawing->record=true;
		//l->drawing->macroAdd("// Execute of macro \""+parameter2+"\" ("+parameter+"). A macro cannot start another macro.");
		l->drawing->macroAdd("layout->executeMacro(\""+parameter+"\");");
		emit operationIcon(":/icons/macroexecuteicon.xpm");
		emit operationTime(timer.elapsed());
		emit recountSelect();
		l->netlistTool->netMutex.unlock();
	}
#endif
	l->drawing->mutexChangeUnlock();
	l->drawing->firstCell->paintInfoClear();
	emit updateSetupLayerbutton();
	emit cellsUpdate();
	emit updateGrid();
	emit updateGui();
	l->drawing->paint();
	l->drawing->setModifyChanged();
#ifdef USE_3d
	emit trigger3dProcessRequest();
#endif
	}
        }
 else if (func=="boolAPlusB") {
	if (l->drawing->mutexAddGuiTryLock()){
	l->booleanTool->aPlusB();
	l->drawing->mutexAddUnlock();
	emit operationIcon(":/icons/booloricon.xpm");
	emit operationTime(timer.elapsed());
	emit recountSelect();
	l->drawing->paint();
  	}
	}
 else if (func=="boolAMinusB") {
	if (l->drawing->mutexAddGuiTryLock()){
	l->booleanTool->aMinusB();
	l->drawing->mutexAddUnlock();
	emit operationIcon(":/icons/boolabicon.xpm");
	emit operationTime(timer.elapsed());
	emit recountSelect();
	l->drawing->paint();
  	}
	}
 else if (func=="boolBMinusA") {
	if (l->drawing->mutexAddGuiTryLock()){
	l->booleanTool->bMinusA();
	l->drawing->mutexAddUnlock();
	emit operationIcon(":/icons/boolbaicon.xpm");
	emit operationTime(timer.elapsed());
	emit recountSelect();
	l->drawing->paint();
  	}
	}
 else if (func=="boolAMultiB") {
	if (l->drawing->mutexAddGuiTryLock()){
	l->booleanTool->aMultiB();
	l->drawing->mutexAddUnlock();
	emit operationIcon(":/icons/boolandicon.xpm");
	emit operationTime(timer.elapsed());
	emit recountSelect();
	l->drawing->paint();
  	}
	}
 else if (func=="boolAExorB") {
	if (l->drawing->mutexAddGuiTryLock()){
	l->booleanTool->aExorB();
	l->drawing->mutexAddUnlock();
	emit operationIcon(":/icons/boolexoricon.xpm");
	emit operationTime(timer.elapsed());
	emit recountSelect();
	l->drawing->paint();
  	}
	}
 else if (func=="boolMergeSelect") {
	if (l->drawing->mutexAddGuiTryLock()){
	l->booleanTool->mergeSelect(l->drawing->activeLayer);
	l->drawing->mutexAddUnlock();
	emit operationIcon(":/icons/mergetoicon.xpm");
	emit operationTime(timer.elapsed());
	emit recountSelect();
	l->drawing->paint();
  	}
	}
 else if (func=="print") {
	if (l->drawing->mutexReadGuiTryLock()){
	l->print();
	l->drawing->mutexReadUnlock();
	emit operationIcon(":/icons/fileprint.xpm");
	emit operationTime(timer.elapsed());
  	}
	}
 else if (func=="groupStructure") {
	 if (l->drawing->mutexChangeGuiTryLock()){
  			l->drawing->prepareUndo();
  			l->drawing->groupStructure();
			l->drawing->mutexChangeUnlock();
			emit operationIcon(":/icons/groupstructureicon.xpm");
			emit operationTime(timer.elapsed());
			emit cellsUpdate();
			emit recountSelect();
  			l->drawing->paint();
  			l->drawing->setModifyChanged();
			}
	}
 else if (func=="groupGlobal") {
	 if (l->drawing->mutexChangeGuiTryLock()){
  			l->drawing->prepareUndo();
  			l->drawing->groupGlobal();
			l->drawing->mutexChangeUnlock();
			emit operationIcon(":/icons/groupglobalicon.xpm");
			emit operationTime(timer.elapsed());
			emit cellsUpdate();
			emit recountSelect();
  			l->drawing->paint();
  			l->drawing->setModifyChanged();
			}
	}
  else if (func=="buildConnect") {
        
	if (l->drawing->mutexChangeGuiTryLock()){
	emit showMessage(tr("build connectivity started"));
#ifdef netlistutility
	if (l->netlistTool->netMutex.tryLock()){
		l->netlistTool->buildConnect();
		l->netlistTool->netMutex.unlock();
		}
#endif
	emit operationIcon(":/icons/netbuildconnecticon.png");
	emit operationTime(timer.elapsed());
	emit showMessage(tr("build connectivity finished"));
	l->drawing->mutexChangeUnlock();
  	}

	}
 else if (func=="drcMinElementDistance") {
	if ( l->drawing->mutexChangeGuiTryLock()){
		l->drcTool->minimumElementDistance(parameterInt1,parameterInt2,parameterBool);
		l->drawing->mutexChangeUnlock();
		emit operationIcon(":/icons/drcminelementdisicon.xpm");
		emit operationTime(timer.elapsed());
		l->drcTool->updateGui();
	}
	}
 else if (func=="drcOverlapingElementsOnActiveLayer"){
	if ( l->drawing->mutexChangeGuiTryLock()){
		l->drcTool->overlapingElements(l->drawing->activeLayer);
		l->drawing->mutexChangeUnlock();
		emit operationIcon(":/icons/drcminovericon.xpm");
		emit operationTime(timer.elapsed());
		l->drcTool->updateGui();
		}
	}
 else if (func=="drcMinSize") {
	if ( l->drawing->mutexChangeGuiTryLock()){
		l->drcTool->minimumSize(parameterInt1,parameterInt2,parameterBool,parameterInt5?false:true);
		l->drawing->mutexChangeUnlock();
		emit operationIcon(":/icons/drcminsizeicon.xpm");
		emit operationTime(timer.elapsed());
		l->drcTool->updateGui();
	}
	}
 else if (func=="drcMinDistance") {
	if ( l->drawing->mutexChangeGuiTryLock()){
		l->drcTool->minimumDistance(parameterInt1,parameterInt2,parameterInt3);
		l->drawing->mutexChangeUnlock();
		emit operationIcon(":/icons/drcmindistanceicon.xpm");
		emit operationTime(timer.elapsed());
		l->drcTool->updateGui();
	}
	}
 else if (func=="drcMinDistanceOrOverlap") {
	if ( l->drawing->mutexChangeGuiTryLock()){
		l->drcTool->minimumDistanceOrOverlap(parameterInt1,parameterInt2,parameterInt3,parameterBool);
		l->drawing->mutexChangeUnlock();
		emit operationIcon(":/icons/drcmindistanceovericon.xpm");
		emit operationTime(timer.elapsed());
		l->drcTool->updateGui();
	}
	}
 else if (func=="drcInside") {
	if ( l->drawing->mutexChangeGuiTryLock()){
		l->drcTool->inside(parameterInt1,parameterInt2,parameterInt3,parameterInt4,parameterInt5);
		l->drawing->mutexChangeUnlock();
		emit operationIcon(":/icons/drcinsideicon.xpm");
		emit operationTime(timer.elapsed());
		l->drcTool->updateGui();
	}
	}
 else if (func=="drcMinOverlap") {
	if ( l->drawing->mutexChangeGuiTryLock()){
		l->drcTool->minimumOverlap(parameterInt1,parameterInt2,parameterInt3);
		l->drawing->mutexChangeUnlock();
		emit operationIcon(":/icons/drcminovericon.xpm");
		emit operationTime(timer.elapsed());
		l->drcTool->updateGui();
	}
	}
 else if (func=="drcLayerCombination") {
	if ( l->drawing->mutexChangeGuiTryLock()){
		l->drcTool->layerCombination(parameterInt1,parameterInt2,parameterInt3,parameterInt4,parameterInt5);
		l->drawing->mutexChangeUnlock();
		emit operationIcon(":/icons/drclayercombicon.xpm");
		emit operationTime(timer.elapsed());
		l->drcTool->updateGui();
	}
	}
 else if (func=="drcMinEnclosure") {
	if ( l->drawing->mutexChangeGuiTryLock()){
		l->drcTool->minimumEnclosure(parameterInt1,parameterInt2,parameterInt3);
		l->drawing->mutexChangeUnlock();
		emit operationIcon(":/icons/drcenclosureicon.xpm");
		emit operationTime(timer.elapsed());
		l->drcTool->updateGui();
	}
	}
 else if (func=="drcMinOverlapDistance") {
	if ( l->drawing->mutexChangeGuiTryLock()){
		l->drcTool->minimumOverlapDistance(parameterInt1,parameterInt2,parameterInt3);
		l->drawing->mutexChangeUnlock();
		emit operationIcon(":/icons/drcoverlapdisicon.xpm");
		emit operationTime(timer.elapsed());
		l->drcTool->updateGui();
	}
	}
 else if (func=="drcNoHoles") {
	if ( l->drawing->mutexChangeGuiTryLock()){
		l->drcTool->noHolesOnLayer(parameterInt1,parameterBool);
		l->drawing->mutexChangeUnlock();
		emit operationIcon(":/icons/drcnoholesicon.xpm");
		emit operationTime(timer.elapsed());
		l->drcTool->updateGui();
	}
	}
 else if (func=="drcMinNotches") {
	if ( l->drawing->mutexChangeGuiTryLock()){
		l->drcTool->minimumNotchOnLayer(parameterInt1,parameterInt2,parameterBool);
		l->drawing->mutexChangeUnlock();
		emit operationIcon(":/icons/drcminnotchesicon.xpm");
		emit operationTime(timer.elapsed());
		l->drcTool->updateGui();
	}
	}
 else if (func=="view3dExortDxf") {
	if (l->drawing->mutexReadGuiTryLock()) {
#ifdef USE_3d
			l->view3dTool->exportDXF(parameter);
#endif
			emit operationIcon(":/icons/screenshot3dicon.xpm");
			emit operationTime(timer.elapsed());
			l->drawing->mutexReadUnlock();
			}
		}
   exit(0);
}



