/***************************************************************************
 *   Copyright (C) 2004, 2005 Thomas Nagy                                  *
 *   tnagy2^8@yahoo.fr                                                     *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License version 2        *
 *   as published by the Free Software Foundation (see COPYING)            *
 *                                                                         *
 *   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.                          *
 ***************************************************************************/

#include <qdir.h>
#include <qpixmap.h>
#include <qstring.h>
#include <qregexp.h>

#include <kmessagebox.h>
#include <kdebug.h>
#include <kstandarddirs.h>
#include <karchive.h>
#include <ktar.h>
#include <klocale.h>
#include <kio/job.h>
#include <kio/netaccess.h>

#include "aux.h"
#include "datastruct/DDataControl.h"
#include "datastruct/DDataItem.h"
#include "settings.h"
#include "DGenerator.h"

DGenerator::DGenerator() : QObject()
{
	m_data = NULL;
	cli=0;
}

DGenerator::DGenerator(QObject *obj) : QObject(obj)
{
	m_data = NULL;
	cli=0;
}

DGenerator::~DGenerator() { }

const QString DGenerator::identifikation()
{
	return "Error";
}

const QString DGenerator::fullName()
{
	return "Error";
}

const QString DGenerator::group()
{
	return "NoGroup";
}

const QString DGenerator::description()
{
	return "Invalid Template : Generator";
}

const QString DGenerator::quickstart()
{
	return i18n("Nothing appropriate");
}

void DGenerator::writeItem(DDataItem* item, QTextStream & /*s*/, int level)
{
	// kdWarning()<<"DGenerator::writeItem on level"<<level<<"with item"<<item<<endl;
	if (!item)
	{
		kdWarning()<<"BUG : DGenerator::writeItem (1)"<<endl;
		return;
	}

	if (level != 0 && item->Parent() == DItem::NOITEM)
	{
		kdWarning()<<"BUG : DGenerator::writeItem (2)"<<endl;
		return;
	}
}

bool DGenerator::generate(const QString &str, DDataControl* data)
{
	generating=true;

	// kdWarning()<<"kdissert is generating a document.. "<<str<<endl;
	if (!data)
	{
		// kdWarning()<<"missing data"<<endl;
		generating=false;
		return false;
	}
	m_data = data;

	QDir dir(str); // if the directory already exists, overwrite it's contents
	if (!dir.exists() && !dir.mkdir(str))
	{
		// kdWarning()<<"could not make dir"<<endl;
		KMessageBox::sorry(0, i18n("Cannot create directory %1.").arg(str));
		generating=false;
		return false;
	}

	// Write the makefile, etc
	if (! copyfiles(str) )
	{
		QString text = i18n( "Unable to copy the template files, this should not happen" );
		if (cli) kdFatal()<<text<<endl;
		else     KMessageBox::sorry( NULL, text );

		// At this point kdissert can safely remove the directory
		KIO::del(str);
		generating=false;
		return false;
	}

	// Write the pictures
	writePics(data, str);

	// Write the main document
	DDataItem *root = (DDataItem*) data->Item( data->rootID() );
	if (root)
	{
		if ( ! writeMaindoc(root, str))
		{
			QString text = i18n( "An error occurred in the document generation, please look in the directory %1" );
			if (cli) kdFatal()<<text.arg(str)<<endl;
			else     KMessageBox::sorry( NULL, text.arg(str) );
		}
	}
	else
	{
		QString text = i18n( "No root found, kdissert is unable to produce the main document" );
		if (cli) kdFatal()<<text<<endl;
		else     KMessageBox::sorry( NULL, text );

		KIO::del(str);	
	}

	generating = false;
	return true;
}

void DGenerator::writePics(DDataControl * data, QString path)
{
	KIO::NetAccess::dircopy( KURL(data->getTmpDir()->absPath()), KURL(path+"/pics/"), NULL );
}

bool DGenerator::writeMaindoc(DDataItem * /*root*/, const QString & /*path*/)
{
	kdWarning()<<"BUG: using DGenerator::writeMaindoc"<<endl;
	return false;
}

bool DGenerator::copyfiles(const QString & destdir)
{
	KTar arch(locate("data", QString("kdissert/templatedata/")+identifikation()+".tar.gz"));
	if (! arch.open(IO_ReadOnly) )
	{
		kdWarning()<<"BUG - missing template data :"<<endl;
		kdWarning()<<locate("data", QString("kdissert/templatedata/")+identifikation()+".tar.gz")<<endl;
		return false;
	}

	const KArchiveDirectory *archiveDir = arch.directory();
	QStringList lst = archiveDir->entries();

	const KArchiveEntry* entry = NULL;
	for (unsigned int i=0; i<lst.count(); i++)
	{
		entry = archiveDir->entry(lst[i]);
		if (entry->isFile())
		{
			KArchiveFile* file = (KArchiveFile*) entry;
			file->copyTo(destdir);
		}
		else if (entry->isDirectory())
		{
			KArchiveDirectory* dir = (KArchiveDirectory*) entry;
			dir->copyTo(destdir+"/"+dir->name(), true);
			//kdWarning()<<"writing directory to "<<destdir+"/"+dir->name()<<endl;
		}
	}

	return true;
}

