/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* writerperfect
 * Version: MPL 2.0 / LGPLv2.1+
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * Major Contributor(s):
 * Copyright (C) 2002-2004 William Lachance (wrlach@gmail.com)
 * Copyright (C) 2004-2006 Fridrich Strba (fridrich.strba@bluewin.ch)
 *
 * For minor contributions see the git repository.
 *
 * Alternatively, the contents of this file may be used under the terms
 * of the GNU Lesser General Public License Version 2.1 or later
 * (LGPLv2.1+), in which case the provisions of the LGPLv2.1+ are
 * applicable instead of those above.
 *
 * For further information visit http://libwpd.sourceforge.net
 */

#include <string.h>
#include <stdio.h>

#include "OdfPackage.hxx"

#include "libodfgen/libodfgen.hxx"
#include "StringXMLSerializer.hxx"

namespace OdfPackageInternal
{
class StringDocumentHandler : public OdfDocumentHandler
{
public:
	StringDocumentHandler();

	char const *cstr() const
	{
		return m_serializer.getData().cstr();
	}

	virtual void startDocument()
	{
		m_serializer.startDocument();
	}

	virtual void endDocument()
	{
		m_serializer.endDocument();
	}

	virtual void startElement(const char *psName, const librevenge::RVNGPropertyList &xPropList)
	{
		if (!psName)
			return;
		if (strcmp(psName,"chart:series")==0 && xPropList["loext:label-string"])
		{
			librevenge::RVNGPropertyList pList(xPropList);
			pList.insert("loext:label-string",
			             librevenge::RVNGString::escapeXML(xPropList["loext:label-string"]->getStr()));
			m_serializer.startElement(psName, pList);
		}
		else
			m_serializer.startElement(psName, xPropList);
	}

	virtual void endElement(const char *psName)
	{
		m_serializer.endElement(psName);
	}

	virtual void characters(const librevenge::RVNGString &sCharacters)
	{
		m_serializer.characters(sCharacters);
	}

private:
	StringXMLSerializer m_serializer;
};

StringDocumentHandler::StringDocumentHandler()
	: m_serializer()
{
}

struct Content
{
	explicit Content(char const *fileName)
		: m_fileName(fileName)
		, m_contentHandler(), m_manifestHandler(), m_metaHandler(), m_settingsHandler(), m_stylesHandler()
	{
	}
	char const *m_fileName;
	StringDocumentHandler m_contentHandler, m_manifestHandler, m_metaHandler, m_settingsHandler, m_stylesHandler;
};
}

OdfPackage::OdfPackage(char const *fileName)
	: OutputFileHelper(fileName)
	, m_type(OdfPackage::Unknown)
	, m_content(new OdfPackageInternal::Content(fileName))
{
}

OdfPackage::~OdfPackage()
{
}

void OdfPackage::addHandlersTo(OdgGenerator &generator)
{
	m_type=Odg;
	if (!m_content->m_fileName)
	{
		generator.addDocumentHandler(&m_content->m_contentHandler, ODF_FLAT_XML);
		return;
	}
	generator.addDocumentHandler(&m_content->m_contentHandler, ODF_CONTENT_XML);
	generator.addDocumentHandler(&m_content->m_manifestHandler, ODF_MANIFEST_XML);
	generator.addDocumentHandler(&m_content->m_metaHandler, ODF_META_XML);
	generator.addDocumentHandler(&m_content->m_settingsHandler, ODF_SETTINGS_XML);
	generator.addDocumentHandler(&m_content->m_stylesHandler, ODF_STYLES_XML);
}

void OdfPackage::addHandlersTo(OdpGenerator &generator)
{
	m_type=Odp;
	if (!m_content->m_fileName)
	{
		generator.addDocumentHandler(&m_content->m_contentHandler, ODF_FLAT_XML);
		return;
	}
	generator.addDocumentHandler(&m_content->m_contentHandler, ODF_CONTENT_XML);
	generator.addDocumentHandler(&m_content->m_manifestHandler, ODF_MANIFEST_XML);
	generator.addDocumentHandler(&m_content->m_metaHandler, ODF_META_XML);
	generator.addDocumentHandler(&m_content->m_settingsHandler, ODF_SETTINGS_XML);
	generator.addDocumentHandler(&m_content->m_stylesHandler, ODF_STYLES_XML);
}

