/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svx.hxx"
#include <tools/debug.hxx>
#include <com/sun/star/container/XNameContainer.hpp>
#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
#include <com/sun/star/uno/Sequence.hxx>
#include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
#include <com/sun/star/drawing/LineDash.hpp>
#include <com/sun/star/awt/Gradient.hpp>
#include <com/sun/star/drawing/Hatch.hpp>
#include <com/sun/star/io/XActiveDataSource.hpp>
#include <com/sun/star/embed/ElementModes.hpp>
#include <sfx2/docfile.hxx>
#include <rtl/ustrbuf.hxx>
#include <xmloff/xmluconv.hxx>
#include "xmloff/xmlnmspe.hxx"
#include "xmloff/nmspmap.hxx"

#include "xmloff/xmltoken.hxx"
#include "xmloff/xmlmetae.hxx"
#include "xmloff/DashStyle.hxx"
#include "xmloff/GradientStyle.hxx"
#include "xmloff/HatchStyle.hxx"
#include "xmloff/ImageStyle.hxx"
#include "xmloff/MarkerStyle.hxx"
#include <com/sun/star/container/XNameContainer.hpp>
#include <com/sun/star/embed/XTransactedObject.hpp>
#include <comphelper/processfactory.hxx>
#include <unotools/streamwrap.hxx>
#include "svx/xmlgrhlp.hxx"

#include "xmlxtexp.hxx"

#include <comphelper/storagehelper.hxx>

using namespace com::sun::star;
using namespace com::sun::star::container;
using namespace com::sun::star::document;
using namespace com::sun::star::uno;
using namespace com::sun::star::awt;
using namespace com::sun::star::lang;
using namespace com::sun::star::xml::sax;
using namespace ::xmloff::token;
using namespace ::rtl;
using namespace cppu;

using com::sun::star::embed::XTransactedObject;

class SvxXMLTableEntryExporter
{
public:
	SvxXMLTableEntryExporter( SvXMLExport& rExport ) : mrExport( rExport ) {}
	virtual ~SvxXMLTableEntryExporter();

	virtual void exportEntry( const OUString& rStrName, const Any& rValue ) = 0;

protected:
	SvXMLExport& mrExport;
};

class SvxXMLColorEntryExporter : public SvxXMLTableEntryExporter
{
public:
	SvxXMLColorEntryExporter( SvXMLExport& rExport );
	virtual ~SvxXMLColorEntryExporter();

	virtual void exportEntry( const OUString& rStrName, const Any& rValue );
};

class SvxXMLLineEndEntryExporter : public SvxXMLTableEntryExporter
{
public:
	SvxXMLLineEndEntryExporter( SvXMLExport& rExport );
	SvxXMLLineEndEntryExporter();
	virtual ~SvxXMLLineEndEntryExporter();

	virtual void exportEntry( const OUString& rStrName, const Any& rValue );
private:
	XMLMarkerStyleExport maMarkerStyle;
};

class SvxXMLDashEntryExporter : public SvxXMLTableEntryExporter
{
public:
	SvxXMLDashEntryExporter( SvXMLExport& rExport );
	virtual ~SvxXMLDashEntryExporter();

	virtual void exportEntry( const OUString& rStrName, const Any& rValue );

private:
	XMLDashStyleExport maDashStyle;
};

class SvxXMLHatchEntryExporter : public SvxXMLTableEntryExporter
{
public:
	SvxXMLHatchEntryExporter( SvXMLExport& rExport );
	virtual ~SvxXMLHatchEntryExporter();

	virtual void exportEntry( const OUString& rStrName, const Any& rValue );
private:
	XMLHatchStyleExport maHatchStyle;
};

class SvxXMLGradientEntryExporter : public SvxXMLTableEntryExporter
{
public:
	SvxXMLGradientEntryExporter( SvXMLExport& rExport );
	virtual ~SvxXMLGradientEntryExporter();

	virtual void exportEntry( const OUString& rStrName, const Any& rValue );
private:
	XMLGradientStyleExport maGradientStyle;
};

