/**************************************************************
 * 
 * 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_filter.hxx"
#include <com/sun/star/uno/Reference.hxx>
#include <com/sun/star/uno/Sequence.hxx>
#include <com/sun/star/uno/Any.hxx>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/container/XNameAccess.hpp>
#include <com/sun/star/embed/XEmbedPersist.hpp>
#include <com/sun/star/embed/NoVisualAreaSizeException.hpp>
#include <com/sun/star/embed/EmbedStates.hpp>
#include <com/sun/star/frame/XStorable.hpp>
#include <com/sun/star/awt/Size.hpp>
#include <com/sun/star/embed/Aspects.hpp>
#include <sot/clsids.hxx>
#include <sfx2/objsh.hxx>
#include <sfx2/docfac.hxx>
#include <sfx2/docfilt.hxx>
#include <sfx2/docfile.hxx>
#include <sfx2/fcontnr.hxx>
#include <sot/formats.hxx>
#include <comphelper/processfactory.hxx>
#include <unotools/streamwrap.hxx>
#include <comphelper/storagehelper.hxx>
#include <svtools/embedhlp.hxx>
#include <filter/msfilter/msdffimp.hxx> // extern sichtbare Header-Datei

#include "filter/msfilter/msoleexp.hxx"

#define CREATE_CONST_ASC(s) String::CreateFromAscii( \
    RTL_CONSTASCII_STRINGPARAM(s))

using namespace ::com::sun::star;

SvGlobalName GetEmbeddedVersion( const SvGlobalName& aAppName )
{
	if ( aAppName == SvGlobalName( SO3_SM_CLASSID_60 ) )
			return SvGlobalName( SO3_SM_OLE_EMBED_CLASSID_8 );
	else if ( aAppName == SvGlobalName( SO3_SW_CLASSID_60 ) )
			return SvGlobalName( SO3_SW_OLE_EMBED_CLASSID_8 );
	else if ( aAppName == SvGlobalName( SO3_SC_CLASSID_60 ) )
			return SvGlobalName( SO3_SC_OLE_EMBED_CLASSID_8 );
	else if ( aAppName == SvGlobalName( SO3_SDRAW_CLASSID_60 ) )
			return SvGlobalName( SO3_SDRAW_OLE_EMBED_CLASSID_8 );
	else if ( aAppName == SvGlobalName( SO3_SIMPRESS_CLASSID_60 ) )
			return SvGlobalName( SO3_SIMPRESS_OLE_EMBED_CLASSID_8 );
	else if ( aAppName == SvGlobalName( SO3_SCH_CLASSID_60 ) )
			return SvGlobalName( SO3_SCH_OLE_EMBED_CLASSID_8 );

	return SvGlobalName();
}

String GetStorageType( const SvGlobalName& aEmbName )
{
	if ( aEmbName == SvGlobalName( SO3_SM_OLE_EMBED_CLASSID_8 ) )
			return String::CreateFromAscii( "opendocument.MathDocument.1" );
	else if ( aEmbName == SvGlobalName( SO3_SW_OLE_EMBED_CLASSID_8 ) )
			return String::CreateFromAscii( "opendocument.WriterDocument.1" );
	else if ( aEmbName == SvGlobalName( SO3_SC_OLE_EMBED_CLASSID_8 ) )
			return String::CreateFromAscii( "opendocument.CalcDocument.1" );
	else if ( aEmbName == SvGlobalName( SO3_SDRAW_OLE_EMBED_CLASSID_8 ) )
			return String::CreateFromAscii( "opendocument.DrawDocument.1" );
	else if ( aEmbName == SvGlobalName( SO3_SIMPRESS_OLE_EMBED_CLASSID_8 ) )
			return String::CreateFromAscii( "opendocument.ImpressDocument.1" );
	else if ( aEmbName == SvGlobalName( SO3_SCH_OLE_EMBED_CLASSID_8 ) )
			return String::CreateFromAscii( "opendocument.ChartDocument.1" );

	return String();
}

sal_Bool UseOldMSExport()
{
    uno::Reference< lang::XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory();

	if ( xFactory.is() )
	{
		uno::Reference< lang::XMultiServiceFactory > xProvider( xFactory->createInstance(
                    rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationProvider"))),
                	uno::UNO_QUERY);
		if ( xProvider.is() )
		{
			try {
				uno::Sequence< uno::Any > aArg( 1 );
				aArg[0] <<= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.Common/InternalMSExport") );
				uno::Reference< container::XNameAccess > xNameAccess(
					xProvider->createInstanceWithArguments(
						rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationUpdateAccess" ) ),
						aArg ),
					uno::UNO_QUERY );
				if ( xNameAccess.is() )
				{
					uno::Any aResult = xNameAccess->getByName(
									rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UseOldExport" ) ) );

					sal_Bool bResult = sal_Bool();
					if ( aResult >>= bResult )
						return bResult;
				}
			}
			catch( uno::Exception& )
			{
			}
		}
	}

	OSL_ENSURE( sal_False, "Could not get access to configuration entry!\n" );
	return sal_False;
}

void SvxMSExportOLEObjects::ExportOLEObject( const com::sun::star::uno::Reference < com::sun::star::embed::XEmbeddedObject>& rObj, SotStorage& rDestStg )
{
    svt::EmbeddedObjectRef aObj( rObj, embed::Aspects::MSOLE_CONTENT );
    ExportOLEObject( aObj, rDestStg );
}

void SvxMSExportOLEObjects::ExportOLEObject( svt::EmbeddedObjectRef& rObj, SvStorage& rDestStg )
{
	SvGlobalName aOwnGlobalName;
    SvGlobalName aObjName( rObj->getClassID() );
	const SfxFilter* pExpFilter = NULL;
	{
		static struct _ObjExpType {
			sal_uInt32 nFlag;
			const char* pFilterNm;
			// GlobalNameId
			struct _GlobalNameIds {
				sal_uInt32 n1;
				sal_uInt16 n2, n3;
				sal_uInt8 b8, b9, b10, b11, b12, b13, b14, b15;
            }
			aGlNmIds[4];
		} aArr[] = {
			{ OLE_STARMATH_2_MATHTYPE, "MathType 3.x",
				{{SO3_SM_CLASSID_60}, {SO3_SM_CLASSID_50},
				 {SO3_SM_CLASSID_40}, {SO3_SM_CLASSID_30 }}},
			{ OLE_STARWRITER_2_WINWORD, "MS Word 97",
				{{SO3_SW_CLASSID_60}, {SO3_SW_CLASSID_50},
				 {SO3_SW_CLASSID_40}, {SO3_SW_CLASSID_30 }}},
			{ OLE_STARCALC_2_EXCEL, "MS Excel 97",
				{{SO3_SC_CLASSID_60}, {SO3_SC_CLASSID_50},
				 {SO3_SC_CLASSID_40}, {SO3_SC_CLASSID_30 }}},
			{ OLE_STARIMPRESS_2_POWERPOINT, "MS PowerPoint 97",
				{{SO3_SIMPRESS_CLASSID_60}, {SO3_SIMPRESS_CLASSID_50},
				 {SO3_SIMPRESS_CLASSID_40}, {SO3_SIMPRESS_CLASSID_30 }}},
			{ 0, "",
				{{SO3_SCH_CLASSID_60}, {SO3_SCH_CLASSID_50},
				 {SO3_SCH_CLASSID_40}, {SO3_SCH_CLASSID_30 }}},
			{ 0, "",
				{{SO3_SDRAW_CLASSID_60}, {SO3_SDRAW_CLASSID_50},	// SJ: !!!! SO3_SDRAW_CLASSID is only available up from
				 {SO3_SDRAW_CLASSID_60}, {SO3_SDRAW_CLASSID_50 }}}, // ver 5.0, it is purpose to have double entrys here.

			{ 0xffff,0,
				{{SO3_SDRAW_CLASSID_60}, {SO3_SDRAW_CLASSID_50},
				{SO3_SDRAW_CLASSID_60}, {SO3_SDRAW_CLASSID_50}}}
		};

        for( const _ObjExpType* pArr = aArr; !pExpFilter && ( pArr->nFlag != 0xffff ); ++pArr )
		{
            for ( int n = 0; n < 4; ++n )
			{
				const _ObjExpType::_GlobalNameIds& rId = pArr->aGlNmIds[ n ];
				SvGlobalName aGlbNm( rId.n1, rId.n2, rId.n3,
							rId.b8, rId.b9, rId.b10, rId.b11,
							rId.b12, rId.b13, rId.b14, rId.b15 );
                if( aObjName == aGlbNm )
				{
					aOwnGlobalName = aGlbNm;

                    // flags for checking if conversion is wanted at all (SaveOptions?!)
					if( GetFlags() & pArr->nFlag )
					{
                        pExpFilter = SfxFilterMatcher().GetFilter4FilterName(String::CreateFromAscii(pArr->pFilterNm));
						break;
					}
				}
			}
		}
	}

	if( pExpFilter )				        // use this filter for the export
	{
        try
        {
            if ( rObj->getCurrentState() == embed::EmbedStates::LOADED )
                rObj->changeState( embed::EmbedStates::RUNNING );
            //TODO/LATER: is stream instead of outputstream a better choice?!
            //TODO/LATER: a "StoreTo" method at embedded object would be nice
            uno::Sequence < beans::PropertyValue > aSeq(2);
            SvStream* pStream = new SvMemoryStream;
            aSeq[0].Name = ::rtl::OUString::createFromAscii( "OutputStream" );
            ::uno::Reference < io::XOutputStream > xOut = new ::utl::OOutputStreamWrapper( *pStream );
            aSeq[0].Value <<= xOut;
            aSeq[1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterName" ) );
            aSeq[1].Value <<= ::rtl::OUString( pExpFilter->GetName() );
            uno::Reference < frame::XStorable > xStor( rObj->getComponent(), uno::UNO_QUERY );
            xStor->storeToURL( ::rtl::OUString::createFromAscii( "private:stream" ), aSeq );
            SotStorageRef xOLEStor = new SotStorage( pStream, sal_True );
            xOLEStor->CopyTo( &rDestStg );
            rDestStg.Commit();
        }
        catch( uno::Exception& )
        {
            // TODO/LATER: Error handling
            DBG_ERROR( "The object could not be exported!" );
        }
	}
	else if( aOwnGlobalName != SvGlobalName() )
	{
        // own format, maybe SO6 format or lower
		SvGlobalName aEmbName = GetEmbeddedVersion( aOwnGlobalName );
		if ( aEmbName != SvGlobalName() && !UseOldMSExport() )
		{
            // this is a SO6 embedded object, save in old binary format
			rDestStg.SetVersion( SOFFICE_FILEFORMAT_31 );
			rDestStg.SetClass( aEmbName,
								SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE,
								GetStorageType( aEmbName ) );
			SotStorageStreamRef xExtStm = rDestStg.OpenSotStream(
											String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "properties_stream" ) ),
											STREAM_STD_READWRITE );

			sal_Bool bExtentSuccess = sal_False;
			if( !xExtStm->GetError() )
			{
				// write extent
                //TODO/MBA: check if writing a size is enough
                if( rObj.GetObject().is() )
                {
                    // MSOLE objects don't need to be in running state for VisualArea access
                    awt::Size aSize;
					try
					{
                        // this is an own object, the content size must be stored in the
                        // extension stream
						aSize = rObj->getVisualAreaSize( embed::Aspects::MSOLE_CONTENT );
					}
					catch( embed::NoVisualAreaSizeException& )
					{
						OSL_ENSURE( sal_False, "Could not get visual area size!\n" );
						aSize.Width = 5000;
						aSize.Height = 5000;
					}
					catch( uno::Exception& )
					{
						OSL_ENSURE( sal_False, "Unexpected exception while getting visual area size!\n" );
						aSize.Width = 5000;
						aSize.Height = 5000;
					}
					
                    //Rectangle aVisArea = xSfxIPObj->GetVisArea( ASPECT_CONTENT );
                    sal_Int32 pRect[4];
                    //pRect[0] = aVisArea.Left();
                    //pRect[1] = aVisArea.Right();
                    //pRect[2] = aVisArea.Top();
                    //pRect[3] = aVisArea.Bottom();
                    pRect[0] = 0;
                    pRect[1] = aSize.Width;
                    pRect[2] = 0;
                    pRect[3] = aSize.Height;

                    sal_Int8 aWriteSet[16];
                    for ( int ind = 0; ind < 4; ind++ )
                    {
                        sal_Int32 nVal = pRect[ind];
                        for ( int nByte = 0; nByte < 4; nByte++ )
                        {
                            aWriteSet[ind*4+nByte] = (sal_Int8) nVal % 0x100;
                            nVal /= 0x100;
                        }
                    }

                    bExtentSuccess = ( xExtStm->Write( aWriteSet, 16 ) == 16 );
                }
			}

			if ( bExtentSuccess )
			{
				SotStorageStreamRef xEmbStm = rDestStg.OpenSotStream(
												String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "package_stream" ) ),
												STREAM_STD_READWRITE );
				if( !xEmbStm->GetError() )
				{
                    try
                    {
                        if ( rObj->getCurrentState() == embed::EmbedStates::LOADED )
                            rObj->changeState( embed::EmbedStates::RUNNING );
                        //TODO/LATER: is stream instead of outputstream a better choice?!
                        //TODO/LATER: a "StoreTo" method at embedded object would be nice
                        uno::Sequence < beans::PropertyValue > aSeq(1);
                        aSeq[0].Name = ::rtl::OUString::createFromAscii( "OutputStream" );
                        ::uno::Reference < io::XOutputStream > xOut = new ::utl::OOutputStreamWrapper( *xEmbStm );
                        aSeq[0].Value <<= xOut;
                        uno::Reference < frame::XStorable > xStor( rObj->getComponent(), uno::UNO_QUERY );
                        xStor->storeToURL( ::rtl::OUString::createFromAscii( "private:stream" ), aSeq );
                    }
                    catch( uno::Exception& )
                    {
                        // TODO/LATER: Error handling
                        DBG_ERROR( "The object could not be exported!" );
                    }
				}
			}
		}
		else
		{
            DBG_ERROR("Own binary format inside own container document!");
		}
	}
	else
	{
        // alien objects
        //TODO/LATER: a "StoreTo" method at embedded object would be nice
		rDestStg.SetVersion( SOFFICE_FILEFORMAT_31 );
        uno::Reference < embed::XStorage > xStor = ::comphelper::OStorageHelper::GetTemporaryStorage();
        uno::Reference < embed::XEmbedPersist > xPers( rObj.GetObject(), uno::UNO_QUERY );
        if ( xPers.is() )
        {
            uno::Sequence < beans::PropertyValue > aEmptySeq;
            ::rtl::OUString aTempName(::rtl::OUString::createFromAscii("bla"));
            try
            {
                xPers->storeToEntry( xStor, aTempName, aEmptySeq, aEmptySeq );
            }
            catch ( uno::Exception& )
            {}

            SotStorageRef xOLEStor = SotStorage::OpenOLEStorage( xStor, aTempName, STREAM_STD_READ );
            xOLEStor->CopyTo( &rDestStg );
            rDestStg.Commit();
        }
	}

    //We never need this stream: See #99809# and #i2179#
    rDestStg.Remove(CREATE_CONST_ASC(SVEXT_PERSIST_STREAM));
}



