/***************************************************************************
 *   Copyright (C) 2009 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 <QMenuBar>
#include <QWhatsThis>
#include <QMessageBox>
#include <QDesktopServices>
#include "mainwindow.h"
#include "defines.h"
#include "dialog/helpwindow.h"
#include "general/setup.h"
#include "general/lastopen.h"
#include <QAbstractButton>
#include <QPushButton>
#include <QDir>
#include "macro/macro.h"
#include "layout.h"
#ifdef FULL_VERSION
#include "license/license.h"
#include "license/licenseinput.h"
#endif
//bool getDebugFlag();

helpWindow *mainWindow::helpwindow=NULL;


mainWindow::mainWindow(): QMainWindow()
{

    setAttribute(Qt::WA_DeleteOnClose);
    setup::init();
    //setup::loadEarlySettings();
    actionNext=0;
    multiToolButtonNext=0;
    singleToolButtonNext=0;
    toolBarNext=-1;
    menuNext=0;
    undoButton=NULL;
    undoAction=NULL;
    redoButton=NULL;
    redoAction=NULL;
    lastFiles=NULL;
    if (helpwindow==NULL) helpwindow=new helpWindow();
    printer=NULL;
    //printer = new QPrinter(QPrinter::HighResolution);
    setWindowIcon(QIcon(":/layoutIcon"));
    macroList=NULL;
    QString s=QString("Main");
    menuList=NULL;
    mainMenu=new menus(NULL,&s,&menuList,this);
    mainmenu=mainMenu->menu;
    lastmode=-1;
    className="";
}


mainWindow::~mainWindow()
{ 
    undoButton=NULL;
    undoAction=NULL;
    redoButton=NULL;
    redoAction=NULL;
    if (printer!=NULL) delete printer;
}

QMenu *mainWindow::getMenu(QString name){
  QString menuName="Main"+className+"/"+name;
  menus *m=menus::findMenu(&menuName,menuList);
  if (m!=NULL) return m->menu;
  int pos=name.lastIndexOf("/");
  if (pos<0){
    QString menuName="Main"+className+"/"+name;
    layoutMenu[menuNext]= menus::addMenu(mainMenu,&name,&menuList,this);
    layoutMenu[menuNext]->setTitle("&"+name);
    menuBar()->addMenu(layoutMenu[menuNext]);
    menuNext++;
    return layoutMenu[menuNext-1];
  }
  QString s=name.mid(pos);
  name=name.left(pos-1);
  menuName="Main"+className+"/"+name;
  QMenu * newMenu = menus::addMenu(menus::findMenu(&menuName,menuList),&s,&menuList,this);
  newMenu->setTitle(s);
  return newMenu;
}

void mainWindow::addMenu(QString name, QList<int> list){
	QString s=name;
	//printf("Menu %s add\n",s.toAscii().data());
	int nextMenuNum=menuNext+1;
	// add to layer menu or new menu
	if (name==""){
		nextMenuNum=menuNext+1;
		menuNext=list.at(0);
		name="Layer";
		}
	else {
		layoutMenu[menuNext]= menus::addMenu(mainMenu,&s,&menuList,this);
    		layoutMenu[menuNext]->setTitle("&"+name);
		if ((list.at(0)<0)&&(menuNext+list.at(0)>=0)){
			menuBar()->insertMenu(layoutMenu[menuNext+list.at(0)]->menuAction(),layoutMenu[menuNext]);
		}
		else
	   		 menuBar()->addMenu(layoutMenu[menuNext]);
         	mainmenu->addMenu(layoutMenu[menuNext]);
		}
	for (int i = 0; i < list.size(); ++i) {
		QString textLabel;
		QObject *receiver;
		const char * slot;
		helpText helptext;
		//printf("%d\n",list.at(i));
		if (list.at(i)<0) {}
		else if (list.at(i)==0) {
			layoutMenu[menuNext]->addSeparator();
		} else if (list.at(i)<50){
			int countItems=list.at(i);
			i++;
			QString s="";
			QIcon icon;
			getFunctionInfo(list.at(i),&textLabel,&receiver,&slot,&helptext);
		    	s=helpwindow->getMenuname(helptext);
			icon=helpwindow->getIcon(helptext);
			switch(list.at(i)){
				case 13000:
					s=tr("Special Select");
					icon=QIcon(":/specialselectIcon");
					break;
				case 13001:
					s=tr("Netlist Tools");
					icon=QIcon(":/icons/netlisticon.png");
					break;
				case 1065:
					s=tr("Adjust Utilities");
					break;
				case 1135:
					s=tr("Align Utilities");
					break;
				case 1075:
					s=tr("Boolean Tools");
					break;
				case 1062:
					s=tr("Circular Utilities");
					break;
				case 1077:
					s=tr("Snapping");
					break;
				case 1144:
					s=tr("Clipboard");
					break;
				case 1095:
					s=tr("Convert Utilities");
					break;
				case 1122:
					s=tr("Global Tools");
					break;
				case 1116:
					s=tr("Macros");
					icon=QIcon(":/macroIcon");
					break;
				case 1068:
					s=tr("Measurement Tools");
					break;
				case 1101:
					s=tr("DRC Tools");
					break;
			  	case 1248:
					s="OpenAccess";
					break;
				case 2001:
					s=tr("Layer Shortkeys");
					break;
				case 1120:
					s=tr("Technology");
					break;
				case 1193:
					s=tr("Barcodes");
					break;
				case 1154:
					s=tr("3D View");
					break;
			}
			QString menuName="Main"+className+"/"+name;
            		QMenu * newMenu = menus::addMenu(menus::findMenu(&menuName,menuList),&s,&menuList,this);
            		newMenu->setTitle(s);
            		if (setup::showMenuIcons) newMenu->setIcon(icon);
            		layoutMenu[menuNext]->addMenu(newMenu);
			for (int k=0;k<countItems;k++){
				i++;
				if (list.at(i)==0) {newMenu->addSeparator();}
				else {
				getFunctionInfo(list.at(i),&textLabel,&receiver,&slot,&helptext);
				textLabel=helpwindow->getMenuname(helptext);
				QKeySequence ks=helpwindow->getShortKey(helptext);
				if (className=="textedit") ks=QKeySequence();
				if (setup::showMenuIcons)
					action[actionNext]=newMenu->addAction(helpwindow->getIcon(helptext), "&"+textLabel, receiver, slot,ks);
				else
 					action[actionNext]=newMenu->addAction("&"+textLabel, receiver, slot,ks);
				action[actionNext]->setWhatsThis( helpwindow->getWhatsthis(helptext));
				actionNext++;}
			}
		}
		else if (list.at(i)==1148) {
			getFunctionInfo(list.at(i),&textLabel,&receiver,&slot,&helptext);
			textLabel=helpwindow->getMenuname(helptext);
			action[actionNext]=QWhatsThis::createAction ( 0 );
			action[actionNext]-> setShortcut( helpwindow->getShortKey(helptext));
			action[actionNext]-> setToolTip(helpwindow->getWhatsthis(helptext));
			action[actionNext]-> setText(textLabel);
			if (!setup::showMenuIcons) action[actionNext]->setIcon(QIcon());
			layoutMenu[menuNext]->addAction(action[actionNext]);
			actionNext++;
		}
		else if (list.at(i)==12000) {
			int off=0;
			if (className=="schematic") off=20;
			else if (className=="textedit") off=40;
			layoutMenu[menuNext]->addSeparator();
            		lastFiles=new lastOpen(layoutMenu[menuNext],this,off);
           		connect(this,SIGNAL(lastFilesAdd(QString)),lastFiles,SLOT(add(QString)),Qt::QueuedConnection);
		}
		/*else if (list.at(i)==12001) {
			// outdated
			layoutMenu[menuNext]->addSeparator();
            		lastFiles=new lastOpen(layoutMenu[menuNext],this,20);
            		connect(this,SIGNAL(lastFilesAdd(QString)),lastFiles,SLOT(add(QString)),Qt::QueuedConnection);
		}*/
		else if (list.at(i)==12002) {if (layout::debug){
			layoutMenu[menuNext]->addSeparator();
    			QString s=QString("Debug");
    			QString menuName="Main"+className+"/Utilities";
			QMenu * debug = menus::addMenu(menus::findMenu(&menuName,menuList),&s,&menuList,this);
			debug->setTitle(tr("Debug"));
			layoutMenu[menuNext]->addMenu(debug);
    			action[actionNext]=debug->addAction(tr("Debug On/Off"),this,SLOT(debugOnOff()));   
			actionNext++;
			/*if (setup::showMenuIcons)
    				action[actionNext]=debug->addAction(QIcon(":/pointtoolIcon"), tr("Debug Pointtool"), drawing, SLOT(nextPoint())); 
			else 
				action[actionNext]=debug->addAction(tr("Debug Pointtool"), drawing, SLOT(nextPoint())); 
			actionNext++;*/
    			action[actionNext]=debug->addAction(tr("Clean"),this,SLOT(cleanElements())); 
			actionNext++;
			action[actionNext]=debug->addAction(tr("Show last Report"),this,SLOT(showLastReport())); 
			actionNext++;
			/*action[actionNext]=debug->addAction(tr("Abort Operation"),workThread,SLOT(abortOperation())); 
			actionNext++;*/
			layoutMenu[menuNext]->addSeparator();
		}else {

		}}	
		else if (list.at(i)==12003) {
			textLabel="Release Notes";
			//getFunctionInfo(list.at(i),&textLabel,&receiver,&slot,&helptext);
			//	helptext=nohelp;
				textLabel="Release Notes";
				if (setup::showMenuIcons)
					action[actionNext]=layoutMenu[menuNext]->addAction(QIcon(":/releaseNotesIcon"),textLabel, this,SLOT(releaseNotes()));
				else
					action[actionNext]=layoutMenu[menuNext]->addAction( textLabel, this,SLOT(releaseNotes()));
				action[actionNext]->setWhatsThis( QString("Release Notes for ")+VERSION);
				actionNext++;
		}
