/***************************************************************************
 *   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 "drc.h"
#include "drawingfield.h"
#include "widgets/selectwidget.h"
#include "bool/booleanhandler.h"
#include <qmessagebox.h>
#include "layout.h"
#include "elements/path.h"
#include "elements/text.h"
#include "general/guiworkthread.h"

#ifdef netlistutility
#endif

drc::drc()
 : QObject()
{
errorLayer=0;
//booleanTool=new booleanHandler(drawing);
reportedErrors=NULL;
}


drc::~drc()
{
}


drc::drc(drawingField *d,layout *lay){
  booleanTool=new booleanHandler(d,lay);
  errorLayer=0;
  drawing=d;
  la=lay;
  ruleName="DRC-Rule";
  result="";
  reportedErrors=NULL;
}

void drc::setRuleName(QString s){
 drawing->macroAdd("layout->drcTool->ruleName= \""+s+"\";");
 ruleName= s;
}

QString drc::getReport(){
QString r=result;
if (r.count("\n")>40){
	QStringList sl=r.split("\n");
	for (int i=sl.size()-1;i>=0;i--){
	  if (sl[i].indexOf("no errors")>0) {
		sl.removeAt(i);
		}
	}
	r=sl.join("\n");
	}
return r;
}

void drc::showReport(){
QString r=getReport();

QMessageBox::information(NULL,tr("Design Rule Checker"),r);
}

void drc::prepareCheck(){
}


void drc::completeCheck(){
}

void drc::updateGui(){
  drawing->paint();
  drawing->recountSelect();
  emit drawing->cellsChange();
  drawing->setModifyAdded();

}

void drc::reportError(QPoint p1,QPoint p2, double value){
elementList *el=new elementList;
el->nextElement=reportedErrors;
pointArray pa;
pa<<p1<<p2;
el->thisElement=new path(pa,errorLayer);
reportedErrors=el;
reportError((p1+p2)/2,value);
}

void drc::reportError(QPoint p, double value){
elementList *el=new elementList;
el->nextElement=reportedErrors;
QString s;
s.setNum(drawing->userunits*value,'g',6);
el->thisElement=new txt(errorLayer,p,s);
el->thisElement->setWidth(-15);
reportedErrors=el;
countErrors++;
}

void drc::reportErrorDeg(QPoint p, double value){
elementList *el=new elementList;
el->nextElement=reportedErrors;
QString s;
s.setNum(value,'g',4);
s+="°";
el->thisElement=new txt(errorLayer,p,s);
el->thisElement->setWidth(-15);
reportedErrors=el;
countErrors++;
}

void drc::addError(){
}


void drc::noHolesOnLayer(int layer,bool mergeBefore){
}

void drc::minimumAreaOnLayer(int layer, double areavalue ,bool mergeBefore){
}

void drc::maximumAreaOnLayer(int layer, double areavalue ,bool mergeBefore){
}

void drc::minimumPerimeterOnLayer(int layer, int perimeter ,bool mergeBefore){
}

void drc::maximumPerimeterOnLayer(int layer, int perimeter,bool mergeBefore){
}

void drc::minimumNotchOnLayer(int notchsize, int layer, bool mergeBefore){
}

void drc::angle90OnLayer(int layer,bool mergeBefore){
}

void drc::angle45OnLayer(int layer,bool mergeBefore){
}

void drc::maximumAngleOnLayer(double anglevalue, int layer, bool mergeBefore){
}

void drc::maximumDimensionOnLayer(int length,int width, int layer, bool mergeBefore){
}

void drc::minimumDimensionOnLayer(int length,int width, int layer, bool mergeBefore){
}

void drc::noElementOnLayer(int layer){
  prepareCheck();
  drawing->deselectAll();
  drawing->currentCell->selectLayer(layer);
  elementCount count=drawing->currentCell->countSelect();
  int sum=count.path+count.box+count.polygon+count.text;
  error=sum;
  drawing->currentCell->moveToLayerSelect(errorLayer);
  completeCheck();
  drawing->macroAdd("layout->drcTool->noElementOnLayer("+drawing->str(layer)+");");
}

void drc::noElementOnActiveLayer(){
  //drawing->macroAdd("layout->drcTool->ruleName= \"no Element on Layer "+drawing->str(drawing->activeLayer)+"\";");
  //ruleName= "no Element on Layer "+drawing->str(drawing->activeLayer);
  noElementOnLayer(drawing->activeLayer);
}

void drc::noPathOnLayer(int layer){
  prepareCheck();
  drawing->deselectAll();
  drawing->currentCell->selectLayer(layer);
  elementList *f;
    for (f=drawing->currentCell->firstElement;f!=NULL;f=f->nextElement) {
        if (f->thisElement!=NULL)
	    if (!f->thisElement->isPath()) f->thisElement->deselectAll();
    }
  elementCount count=drawing->currentCell->countSelect();
  int sum=count.path;
  error=sum;
  drawing->currentCell->moveToLayerSelect(errorLayer);
  completeCheck();
  drawing->macroAdd("layout->drcTool->noPathOnLayer("+drawing->str(layer)+");");
}

void drc::noPathOnActiveLayer(){
  //drawing->macroAdd("layout->drcTool->ruleName= \"no Path on Layer "+drawing->str(drawing->activeLayer)+"\";");
  //ruleName= "no Path on Layer "+drawing->str(drawing->activeLayer);
  noPathOnLayer(drawing->activeLayer);
}

void drc::noBoxOnLayer(int layer){
  prepareCheck();
  drawing->deselectAll();
  drawing->currentCell->selectLayer(layer);
  elementList *f;
  for (f=drawing->currentCell->firstElement;f!=NULL;f=f->nextElement) {
        if (f->thisElement!=NULL)
	    if (!f->thisElement->isBox()) f->thisElement->deselectAll();
    }
  elementCount count=drawing->currentCell->countSelect();
  int sum=count.box;
  error=sum;
  drawing->currentCell->moveToLayerSelect(errorLayer);
  completeCheck();
  drawing->macroAdd("layout->drcTool->noBoxOnLayer("+drawing->str(layer)+");");
}

void drc::noBoxOnActiveLayer(){
  //drawing->macroAdd("layout->drcTool->ruleName= \"no Box on Layer "+drawing->str(drawing->activeLayer)+"\";");
  //ruleName= "no Box on Layer "+drawing->str(drawing->activeLayer);
  noBoxOnLayer(drawing->activeLayer);
}

void drc::noPolygonOnLayer(int layer){
}

void drc::noPolygonOnActiveLayer(){
  //drawing->macroAdd("layout->drcTool->ruleName= \"no Polygon on Layer "+drawing->str(drawing->activeLayer)+"\";");
  //ruleName= "no Polygon on Layer "+drawing->str(drawing->activeLayer);
  noPolygonOnLayer(drawing->activeLayer);
}

void drc::noTextOnLayer(int layer){
  prepareCheck();
  drawing->deselectAll();
  drawing->currentCell->selectLayer(layer);
    elementList *f;
    for (f=drawing->currentCell->firstElement;f!=NULL;f=f->nextElement) {
        if (f->thisElement!=NULL)
	    if (!f->thisElement->isText()) f->thisElement->deselectAll();
    }
  elementCount count=drawing->currentCell->countSelect();
  int sum=count.text;
  error=sum;
  drawing->currentCell->moveToLayerSelect(errorLayer);
  completeCheck();
  drawing->macroAdd("layout->drcTool->noTextOnLayer("+drawing->str(layer)+");");
}

void drc::noTextOnActiveLayer(){
  //drawing->macroAdd("layout->drcTool->ruleName= \"no Text on Layer "+drawing->str(drawing->activeLayer)+"\";");
  //ruleName= "no Text on Layer "+drawing->str(drawing->activeLayer);
  noTextOnLayer(drawing->activeLayer);
}



void drc::minimumSize(int distance,int layer,bool mergeBefore, bool sharpAngles){
}

void drc::overlapingElements(int layer){
}

void drc::minimumElementDistance(int distance,int layer,bool mergeBefore){
}

void drc::minimumDistance(int distance,int layer1, int layer2){
#ifdef netlistutility
#endif
}

void drc::minimumDistanceOrOverlap(int distance,int layer1, int layer2,bool mode){
}


void drc::inside(int distance,int insideLayer, int layer1, int layer2, int layer3){
}

void drc::minimumEnclosure(int distance,int layer1,int layer2){
}


void drc::minimumOverlap(int distance,int layer1, int layer2){
}



void drc::layerCombination(int layer1,int layer2, int layer3,int layer4, int layer5){
}



void drc::minimumOverlapDistance(int distance,int layer1,int layer2){
}


void drc::onGrid(int size,int layer){
}

void drc::noCircleOnLayer(int layer){
}

void drc::onlyCircleOnLayer(int layer){
}

void drc::minimumElementDistanceOnActiveLayer(int distance){  
//drawing->macroAdd("layout->drcTool->ruleName= \"Minimum Element Distance on Layer "+drawing->str(drawing->activeLayer)+"\";");
 // ruleName= "Minimum Element Distance on Layer "+drawing->str(drawing->activeLayer);
  minimumElementDistance(distance,drawing->activeLayer);
}

void drc::overlapingElementsOnActiveLayer(){
 // drawing->macroAdd("layout->drcTool->ruleName= \"Overlaping Elements on Layer "+drawing->str(drawing->activeLayer)+"\";");
 // ruleName= "Overlaping Elements on Layer "+drawing->str(drawing->activeLayer);
  overlapingElements(drawing->activeLayer);
}


void drc::noCircleOnActiveLayer(){
  noCircleOnLayer(drawing->activeLayer);
}

void drc::onlyCircleOnActiveLayer(){
  onlyCircleOnLayer(drawing->activeLayer);
}


void drc::noCircleOnActiveLayerGui(){
if ( drawing->mutexChangeGuiTryLock()){
	drawing->macroAdd("layout->drcTool->ruleName= \"no Circle on Layer "+drawing->str(drawing->activeLayer)+"\";");
	ruleName= "no Circle on Layer "+drawing->str(drawing->activeLayer);
	noCircleOnActiveLayer();
	drawing->mutexChangeUnlock();
	updateGui();
	}
}

void drc::onlyCircleOnActiveLayerGui(){
if ( drawing->mutexChangeGuiTryLock()){
	drawing->macroAdd("layout->drcTool->ruleName= \"only Circle on Layer "+drawing->str(drawing->activeLayer)+"\";");
	ruleName= "only Circle on Layer "+drawing->str(drawing->activeLayer);
	onlyCircleOnActiveLayer();
	drawing->mutexChangeUnlock();
	updateGui();
	}
}


void drc::noElementOnActiveLayerGui(){
if ( drawing->mutexChangeGuiTryLock()){
	drawing->macroAdd("layout->drcTool->ruleName= \"no Element on Layer "+drawing->str(drawing->activeLayer)+"\";");
	ruleName= "no Element on Layer "+drawing->str(drawing->activeLayer);
	noElementOnActiveLayer();
	drawing->mutexChangeUnlock();
	updateGui();
	}
}

void drc::noPathOnActiveLayerGui(){
if ( drawing->mutexChangeGuiTryLock()){
	drawing->macroAdd("layout->drcTool->ruleName= \"no Path on Layer "+drawing->str(drawing->activeLayer)+"\";");
	ruleName= "no Path on Layer "+drawing->str(drawing->activeLayer);
	noPathOnActiveLayer();
	drawing->mutexChangeUnlock();
	updateGui();
	}
}

void drc::noBoxOnActiveLayerGui(){
if ( drawing->mutexChangeGuiTryLock()){
	drawing->macroAdd("layout->drcTool->ruleName= \"no Box on Layer "+drawing->str(drawing->activeLayer)+"\";");
        ruleName= "no Box on Layer "+drawing->str(drawing->activeLayer);
	noBoxOnActiveLayer();
	drawing->mutexChangeUnlock();
	updateGui();
	}
}

void drc::noPolygonOnActiveLayerGui(){
if ( drawing->mutexChangeGuiTryLock()){
	drawing->macroAdd("layout->drcTool->ruleName= \"no Polygon on Layer "+drawing->str(drawing->activeLayer)+"\";");
	ruleName= "no Polygon on Layer "+drawing->str(drawing->activeLayer);
	noPolygonOnActiveLayer();
	drawing->mutexChangeUnlock();
	updateGui();
	}
}

void drc::noTextOnActiveLayerGui(){
if ( drawing->mutexChangeGuiTryLock()){
	drawing->macroAdd("layout->drcTool->ruleName= \"no Text on Layer "+drawing->str(drawing->activeLayer)+"\";");
	ruleName= "no Text on Layer "+drawing->str(drawing->activeLayer);
	noTextOnActiveLayer();
	drawing->mutexChangeUnlock();
	}
}

void drc::overlapingElementsOnActiveLayerGui(){
drawing->macroAdd("layout->drcTool->ruleName= \"Overlaping Elements on Layer "+drawing->str(drawing->activeLayer)+"\";");
ruleName= "Overlaping Elements on Layer "+drawing->str(drawing->activeLayer);
if (la->isGuiThread()){
  		la->workThread->startOperation("drcOverlapingElementsOnActiveLayer");
 	}
	else {
	if ( drawing->mutexChangeGuiTryLock()){
		overlapingElements(drawing->activeLayer);
		drawing->mutexChangeUnlock();
		updateGui();
		}
	}
}