void OdfPackage::addHandlersTo(OdsGenerator &generator)
{
	m_type=Ods;
	if (!m_content->m_fileName)
	{
		generator.addDocumentHandler(&m_content->m_contentHandler, ODF_FLAT_XML);
		return;
	}
	generator.addDocumentHandler(&m_content->m_contentHandler, ODF_CONTENT_XML);
	generator.addDocumentHandler(&m_content->m_manifestHandler, ODF_MANIFEST_XML);
	generator.addDocumentHandler(&m_content->m_metaHandler, ODF_META_XML);
	generator.addDocumentHandler(&m_content->m_stylesHandler, ODF_STYLES_XML);
}

void OdfPackage::addHandlersTo(OdtGenerator &generator)
{
	m_type=Odt;
	if (!m_content->m_fileName)
	{
		generator.addDocumentHandler(&m_content->m_contentHandler, ODF_FLAT_XML);
		return;
	}
	generator.addDocumentHandler(&m_content->m_contentHandler, ODF_CONTENT_XML);
	generator.addDocumentHandler(&m_content->m_manifestHandler, ODF_MANIFEST_XML);
	generator.addDocumentHandler(&m_content->m_metaHandler, ODF_META_XML);
	generator.addDocumentHandler(&m_content->m_stylesHandler, ODF_STYLES_XML);
}

bool OdfPackage::write()
{
	if (m_type==Unknown) return false;
	if (!m_content->m_fileName)
	{
		printf("%s\n", m_content->m_contentHandler.cstr());
		return true;
	}

	if ((m_type==Odg && !writeChildFile("mimetype", "application/vnd.oasis.opendocument.graphics", (char)0)) ||
	        (m_type==Odp && !writeChildFile("mimetype", "application/vnd.oasis.opendocument.presentation", (char)0)) ||
	        (m_type==Ods && !writeChildFile("mimetype", "application/vnd.oasis.opendocument.spreadsheet", (char)0)) ||
	        (m_type==Odt && !writeChildFile("mimetype", "application/vnd.oasis.opendocument.text", (char)0)))
		return false;
	if (!writeChildFile("META-INF/manifest.xml", m_content->m_manifestHandler.cstr()) ||
	        !writeChildFile("content.xml", m_content->m_contentHandler.cstr()) ||
	        !writeChildFile("meta.xml", m_content->m_metaHandler.cstr()) ||
	        ((m_type==Odg || m_type==Odp) && !writeChildFile("settings.xml", m_content->m_settingsHandler.cstr())) ||
	        !writeChildFile("styles.xml", m_content->m_stylesHandler.cstr()))
		return false;

	return true;
}

bool OdfPackage::write(OdgGenerator &generator)
{
	if (!write()) return false;
	if (!m_content->m_fileName) return true;
	librevenge::RVNGStringVector objects=generator.getObjectNames();
	for (unsigned i=0; i<objects.size(); ++i)
	{
		OdfPackageInternal::StringDocumentHandler objectHandler;
		if (generator.getObjectContent(objects[i], &objectHandler))
			writeChildFile(objects[i].cstr(), objectHandler.cstr());
	}
	return true;
}

bool OdfPackage::write(OdpGenerator &generator)
{
	if (!write()) return false;
	if (!m_content->m_fileName) return true;
	librevenge::RVNGStringVector objects=generator.getObjectNames();
	for (unsigned i=0; i<objects.size(); ++i)
	{
		OdfPackageInternal::StringDocumentHandler objectHandler;
		if (generator.getObjectContent(objects[i], &objectHandler))
			writeChildFile(objects[i].cstr(), objectHandler.cstr());
	}
	return true;
}

bool OdfPackage::write(OdsGenerator &generator)
{
	if (!write()) return false;
	if (!m_content->m_fileName) return true;
	librevenge::RVNGStringVector objects=generator.getObjectNames();
	for (unsigned i=0; i<objects.size(); ++i)
	{
		OdfPackageInternal::StringDocumentHandler objectHandler;
		if (generator.getObjectContent(objects[i], &objectHandler))
			writeChildFile(objects[i].cstr(), objectHandler.cstr());
	}
	return true;
}

bool OdfPackage::write(OdtGenerator &generator)
{
	if (!write()) return false;
	if (!m_content->m_fileName) return true;
	librevenge::RVNGStringVector objects=generator.getObjectNames();
	for (unsigned i=0; i<objects.size(); ++i)
	{
		OdfPackageInternal::StringDocumentHandler objectHandler;
		if (generator.getObjectContent(objects[i], &objectHandler))
			writeChildFile(objects[i].cstr(), objectHandler.cstr());
	}
	return true;
}

/* vim:set shiftwidth=4 softtabstop=4 noexpandtab: */