/*		else if (list.at(i)==12004) {
#ifdef USE_3d
    // 3d

#endif
		}*/
		else {
			getFunctionInfo(list.at(i),&textLabel,&receiver,&slot,&helptext);
			//printf("%s\n",textLabel.toAscii().data());
			textLabel=helpwindow->getMenuname(helptext);
			QKeySequence ks=helpwindow->getShortKey(helptext);
			if (className=="textedit") ks=QKeySequence();
			if (setup::showMenuIcons)
				action[actionNext]=layoutMenu[menuNext]->addAction(helpwindow->getIcon(helptext), "&"+textLabel, receiver, slot,ks);
			else
				action[actionNext]=layoutMenu[menuNext]->addAction( "&"+textLabel, receiver, slot,ks);
			action[actionNext]->setWhatsThis( helpwindow->getWhatsthis(helptext));
			if (list.at(i)==1053) {
				redoAction=action[actionNext];
				redoEnable(false);
			}
			if (list.at(i)==1052) {
				undoAction=action[actionNext];
				undoEnable(false);
			}
			actionNext++;
		}

	 }
	menuNext=nextMenuNum;
}




void mainWindow::addToolbar(QString name, QList<int> list, bool visible){
	toolBarNext++;
    toolBar[toolBarNext] = new QToolBar( name, this );
    toolBar[toolBarNext]->setWindowTitle( name );
    toolBar[toolBarNext]->setObjectName (name);
    addToolBar(Qt::TopToolBarArea,toolBar[toolBarNext]);
	int multitoolbutton=0;
	int multitoolbuttoncount=0;
	bool multitool=false;
    for (int i = 0; i < list.size(); ++i) {
		QString textLabel;
		QObject *receiver;
		const char * slot;
		helpText helptext;
		if (list.at(i)==0) {
			toolBar[toolBarNext]->addSeparator();
		} else if (list.at(i)<20){
			multitool=true;
			multitoolbutton=list.at(i);
			multitoolbuttoncount=0;
			i++;
			if (list.at(i)==10000) 
				multiButton[multiToolButtonNext]=new multiToolButton(toolBar[toolBarNext],QIcon(":/ungroupIcon"));
			else if (list.at(i)==10001) 
				multiButton[multiToolButtonNext]=new multiToolButton(toolBar[toolBarNext],QIcon(":/movelayerIcon"));
			else if (list.at(i)==10002) 
				multiButton[multiToolButtonNext]=new multiToolButton(toolBar[toolBarNext],QIcon(":/specialselectIcon"));
			else {
			getFunctionInfo(list.at(i),&textLabel,&receiver,&slot,&helptext);
			multiButton[multiToolButtonNext]=new multiToolButton(toolBar[toolBarNext],helpwindow->getIcon(helptext));
			}
			connect(this,SIGNAL(newMode(int,int)),multiButton[multiToolButtonNext],SLOT(modeChanged(int,int)));
		}
		else if (multitool) {
			getFunctionInfo(list.at(i),&textLabel,&receiver,&slot,&helptext);
			int mode=helpWindow::getMode(helptext);
			multiButton[multiToolButtonNext]->addToolButton(multitoolbuttoncount, textLabel, 
				                  receiver, slot, helptext,mode );
			multitoolbuttoncount++;
			if (multitoolbuttoncount==multitoolbutton){
				multitool=false;
				i++;
				if (list.at(i)>=0)multiButton[multiToolButtonNext]->set(list.at(i));
				multiToolButtonNext++;
			}
		}
		else if (list.at(i)==11000){
			spezialToolbar(11000);
		}
		else if (list.at(i)==11001){
			spezialToolbar(11001);
		}
		else if (list.at(i)==11002) {
			spezialToolbar(11002);
		}
		else if (list.at(i)==12004){
			spezialToolbar(12004);
		}
		else if (list.at(i)>=13000){
			spezialToolbar(list.at(i));
		}
		else {
		getFunctionInfo(list.at(i),&textLabel,&receiver,&slot,&helptext);
		switch (list.at(i)){
		case 1077:
			spezialToolbar(1077);
			break;
		case 1078:
			spezialToolbar(1078);
			break;
		case 1079:
			spezialToolbar(1079);
			break;
		case 1080:
			spezialToolbar(1080);
			break;
		case 1081:
			spezialToolbar(1081);
			break;
		case 1082:
			spezialToolbar(1082);
			break;
		default:
	       		singleButton[singleToolButtonNext] = new singleToolButton(textLabel,receiver, slot,  toolBar[toolBarNext],  helptext );
			int mode=helpWindow::getMode(helptext);
			if (mode>=0){
				singleButton[singleToolButtonNext]->setMode(mode);
				connect(this,SIGNAL(newMode(int,int)),singleButton[singleToolButtonNext],SLOT(modeChanged(int,int)));
				}
		}
		if (list.at(i)==1052) {
			undoButton=singleButton[singleToolButtonNext];
			undoEnable(false);
		}
		if (list.at(i)==1053) {
			redoButton=singleButton[singleToolButtonNext];
			redoEnable(false);
		}
	    singleToolButtonNext++;
	  }
    }
    if (!visible) {toolBar[toolBarNext]->hide();}
}