class SvxXMLBitmapEntryExporter : public SvxXMLTableEntryExporter
{
public:
	SvxXMLBitmapEntryExporter( SvXMLExport& rExport );
	virtual ~SvxXMLBitmapEntryExporter();

	virtual void exportEntry( const OUString& rStrName, const Any& rValue );

private:
	XMLImageStyle maImageStyle;
};

///////////////////////////////////////////////////////////////////////

// #110680#
SvxXMLXTableExportComponent::SvxXMLXTableExportComponent(
	const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xServiceFactory,
	const OUString& rFileName,
	const uno::Reference<xml::sax::XDocumentHandler> & rHandler,
	const uno::Reference<container::XNameContainer >& xTable,
	uno::Reference<document::XGraphicObjectResolver >& xGrfResolver ) 
:	SvXMLExport( xServiceFactory, rFileName, rHandler, NULL, MAP_100TH_MM), 
	mxTable( xTable )
{

	_GetNamespaceMap().Add( GetXMLToken(XML_NP_OOO), GetXMLToken(XML_N_OOO), XML_NAMESPACE_OOO );
	_GetNamespaceMap().Add( GetXMLToken(XML_NP_OFFICE), GetXMLToken(XML_N_OFFICE), XML_NAMESPACE_OFFICE );
	_GetNamespaceMap().Add( GetXMLToken(XML_NP_DRAW), GetXMLToken(XML_N_DRAW), XML_NAMESPACE_DRAW );
	_GetNamespaceMap().Add( GetXMLToken(XML_NP_XLINK), GetXMLToken(XML_N_XLINK), XML_NAMESPACE_XLINK );
	_GetNamespaceMap().Add( GetXMLToken(XML_NP_SVG), GetXMLToken(XML_N_SVG),  XML_NAMESPACE_SVG );
	SetGraphicResolver( xGrfResolver );
	setExportFlags( 0 );
}

SvxXMLXTableExportComponent::~SvxXMLXTableExportComponent()
{
}

