/***************************************************************************
 *   Copyright (C) 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 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 <qdir.h>
#include <qfile.h>
#include <qtextstream.h>
#include <qmap.h>
#include <qpixmap.h>

#include <kio/job.h>
#include <kio/netaccess.h>
#include <kzip.h>
#include <kurl.h>
#include <klocale.h>
#include <kdebug.h>
#include <ktempdir.h>
#include <kgenericfactory.h>

#include "datastruct/aux.h"
#include "datastruct/DItem.h"
#include "datastruct/DDataControl.h"
#include "datastruct/DDataItem.h"

#include "kdissOOOimpress.h"

K_EXPORT_COMPONENT_FACTORY(libkdissOOOimpress, kdissOOOimpressFactory) 
	QObject *kdissOOOimpressFactory::createObject(QObject *, const char *, const char *, const QStringList &) { return new kdissOOOimpress; }

	static const int maxpicsize = 700;
	int kdissOOOimpress::m_slidecount = 0;
	int kdissOOOimpress::m_piclocation = 0;

const QString kdissOOOimpress::identifikation()
{
	return "kdissOOOimpress";
}

const QString kdissOOOimpress::fullName()
{
	return i18n("OpenOffice.org Impress");
}

const QString kdissOOOimpress::group()
{
	return "OpenOffice.org";
}

const QString kdissOOOimpress::description()
{
	return i18n("This template generates a simple OpenOffice.org presentation that can be viewed using any OpenOffice.org file format reader like OpenOffice.org impress or kpresenter\n"
			"Nice and interesting presentations can be obtained quickly from mindmaps containing lots of pictures and illustrations"
		   );
}

const QString kdissOOOimpress::quickstart()
{
	return i18n("Go into the directory created and open the .sxi file generated with ooimpress or kpresenter\n"
			"The picture positioning heuristic is not perfect, so you may have to move some of them\n"
		   );
}

void outputPix(DDataItem* item, QTextStream & s)
{
	if (item->m_pix.isNull())
		return;

	int width = item->m_pix.width();
	int height = item->m_pix.height();

	int newwidth = width;
	int newheight = width;

	if (width > maxpicsize)
	{
		newwidth = maxpicsize;
		newheight = height*newwidth/width;
	}
	else if (height > maxpicsize)
	{
		newheight = maxpicsize;
		newwidth = width*newheight/height;
	}

	// TODO : there is no cation for the picture
	s<<"<draw:image draw:style-name=\"gr1\" draw:text-style-name=\"P5\" draw:layer=\"layout\" svg:width=\""<<newwidth<<"pt\" svg:height=\""<<newheight<<"pt\" svg:x=\"22.512cm\" svg:y=\""<<kdissOOOimpress::m_piclocation<<"cm\" xlink:href=\"#Pictures/"<<item->m_picfilename<<"\" xlink:type=\"simple\" xlink:show=\"embed\" xlink:actuate=\"onLoad\"/>\n";

	// FIXME do not put all pictures at the same location .. 
	kdissOOOimpress::m_piclocation += 1;
}

void outputURL(DDataItem* item, QTextStream & s)
{
	// FIXME : url goes nowhere .. information loss
	for (unsigned int i=0; i<item->m_urllist.count(); i++)
	{
		QString url = item->m_urllist[i].m_url;
		QString caption = item->m_urllist[i].m_caption;

		if (!caption.length()) caption = url;

		s<<"<text:p text:style-name=\"Standard\">";
		s<<"<text:a xlink:type=\"simple\" xlink:href=\"";
		s<<url;
		s<<"\">"<<caption<<"</text:a>\n";
		s<<"</text:p>\n";
	}
}

void outputComment(DDataItem* item, QTextStream & s)
{
	if (item->m_comment.length()>0)
		s<<"<!--"<<item->m_comment<<"-->\n";
}

void printItem(DDataItem* item, QTextStream & s)
{
	s<<"<p>\n";
	s<<DDataItem::protectXML( wipeTags(item->m_text) );
	s<<"\n</p>\n";

	outputPix(item, s);
	outputURL(item, s);
	outputComment(item, s);
}

void kdissOOOimpress::writeDownPics(DDataItem* item, QTextStream & s)
{
	outputPix(item, s);
	if (item->countChildren() > 0)
	{
		for (int i = 0; i<item->countChildren(); i++)
			writeDownPics((DDataItem*) m_data->Item(item->childNum(i)), s);
	}
}

void kdissOOOimpress::outputData(DDataItem* item, QTextStream & s, int level)
{
        // links
        for (unsigned int i=0; i<item->m_urllist.count(); i++)
        {
                QString url = item->m_urllist[i].m_url;
                QString caption = item->m_urllist[i].m_caption;

                if (!caption.length()) caption = url;

                s<<"<text:p text:style-name=\"Standard\">";
                s<<"<text:a xlink:type=\"simple\" xlink:href=\"";
                s<<url;
                s<<"\">"<<caption<<"</text:a>\n";
                s<<"</text:p>\n";
        }

	// print the comment
	if (item->m_comment.length()>0)
	{
		s<<"<text:p text:style-name=\"P67\">";
		s<<DDataItem::protectXML(item->m_comment);
		s<<"</text:p>\n";
	}

	// process the picture
	if (!item->m_pix.isNull())
	{
		s<<"<text:p text:style-name=\"P"<<level<<"\">\n";
		s<<"<draw:text-box draw:style-name=\"fr1\" draw:name=\"Cadre1\" text:anchor-type=\"paragraph\" svg:x=\"1.48cm\" svg:y=\"0.226cm\" svg:width=\"5.606cm\" fo:min-height=\"3.605cm\" draw:z-index=\"0\">\n";

		s<<"<text:p text:style-name=\"Illustration\">\n";

		// TODO : set the size of the picture ..
		s<<"<draw:image draw:style-name=\"fr2\" draw:name=\"Image1\" text:anchor-type=\"paragraph\" svg:x=\"0.004cm\" svg:y=\"0.002cm\" svg:width=\"5.606cm\" style:rel-width=\"100%\" svg:height=\"3.605cm\" style:rel-height=\"scale\" draw:z-index=\"1\" xlink:href=\""<<"#Pictures/"<<item->m_picfilename<<"\" xlink:type=\"simple\" xlink:show=\"embed\" xlink:actuate=\"onLoad\"/>Illustration <text:sequence text:ref-name=\"refIllustration0\" text:name=\"Illustration\" text:formula=\"Illustration+1\" style:num-format=\"1\">1</text:sequence>: "<<DDataItem::protectXML(item->m_piccaption)<<"</text:p>";

		s<<"</draw:text-box>\n";
		s<<"</text:p>\n";
	}	
}

void kdissOOOimpress::writeCompleteSlide(DDataItem* item, QTextStream & s)
{
	m_slidecount++;
	m_piclocation = 1;
	s<<"<draw:page draw:name=\""<<i18n("slide %1").arg(m_slidecount)<<"\" draw:style-name=\"dp1\" draw:id=\"2\" draw:master-page-name=\"lyt-cool\" presentation:presentation-page-layout-name=\"AL2T1\">\n";
	s<<"<draw:text-box presentation:style-name=\"pr4\" draw:text-style-name=\"P4\" draw:layer=\"layout\" svg:width=\"23.912cm\" svg:height=\"3.508cm\" svg:x=\"2.058cm\" svg:y=\"1.543cm\" draw:corner-radius=\"0.032cm\" presentation:class=\"title\">\n";
	s<<"<text:p text:style-name=\"P4\">"<<DDataItem::protectXML(item->m_summary)<<"</text:p>\n";
	s<<"</draw:text-box><draw:text-box presentation:style-name=\"pr5\" draw:text-style-name=\"P6\" draw:layer=\"layout\" svg:width=\"23.549cm\" svg:height=\"13.232cm\" svg:x=\"3.023cm\" svg:y=\"6.178cm\" draw:corner-radius=\"0.032cm\" presentation:class=\"outline\" presentation:user-transformed=\"true\">\n";

	if (item->countChildren() > 0)
	{
		for (int i = 0; i<item->countChildren(); i++)
			writeBullet((DDataItem*) m_data->Item(item->childNum(i)), s, 1);
	}

	s<<"</draw:text-box><presentation:notes>\n";
	s<<"<draw:page-thumbnail draw:style-name=\"gr1\" draw:layer=\"layout\" svg:width=\"13.706cm\" svg:height=\"10.28cm\" svg:x=\"3.647cm\" svg:y=\"2.853cm\" draw:page-number=\"2\"/>\n";
	s<<"<draw:text-box presentation:style-name=\"pr3\" draw:text-style-name=\"P1\" draw:layer=\"layout\" svg:width=\"14.518cm\" svg:height=\"11.411cm\" svg:x=\"3.249cm\" svg:y=\"14.13cm\" draw:corner-radius=\"0.002cm\" presentation:class=\"notes\" presentation:placeholder=\"true\"/>\n";
	s<<"</presentation:notes>\n";
	writeDownPics(item, s);
	s<<"</draw:page>\n";
}

void kdissOOOimpress::writeBullet(DDataItem* item, QTextStream & s, int level)
{
	int val=0;
	if (level > 9)
	{
		kdWarning()<<"insanity detector found something wrong .. kdissOOOimpress::writeBullet"<<endl;
		return;
	}

	s<<"<text:unordered-list text:style-name=\"L4\">\n";
	val = level;
	while (val > 0)
	{
		val--;
		s<<"<text:list-item>\n";
		s<<"<text:unordered-list>\n";
	}
	s<<"<text:list-item>\n";
	s<<"<text:p text:style-name=\"P"<<QString::number(level+4)<<"\">"<<DDataItem::protectXML(item->m_summary)<<"</text:p>\n";
	s<<"</text:list-item>\n";
	val = level;
	while (val > 0)
	{
		val--;
		s<<"</text:unordered-list>\n";
		s<<"</text:list-item>\n";
	}
	s<<"</text:unordered-list>\n";

	if (item->countChildren() > 0)
	{
		for (int i = 0; i<item->countChildren(); i++)
			writeBullet((DDataItem*) m_data->Item(item->childNum(i)), s, level+1);
	}
}

void kdissOOOimpress::writeItem(DDataItem* item, QTextStream & s, int level)
{
	DGenerator::writeItem(item, s, level);
	if (item->countFamily() > 8)
	{
		m_slidecount++;
		m_piclocation = 1;

		s<<"<draw:page draw:name=\""<<i18n("slide %1").arg(m_slidecount)<<"\" draw:style-name=\"dp1\" draw:id=\"2\" draw:master-page-name=\"lyt-cool\" presentation:presentation-page-layout-name=\"AL2T1\">\n";
		s<<"<draw:text-box presentation:style-name=\"pr4\" draw:text-style-name=\"P4\" draw:layer=\"layout\" svg:width=\"23.912cm\" svg:height=\"3.508cm\" svg:x=\"2.058cm\" svg:y=\"1.543cm\" draw:corner-radius=\"0.032cm\" presentation:class=\"title\">\n";
		s<<"<text:p text:style-name=\"P5\">"<<DDataItem::protectXML(item->m_summary)<<"</text:p>\n";
		s<<"</draw:text-box><draw:text-box presentation:style-name=\"pr5\" draw:text-style-name=\"P6\" draw:layer=\"layout\" svg:width=\"23.549cm\" svg:height=\"13.232cm\" svg:x=\"3.023cm\" svg:y=\"6.178cm\" draw:corner-radius=\"0.032cm\" presentation:class=\"outline\" presentation:user-transformed=\"true\">\n";
		//s<<"<text:unordered-list text:style-name=\"L4\">\n";
		s<<"<text:p text:style-name=\"P"<<QString::number(7)<<"\">"<<DDataItem::protectXML( wipeTags(item->m_text))<<"</text:p>\n";
		//s<<"</text:unordered-list>\n";
		s<<"</draw:text-box><presentation:notes>\n";

		outputPix(item, s);

		s<<"<draw:page-thumbnail draw:style-name=\"gr1\" draw:layer=\"layout\" svg:width=\"13.706cm\" svg:height=\"10.28cm\" svg:x=\"3.647cm\" svg:y=\"2.853cm\" draw:page-number=\"2\"/>\n";
		s<<"<draw:text-box presentation:style-name=\"pr3\" draw:text-style-name=\"P1\" draw:layer=\"layout\" svg:width=\"14.518cm\" svg:height=\"11.411cm\" svg:x=\"3.249cm\" svg:y=\"14.13cm\" draw:corner-radius=\"0.002cm\" presentation:class=\"notes\" presentation:placeholder=\"true\"/>\n";
		s<<"</presentation:notes>\n";
		s<<"</draw:page>\n";

		for (int i = 0; i<item->countChildren(); i++)
		{
			writeCompleteSlide((DDataItem*) m_data->Item(item->childNum(i)), s);
		}
	}
	else
	{
		writeCompleteSlide(item, s);
	}
}

void kdissOOOimpress::writeItemPic(DDataControl *data, DDataItem *item, QTextStream &m)
{
	if (!item)
		return;

	if (! item->m_pix.isNull())
	{
		if (item->m_picfilename.endsWith(".png", false))
		{
			m<<"<manifest:file-entry manifest:media-type=\"image/png\" manifest:full-path=\"";
			m<<"Pictures/"+item->m_picfilename;
			m<<"\"/>\n";
		}
		else if (item->m_picfilename.endsWith(".jpeg", false) || item->m_picfilename.endsWith(".jpg", false))
		{
			m<<"<manifest:file-entry manifest:media-type=\"image/jpeg\" manifest:full-path=\"";
			m<<"Pictures/"+item->m_picfilename;
			m<<"\"/>\n";
		}
		// FIXME : can't remember why ?
		//item->m_pix.save(path+"/Pictures/"+"pic-"+QString::number(data->idNum(i))+".png", "PNG");
	}

	for (int i=0; i<item->countChildren(); i++)
	{
		writeItemPic( data, (DDataItem*) data->Item(item->childNum(i)), m );
	}
}

void kdissOOOimpress::writePics(DDataControl * data, QString path)
{
	// ----------------------------------------------------
	// write the pics and process the META-INF directory

	DDataItem *root = (DDataItem*) data->Item( data->rootID() );

	// copy the pictures
	KIO::NetAccess::dircopy( KURL(data->getTmpDir()->absPath()), KURL(path+"/Pictures"), NULL );

	// proces the manifest file
	QFile manifestfile(path+"/META-INF/manifest.xml");
	if (!manifestfile.open(IO_WriteOnly | IO_Append) )
	{
		kdError()<<"could not open the manifest xml file for append :-/"<<endl;
		return;
	}

	QTextStream m(&manifestfile);
	m.setEncoding(QTextStream::UnicodeUTF8);

	// write the pictures contained in the subtree considered
	writeItemPic( data, root, m );

	// close the manifest file
	m<<"</manifest:manifest>";
	manifestfile.close();
}

bool kdissOOOimpress::writeMaindoc(DDataItem *root, const QString & path)
{
	// ----------------------------------------------------
	// process the content

	QFile textfile(path+"/content.xml");
	if (!textfile.open(IO_WriteOnly | IO_Append) )
	{
		kdWarning()<<"could not open the main xml file for append :-/"<<endl;
		return false;
	}

	QTextStream u(&textfile);
	u.setEncoding(QTextStream::UnicodeUTF8);

	// test
	//u<<"<text:p text:style-name=\"Standard\">";
	//u<<DDataItem::protectXML(root->m_summary);
	//u<<"</text:p>\n";

	/*outputPixParagraph(root, u);
	  outputURL(root, u);
	  outputComment(root, u);*/

	//u<<"<office:body>\n";

	m_piclocation = 1;
	// now the central part, with text, pictures, etc ..
	u<<"<draw:page draw:name=\""<<i18n("Title")<<"\" draw:style-name=\"dp1\" draw:id=\"1\" draw:master-page-name=\"lyt-cool\" presentation:presentation-page-layout-name=\"AL1T0\">\n";
	u<<"<draw:text-box presentation:style-name=\"pr1\" draw:text-style-name=\"P1\" draw:layer=\"layout\" svg:width=\"23.912cm\" svg:height=\"3.508cm\" svg:x=\"2.058cm\" svg:y=\"1.543cm\" draw:corner-radius=\"0.048cm\" presentation:class=\"title\">\n";
	u<<"<text:p text:style-name=\"P1\">"<<DDataItem::protectXML(root->m_summary)<<"</text:p>";
	u<<"</draw:text-box>\n";
	u<<"<draw:text-box presentation:style-name=\"pr2\" draw:text-style-name=\"P3\" draw:layer=\"layout\" svg:width=\"23.549cm\" svg:height=\"13.232cm\" svg:x=\"3.023cm\" svg:y=\"6.178cm\" draw:corner-radius=\"0.048cm\" presentation:class=\"subtitle\" presentation:user-transformed=\"true\">\n";
	u<<"<text:p text:style-name=\"P6\">"<<DDataItem::protectXML( wipeTags(root->m_text) )<<"</text:p><text:p text:style-name=\"P2\"/>\n";
	u<<"</draw:text-box>\n";

	outputPix(root, u);

	u<<"<presentation:notes>\n";
	u<<"<draw:page-thumbnail draw:style-name=\"gr1\" draw:layer=\"layout\" svg:width=\"13.706cm\" svg:height=\"10.28cm\" svg:x=\"3.647cm\" svg:y=\"2.853cm\" draw:page-number=\"1\"/>\n";
	u<<"<draw:text-box presentation:style-name=\"pr3\" draw:text-style-name=\"P1\" draw:layer=\"layout\" svg:width=\"14.518cm\" svg:height=\"11.411cm\" svg:x=\"3.249cm\" svg:y=\"14.13cm\" presentation:class=\"notes \" presentation:placeholder=\"true\"/>\n";
	u<<"</presentation:notes>\n";
	u<<"</draw:page>\n";

	//outputData(item, s, level);
	//s<<"<text:ordered-list text:style-name=\"L1\">";
	if (root->countChildren() > 0)
	{
		for (int i = 0; i<root->countChildren(); i++)
			writeItem((DDataItem*) m_data->Item(root->childNum(i)), u, 0);
	}

	// write the end of document
	u<<"<presentation:settings presentation:stay-on-top=\"true\"/>\n";
	u<<"</office:body>\n";
	u<<"</office:document-content>";

	// close the content document
	textfile.close();

	// ----------------------------
	// styles

	QFile stylefile(path+"/styles.xml");
	if (!stylefile.open(IO_WriteOnly | IO_Append) )
	{
		kdWarning()<<"could not open the styles xml file for append :-/"<<endl;
		return false;
	}
	QTextStream v(&stylefile);

	v<<"<draw:text-box draw:style-name=\"gr2\" draw:text-style-name=\"P3\" draw:layer=\"backgroundobjects\" svg:width=\"16.93cm\" svg:height=\"1.259cm\" svg:x=\"5.76cm\" svg:y=\"19.298cm\">";
	v<<"<text:p text:style-name=\"P3\">";
	v<<DDataItem::protectXML(m_data->m_fname)<<" "<<DDataItem::protectXML(m_data->m_sname);
	v<<"</text:p>";
	v<<"</draw:text-box>";
	v<<"<presentation:notes style:page-master-name=\"PM2\">";
	v<<"<draw:page-thumbnail presentation:style-name=\"lyt-cool-title\" draw:layer=\"backgroundobjects\" svg:width=\"13.706cm\" svg:height=\"10.28cm\" svg:x=\"3.647cm\" svg:y=\"2.853cm\" presentation:class=\"page\"/>";
	v<<"<draw:text-box presentation:style-name=\"lyt-cool-notes\" draw:layer=\"backgroundobjects\" svg:width=\"14.518cm\" svg:height=\"11.41cm\" svg:x=\"3.249cm\" svg:y=\"14.13cm\" presentation:class=\"notes\" presentation:placeholder=\"true\"/>";
	v<<"</presentation:notes> </style:master-page> </office:master-styles> </office:document-styles>";

	stylefile.close();

	// ------------------------------
	// process the meta-data section

	// store the author name, title and time creation

	// title : DDataItem::protectXML(root->m_summary)
	// author : protectTex(m_data->m_fname)<<" "<<protectTex(m_data->m_sname)

	QFile metafile(path+"/meta.xml");
	if (!metafile.open(IO_WriteOnly | IO_Append) )
	{
		kdWarning()<<"could not open the main xml file for append :-/"<<endl;
		return false;
	}

	QTextStream m(&metafile);
	m.setEncoding(QTextStream::UnicodeUTF8);

	m<<"<meta:initial-creator>"<<DDataItem::protectXML(m_data->m_fname)<<" "<<DDataItem::protectXML(m_data->m_sname)<<"</meta:initial-creator>\n";
	m<<"<dc:creator>"<<DDataItem::protectXML(m_data->m_fname)<<" "<<DDataItem::protectXML(m_data->m_sname)<<"</dc:creator>\n";

	m<<"<dc:language>";
	//KLocale *loc = KGlobal::locale();
	//if (loc) m<<loc->country();
	//m<<KLocale::defaultLanguage().replace('_', '-');
	//m<<"fr-FR";
	m<<Settings::countrycode();
	m<<"</dc:language>\n";

	m<<"<meta:editing-cycles>3</meta:editing-cycles>\n";
	m<<"<meta:editing-duration>PT8S</meta:editing-duration>\n";

	m<<"<meta:user-defined meta:name=\"Info 1\"/>";
	m<<"<meta:user-defined meta:name=\"Info 2\"/>";
	m<<"<meta:user-defined meta:name=\"Info 3\"/>";
	m<<"<meta:user-defined meta:name=\"Info 4\"/>";
	m<<"<meta:document-statistic meta:table-count=\"0\" meta:image-count=\"0\" meta:object-count=\"0\" meta:page-count=\"1\" meta:paragraph-count=\"1\" meta:word-count=\"1\" meta:character-count=\"0\"/>\n";
	m<<"</office:meta>\n</office:document-meta>";

	metafile.close();

	// ----------------------------------------------------
	// create the archive

	KZip zip(path+"/newdoc.sxi");
	zip.setCompression( KZip::DeflateCompression );
	zip.open( IO_WriteOnly );

	zip.addLocalFile(path+"/content.xml", "content.xml");
	zip.addLocalFile(path+"/meta.xml", "meta.xml");
	zip.addLocalFile(path+"/mimetype", "mimetype");
	zip.addLocalFile(path+"/settings.xml", "settings.xml");
	zip.addLocalFile(path+"/styles.xml", "styles.xml");
	zip.addLocalDirectory(path+"/Pictures", "Pictures");
	zip.addLocalDirectory(path+"/META-INF", "META-INF");

	zip.close();

	// ----------------------------------------------------
	// remove the (now useless) temporary files

	// do not show the progressdialog
	KIO::del(KURL(path+"/content.xml"), false, false );
	KIO::del(KURL(path+"/meta.xml"), false, false );
	KIO::del(KURL(path+"/mimetype"), false, false );
	KIO::del(KURL(path+"/settings.xml"), false, false );
	KIO::del(KURL(path+"/styles.xml"), false, false );
	KIO::del(KURL(path+"/META-INF"), false, false );
	KIO::del(KURL(path+"/Pictures"), false, false );

	notifyDocGenerated( path+"/newdoc.sxi" );
	
	return true;
}

#include "kdissOOOimpress.moc"