void mainWindow::about(){
QString s;
s="LayoutEditor"+(QString)(QChar(0x2122))+"\r\n";
s+="\r\n";
bool b=false;
#ifdef FULL_VERSION
b=((license::getLicensee()!=""));
#endif
#ifdef GENISYS
        s+=QString("GenISys OEM\r\n");
#endif
#ifndef GENISYS
#ifdef FULL_VERSION
switch (license::licenseLevel()){
case 0: s+="No Version\r\n";
	break;
case 1: s+="Demo Version\r\n";
	break;
case 2: s+="Viewer Version\r\n";
	break;
case 3:	s+="Basic Version\r\n";
	break;
case 4: s+="Reduced Version\r\n";
	break;
case 5: s+="Full Version\r\n";
	break;
}
#endif
#endif
#ifndef FULL_VERSION
s+="GPL-Version\r\n";
#endif
s+=QString("Build: ")+QString(VERSION)+"\r\n";
#ifdef FULL_VERSION
if (b) s+=QString("Registered for: ")+license::getLicensee()+QString("\r\n");
else s+=QString("NON COMMERCIAL USE ONLY\r\n");
#endif
#ifndef FULL_VERSION
s+=QString("BASIC FEATURES ONLY\r\n");
#endif
s+="\r\n";
s+=QChar(0xA9)+QString("2004-2009 J")+QChar(0xFC)+QString("rgen Thies");
s+="\r\n";
s+=QChar(0xA9)+QString("2009-2010 juspertor UG (haftungsbeschr")+QChar(0xE4)+QString("nkt)");
s+="\r\n\r\n";
s+=tr("Author:");
s+=" J"+(QString)(QChar(0xFC))+"rgen Thies\r\nHomepage: http://www.layouteditor.net\r\n";
s+=QString("Email: info")+"@"+"layouteditor"+".net\r\n";

if ((setup::language!="")&&(setup::language!="en")){
  s+="\r\n"+tr("'enter language' translation:");
  s+=tr("'enter your name(s) here'")+"\r\n";
}
 //  QMessageBox::about( this, tr("LayoutEditor"),s);
	QMessageBox msgBox;
	QPushButton *donateButton = msgBox.addButton(tr("Buy License"),
	QMessageBox::ActionRole);
	QPushButton *nodonateButton = msgBox.addButton(tr("OK"),
	QMessageBox::ActionRole);
	//QPushButton *abortButton = msgBox.addButton(QMessageBox::Ok);
	msgBox.setText(s);
	msgBox.setWindowTitle(tr("LayoutEditor"));
	msgBox.setIconPixmap(QPixmap(":/layoutIcon"));
	msgBox.exec();
	
	if (msgBox.clickedButton() == donateButton) {
	QUrl url;
	url=QUrl(HOMEPAGE_BUY);
	QDesktopServices::openUrl(url);
	} else if (msgBox.clickedButton() == nodonateButton) {
	}
}