QString DGenerator::protectCode(const QString & str)
{
	QString ret = str;

	ret.replace("\n", "\\n");
	ret.replace("\"", "\\\"");

	return ret;
}

QString DGenerator::protectTex(const QString & str)
{
	QString ret = str;

	ret.replace( "\\", "\\begin{displaymath}\\backslash\\end{displaymath}");
	ret.replace( "$", "\\$");

	ret.replace( "&", "\\&");
	ret.replace( "#", "\\#");
	ret.replace( "_", "\\_");
	ret.replace( "%", "\\%");

	ret.replace( "{", "$\\lbrace$" );
	ret.replace( "}", "$\\rbrace$");
	ret.replace( "^", "\\^{}");
	ret.replace( "~", "\\~{}" );

	//////////
	// proceed with the richtext stuff (<b>, <p> ..)

	// wipe out useless tags
	ret.replace( "<html>", QString::null);
	ret.replace( "</html>", QString::null);
	ret.replace( "</span>", QString::null);
	ret.replace( "</body>", QString::null);

	// process bulletted lists
	QRegExp rul_begin("<ul.*>");
	rul_begin.setMinimal(true);
	ret.replace( rul_begin, "\\begin{itemize}");
	ret.replace( "<li>", "\n\\item ");
	ret.replace( "</ul>", "\n\\end{itemize}\n");
	
	ret.replace( "<br />", "\n\n");
	ret.replace( "</p>", "\n\n\n");

	QRegExp rspan("<span.*>");
	rspan.setMinimal(true);
	ret.replace(rspan, QString::null);

	QRegExp rx("<head.*head>");
	rx.setMinimal(true);
	ret.replace( rx, QString::null);

	// and remove all other tags
	QRegExp rem("<.*>");
	rem.setMinimal(true);
	ret.replace( rem, QString::null);

	// comment the rest
	ret.replace( "\\&lt;=", "$\\leq$");
	ret.replace( "\\&gt;=", "$\\geq$");
	ret.replace( "\\&lt;", "$<$");
	ret.replace( "\\&gt;", "$>$");

	ret.replace( "\\&quot;", "\'");
	ret.replace( "\\&amp;", "\\&");

	ret.replace( "[", "$[$" );
	ret.replace( "]", "$]$" );

	/*kdWarning()<<"-------------------------"<<endl;
	kdWarning()<<" beginning was: "<<endl;
	kdWarning()<<str<<endl;
	
	kdWarning()<<"-------------------------"<<endl;
	kdWarning()<<ret<<endl;
	kdWarning()<<"-------------------------"<<endl;
	*/
	
	return ret;
}

QString DGenerator::commentTex(const QString & str)
{
	QString ret = str;

	ret.prepend( "% ");
	ret.replace( "\n", "\n% ");
	ret.append( "\n" );

	return ret;
}

QString DGenerator::htmlToTex(const QString &str)
{
	QString thing = str;

	thing.replace("</span>", "SPAN");
	thing.replace("<span", "SPAN<span");
	QStringList lst = QStringList::split("SPAN", thing);

	QString ret;
	QRegExp boldrx("font-weight:600.*>");
	QRegExp italicrx("italic.*>");
	QRegExp underlinerx("underline.*>");
	QRegExp toremove("<span.*>");
	toremove.setMinimal(true);

	for (unsigned int i=0; i<lst.size(); ++i)
	{
		QString txt = lst[i];
		/*kdWarning()<<"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"<<endl;
		kdWarning()<<"processing "<<endl;
		kdWarning()<<txt<<endl;
		kdWarning()<<"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"<<endl;
		*/

		if (txt.startsWith("<span"))
		{
			bool bold = false;
			bool italic = false;
			bool underline = false;

			if (txt.contains(boldrx)) bold = true;
			if (txt.contains(italicrx)) italic = true;
			if (txt.contains(underlinerx)) underline = true;

			txt.remove(toremove);

			// textbf, etc need all the text on a single line .. stypid stupid stupid
			QStringList splitnewlines=QStringList::split("\n", protectTex( txt ));
			for (unsigned int j=0; j<splitnewlines.size(); ++j)
			{
				if (j>0) ret += "\n";

				QString interm = splitnewlines[j];

				if (interm.length())
				{
					if (bold) ret += "\\textbf{";
					if (italic) ret += "\\textit{";
					if (underline) ret += "\\underline{";
				}

				ret += splitnewlines[j];

				if (interm.length())
				{
					if (bold) ret += "}";
					if (italic) ret += "}";
					if (underline) ret += "}";
				}
			}
		}
		else	
		{
			ret += protectTex( txt );
		}
	}

	return ret;
}

void DGenerator::notifyDocGenerated( const QString& url )
{
	if (!cli) emit documentGenerated( url, true );
}

QWidget* DGenerator::confWidget()
{
	return NULL;
}

QString wipeTags(const QString &str)
{
	QString ret = str;

	// add newlines
	ret.replace("</p><p>", "\n" );
	ret.replace("<br />", "\n");

	// remove all tags
	QRegExp rx("<.*>");
	rx.setMinimal(true);
	ret.replace( rx, QString::null );

	// replace characters by normal ones
	ret.replace("&quot;", "\"");
	ret.replace("&amp;", "&");
	ret.replace("&lt;", "<");
	ret.replace("&gt;", ">");

	return ret;
}

#include "DGenerator.moc"