sal_Bool SvxXMLXTableExportComponent::save( const OUString& rURL, const uno::Reference<container::XNameContainer >& xTable ) throw()
{
    uno::Reference < embed::XStorage > xStorage;
	SfxMedium* pMedium = NULL;
	sal_Bool bRet = sal_False;

	uno::Reference< XGraphicObjectResolver >	xGrfResolver;
	SvXMLGraphicHelper*	pGraphicHelper = 0;

	try
	{
		do
		{
            uno::Reference < io::XOutputStream > xOut;
            uno::Reference < io::XStream > xStream;

			sal_Bool bNeedStorage = xTable->getElementType() == ::getCppuType((const OUString*)0);

			uno::Reference< lang::XMultiServiceFactory> xServiceFactory( ::comphelper::getProcessServiceFactory() );
			if( !xServiceFactory.is() )
			{
				DBG_ERROR( "got no service manager" );
				return sal_False;
			}

			uno::Reference< uno::XInterface > xWriter( xServiceFactory->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.xml.sax.Writer" ) ) ) );
			if( !xWriter.is() )
			{
				DBG_ERROR( "com.sun.star.xml.sax.Writer service missing" );
				return sal_False;
			}

			uno::Reference<xml::sax::XDocumentHandler>	xHandler( xWriter, uno::UNO_QUERY );

			if( bNeedStorage )
			{
                xStorage =
                  ::comphelper::OStorageHelper::GetStorageFromURL( rURL, embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE );

                if( !xStorage.is() )
				{
					DBG_ERROR( "no storage!" );
					break;
				}

				OUString sMetaName( RTL_CONSTASCII_USTRINGPARAM( "Content.xml" ) );
                xStream = xStorage->openStreamElement( sMetaName, embed::ElementModes::WRITE );
                pGraphicHelper = SvXMLGraphicHelper::Create( xStorage, GRAPHICHELPER_MODE_WRITE );
				xGrfResolver = pGraphicHelper;
                xOut = xStream->getOutputStream();
			}
			else
			{
				pMedium = new SfxMedium( rURL, STREAM_WRITE | STREAM_TRUNC, sal_True );
				pMedium->IsRemote();

				SvStream* pStream = pMedium->GetOutStream();
				if( NULL == pStream )
				{
					DBG_ERROR( "no output stream!" );
					break;
				}

				xOut = new utl::OOutputStreamWrapper( *pStream );
			}

			uno::Reference<io::XActiveDataSource> xMetaSrc( xWriter, uno::UNO_QUERY );
			xMetaSrc->setOutputStream( xOut );

			const OUString aName;
			
			// #110680#
			// SvxXMLXTableExportComponent aExporter( aName, xHandler, xTable, xGrfResolver );
			SvxXMLXTableExportComponent aExporter( xServiceFactory, aName, xHandler, xTable, xGrfResolver );

			bRet = aExporter.exportTable();

		}
		while( 0 );

		if( pGraphicHelper )
			SvXMLGraphicHelper::Destroy( pGraphicHelper );

		if( xStorage.is() )
		{
			uno::Reference< XTransactedObject > xTrans( xStorage, UNO_QUERY );
			if( xTrans.is() )
				xTrans->commit();

			uno::Reference< XComponent > xComp( xStorage, UNO_QUERY );
			if( xComp.is() )
				xStorage->dispose();
		}
	}
	catch( uno::Exception& )
	{
		bRet = sal_False;
	}

	if( pMedium )
	{
		pMedium->Commit();
		delete pMedium;
	}

	return bRet;
}

sal_Bool SvxXMLXTableExportComponent::exportTable() throw()
{
	sal_Bool bRet = sal_False;

	try
	{
		GetDocHandler()->startDocument();

		// export namespaces
		sal_uInt16 nPos = GetNamespaceMap().GetFirstKey();
		while( USHRT_MAX != nPos )
		{
			GetAttrList().AddAttribute( GetNamespaceMap().GetAttrNameByKey( nPos ), GetNamespaceMap().GetNameByKey( nPos ) );
			nPos = GetNamespaceMap().GetNextKey( nPos );
		}

		do
		{
			if( !mxTable.is() )
				break;

			char const* pEleName;
			Type aExportType = mxTable->getElementType();
			SvxXMLTableEntryExporter* pExporter = NULL;

			if( aExportType == ::getCppuType((const sal_Int32*)0) )
			{
				pExporter = new SvxXMLColorEntryExporter(*this);
				pEleName = "color-table";
			}
			else if( aExportType == ::getCppuType((const drawing::PolyPolygonBezierCoords*)0) )
			{
				pExporter = new SvxXMLLineEndEntryExporter(*this);
				pEleName = "marker-table";
			}
			else if( aExportType == ::getCppuType((const drawing::LineDash*)0) )
			{
				pExporter = new SvxXMLDashEntryExporter(*this);
				pEleName = "dash-table";
			}
			else if( aExportType == ::getCppuType((const drawing::Hatch*)0) )
			{
				pExporter = new SvxXMLHatchEntryExporter(*this);
				pEleName = "hatch-table";
			}
			else if( aExportType == ::getCppuType((const awt::Gradient*)0))
			{
				pExporter = new SvxXMLGradientEntryExporter(*this);
				pEleName = "gradient-table";
			}
			else if( aExportType == ::getCppuType((const OUString*)0))
			{
				pExporter = new SvxXMLBitmapEntryExporter(*this);
				pEleName = "bitmap-table";
			}
			else
			{
				DBG_ERROR( "unknown type for export");
				break;
			}

			SvXMLElementExport aElem( *this, XML_NAMESPACE_OOO, pEleName, sal_True, sal_True );

			Sequence< OUString > aNames = mxTable->getElementNames();
			const sal_Int32 nCount = aNames.getLength();
			const OUString* pNames = aNames.getConstArray();
			Any aAny;

			sal_Int32 nIndex;
			for( nIndex = 0; nIndex < nCount; nIndex++, pNames++ )
			{
				aAny = mxTable->getByName( *pNames );
				pExporter->exportEntry( *pNames, aAny );
			}

			bRet = sal_True;
		}
		while(0);

		GetDocHandler()->endDocument();
	}
	catch( Exception e )
	{
		bRet = sal_False;
	}

	return bRet;
}

// methods without content:
void SvxXMLXTableExportComponent::_ExportAutoStyles() {}
void SvxXMLXTableExportComponent::_ExportMasterStyles() {}
void SvxXMLXTableExportComponent::_ExportContent() {}

///////////////////////////////////////////////////////////////////////

SvxXMLTableEntryExporter::~SvxXMLTableEntryExporter()
{
}

///////////////////////////////////////////////////////////////////////

SvxXMLColorEntryExporter::SvxXMLColorEntryExporter( SvXMLExport& rExport )
: SvxXMLTableEntryExporter( rExport )
{
}

SvxXMLColorEntryExporter::~SvxXMLColorEntryExporter()
{
}

void SvxXMLColorEntryExporter::exportEntry( const OUString& rStrName, const Any& rValue )
{
	mrExport.AddAttribute( XML_NAMESPACE_DRAW, XML_NAME, rStrName );

	sal_Int32 nColor = 0;
	rValue >>= nColor;

	OUStringBuffer aOut;
	mrExport.GetMM100UnitConverter().convertColor( aOut, nColor );
	mrExport.AddAttribute( XML_NAMESPACE_DRAW, XML_COLOR, aOut.makeStringAndClear() );

	SvXMLElementExport aElem( mrExport, XML_NAMESPACE_DRAW, XML_COLOR, sal_True, sal_True );
}

///////////////////////////////////////////////////////////////////////

SvxXMLLineEndEntryExporter::SvxXMLLineEndEntryExporter( SvXMLExport& rExport )
: SvxXMLTableEntryExporter( rExport ), maMarkerStyle( rExport )
{
}

SvxXMLLineEndEntryExporter::~SvxXMLLineEndEntryExporter()
{
}

void SvxXMLLineEndEntryExporter::exportEntry( const OUString& rStrName, const Any& rValue )
{
	maMarkerStyle.exportXML( rStrName, rValue );
}

///////////////////////////////////////////////////////////////////////

SvxXMLDashEntryExporter::SvxXMLDashEntryExporter( SvXMLExport& rExport )
: SvxXMLTableEntryExporter( rExport ), maDashStyle( rExport )
{
}

SvxXMLDashEntryExporter::~SvxXMLDashEntryExporter()
{
}

void SvxXMLDashEntryExporter::exportEntry( const OUString& rStrName, const Any& rValue )
{
	maDashStyle.exportXML( rStrName, rValue );
}

///////////////////////////////////////////////////////////////////////

SvxXMLHatchEntryExporter::SvxXMLHatchEntryExporter( SvXMLExport& rExport )
: SvxXMLTableEntryExporter( rExport ), maHatchStyle( rExport )
{
}

SvxXMLHatchEntryExporter::~SvxXMLHatchEntryExporter()
{
}

void SvxXMLHatchEntryExporter::exportEntry( const OUString& rStrName, const Any& rValue )
{
	maHatchStyle.exportXML( rStrName, rValue );
}

///////////////////////////////////////////////////////////////////////

SvxXMLGradientEntryExporter::SvxXMLGradientEntryExporter( SvXMLExport& rExport )
: SvxXMLTableEntryExporter( rExport ), maGradientStyle( rExport )
{
}

SvxXMLGradientEntryExporter::~SvxXMLGradientEntryExporter()
{
}

void SvxXMLGradientEntryExporter::exportEntry( const OUString& rStrName, const Any& rValue )
{
	maGradientStyle.exportXML( rStrName, rValue );
}

///////////////////////////////////////////////////////////////////////

SvxXMLBitmapEntryExporter::SvxXMLBitmapEntryExporter( SvXMLExport& rExport )
: SvxXMLTableEntryExporter( rExport )
{
}

SvxXMLBitmapEntryExporter::~SvxXMLBitmapEntryExporter()
{
}

void SvxXMLBitmapEntryExporter::exportEntry( const OUString& rStrName, const Any& rValue )
{
	maImageStyle.exportXML( rStrName, rValue, mrExport );
}