void mainWindow::aboutQt(){
    QMessageBox::aboutQt( this, tr("Layout") );
}

void mainWindow::registerLicense(){
#ifdef FULL_VERSION
    licenseInput b;
    b.show();
    b.exec();
#endif
}

void mainWindow::setNewMode(int newmode){
//if (lastmode!=newmode)
	emit newMode(lastmode,newmode);
lastmode=newmode;
}


void mainWindow::showMainmenu(){
   mainmenu->exec(QCursor::pos());
}

void mainWindow::showMainmenu(QMenu *m){
   
 QAction *a=m->addMenu(mainmenu);
a->setText(tr("Main Menu"));
   //m.exec(QCursor::pos());
}

void mainWindow::updateMacros(){
#ifdef FULL_VERSION
   while (macroList!=NULL){
   	macroMenuEntry *m=macroList;
	macroList=macroList->next;
	m->menu->menu->removeAction(m->action);
	//m->menu->menu->removeItem(m->menuId);
	delete m;
   }
   addMacros();
#endif
}

void mainWindow::addMacros(){
#ifdef FULL_VERSION
   QDir d(setup::macroDirectory);
   QStringList sl;
   sl <<"*";
   QStringList l=d.entryList(sl,QDir::Dirs,QDir::Name);
   for ( QStringList::Iterator it = l.begin(); it != l.end(); ++it ) {
      if ((*it).left(1)!=QString(".")) {
           QString s1=QString(setup::macroDirectory)+QString("/")+(*it);
	   QString s2="Main"+className;
	   QString s3="";
	   if (className!="") {
		//printf("%s\n",s1.toAscii().data());
	   	if (it->contains(className))
           		addMacroTree(&s1,&s2,&s3);
		}
		else {
			if (!it->contains("schematic"))
				addMacroTree(&s1,&s2,&s3);
		}
	   }
      }    
   if (className==""){
   	QString menuname="Main"+className+"/"+tr("Utilities")+"/"+tr("Macros");
   	menus *p=menus::findMenu(&menuname,menuList);//insert menu
	l=d.entryList(sl,QDir::Files,QDir::Name);
	if (p!=NULL) 
	for ( QStringList::Iterator it = l.begin(); it != l.end(); ++it ) {
		if ((*it).left(1)!=QString(".")) {
		QString s1=setup::macroDirectory+QString("/")+(*it); //macrofilename
		QString name=tr("Noname"),help=tr("No help available.");
		if (macro::isMacro(&s1,&name,&help)){
			macroMenuEntry *m=new macroMenuEntry(&s1,&macroList, this,&name,&help,p);
			QAction *a=p->menu->addAction(name,m,SLOT(start()));
			//int id=p->menu->insertItem(tr(name.latin1()),m,SLOT(start()));
			//m->menuId=id;
			m->action=a;
			a->setWhatsThis(help );
			//p->menu->setWhatsThis( id, help );
		}
		}
	}
	}
#endif
}

void mainWindow::addMacroTree(QString *path,QString *menuName,QString *parentName){
#ifdef FULL_VERSION

  QString s=(*parentName)+QString("/")+(*menuName);
  if ((*parentName)=="") s=(*menuName);
  menus *p=menus::findMenu(&s,menuList);
 
  if (p==NULL) {
	//printf("%s ->",s.toAscii().data());
	QString s1=(*parentName)+QString("/")+(tr((*menuName).toAscii().data()));
  	if ((*parentName)=="") s=tr((*menuName).toAscii().data());
	p=menus::findMenu(&s1,menuList);
	if (p!=NULL) s=s1;
	else {
		s1=(*parentName)+QString("/")+(mainWindow::tr((*menuName).toAscii().data()));
  		if ((*parentName)=="") s=mainWindow::tr((*menuName).toAscii().data());
		p=menus::findMenu(&s1,menuList);
	}
	if (p!=NULL) s=s1;
	//printf("%s\n",s.toAscii().data());
	}
  menus *parent=menus::findMenu(parentName,menuList);
  if (p==NULL) {
  	p=new menus(p, &s,&menuList, this);
	p->menu->setTitle((*menuName));
	parent->menu->addMenu(p->menu);
	if (parent->path=="Main"+className) 
		{
		if (*menuName=="Simulation")
			menuBar()->insertMenu(layoutMenu[4]->menuAction(),p->menu);
		else
			menuBar()->addMenu(p->menu);
		
		}
	}
  QDir d(*path);
   QStringList sl;
   sl <<"*";
   QStringList l=d.entryList(sl,QDir::Dirs,QDir::Name);
   for ( QStringList::Iterator it = l.begin(); it != l.end(); ++it ) {
        if ((*it).left(1)!=QString(".")) {
           QString s1=(*path)+QString("/")+(*it);
           addMacroTree(&s1,&(*it),&s);
	   }
      }
  l=d.entryList(sl,QDir::Files,QDir::Name);
  for ( QStringList::Iterator it = l.begin(); it != l.end(); ++it ) {
        if ((*it).left(1)!=QString(".")) {
           QString s1=(*path)+QString("/")+(*it);
	   QString name=tr("Noname"),help=tr("No help available.");
	   if (macro::isMacro(&s1,&name,&help)){
	   	macroMenuEntry *m=new macroMenuEntry(&s1,&macroList, this,&name,&help,p);
		QAction *a;
		if (setup::showMenuIcons)
			a=p->menu->addAction(QIcon(":/macroIcon"),name,m,SLOT(start()));
		else
			a=p->menu->addAction(name,m,SLOT(start()));
		//int id=p->menu->insertItem(tr(name.latin1()),m,SLOT(start()));
		//m->menuId=id;
		m->action=a;
		a->setWhatsThis(help );
		//p->menu->setWhatsThis( id, help );
	   }
	   }
      }
#endif
}

 bool mainWindow::setShortcut(QString function,QString key){
 for (int i=0; i<actionNext;i++){
 	if (action[i]->text()==function){
    		action[i]->setShortcut(QKeySequence(key));
		return true;
		 }
 }
 return false;
 }

void mainWindow::callPythonFile(QString filename){
  QFile f(filename);
  if ( !f.open( QIODevice::ReadOnly ) ) return;
  QTextStream ts( &f );
  QString s=ts.readAll();
  f.close();
  callPython(s);
}
