/**************************************************************
 *
 * 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_embeddedobj.hxx"
#include <com/sun/star/embed/ElementModes.hpp>
#include <com/sun/star/embed/EntryInitModes.hpp>
#include <com/sun/star/document/XTypeDetection.hpp>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/container/XNameAccess.hpp>

#include <rtl/logfile.hxx>


#include "xfactory.hxx"
#include "commonembobj.hxx"
#include "specialobject.hxx"
#include "oleembobj.hxx"


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

//-------------------------------------------------------------------------
uno::Sequence< ::rtl::OUString > SAL_CALL OOoEmbeddedObjectFactory::impl_staticGetSupportedServiceNames()
{
    uno::Sequence< ::rtl::OUString > aRet(2);
    aRet[0] = ::rtl::OUString::createFromAscii("com.sun.star.embed.OOoEmbeddedObjectFactory");
    aRet[1] = ::rtl::OUString::createFromAscii("com.sun.star.comp.embed.OOoEmbeddedObjectFactory");
    return aRet;
}

//-------------------------------------------------------------------------
::rtl::OUString SAL_CALL OOoEmbeddedObjectFactory::impl_staticGetImplementationName()
{
    return ::rtl::OUString::createFromAscii("com.sun.star.comp.embed.OOoEmbeddedObjectFactory");
}

//-------------------------------------------------------------------------
uno::Reference< uno::XInterface > SAL_CALL OOoEmbeddedObjectFactory::impl_staticCreateSelfInstance(
			const uno::Reference< lang::XMultiServiceFactory >& xServiceManager )
{
	return uno::Reference< uno::XInterface >( *new OOoEmbeddedObjectFactory( xServiceManager ) );
}

//-------------------------------------------------------------------------
uno::Reference< uno::XInterface > SAL_CALL OOoEmbeddedObjectFactory::createInstanceInitFromEntry(
																	const uno::Reference< embed::XStorage >& xStorage,
																	const ::rtl::OUString& sEntName,
																	const uno::Sequence< beans::PropertyValue >& aMediaDescr,
																	const uno::Sequence< beans::PropertyValue >& lObjArgs )
	throw ( lang::IllegalArgumentException,
			container::NoSuchElementException,
			io::IOException,
			uno::Exception,
			uno::RuntimeException)
{
	RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OOoEmbeddedObjectFactory::createInstanceInitFromEntry" );

	if ( !xStorage.is() )
		throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "No parent storage is provided!\n" ),
											uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ),
											1 );

	if ( !sEntName.getLength() )
		throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "Empty element name is provided!\n" ),
											uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ),
											2 );

	uno::Reference< container::XNameAccess > xNameAccess( xStorage, uno::UNO_QUERY );
	if ( !xNameAccess.is() )
		throw uno::RuntimeException(); //TODO

	// detect entry existence
	if ( !xNameAccess->hasByName( sEntName ) )
		throw container::NoSuchElementException();

	uno::Reference< uno::XInterface > xResult;
	if ( xStorage->isStorageElement( sEntName ) )
	{
		// the object must be based on storage
		uno::Reference< embed::XStorage > xSubStorage =
				xStorage->openStorageElement( sEntName, embed::ElementModes::READ );

		uno::Reference< beans::XPropertySet > xPropSet( xSubStorage, uno::UNO_QUERY );
		if ( !xPropSet.is() )
			throw uno::RuntimeException();

		::rtl::OUString aMediaType;
		try {
			uno::Any aAny = xPropSet->getPropertyValue( ::rtl::OUString::createFromAscii( "MediaType" ) );
			aAny >>= aMediaType;
		}
		catch ( uno::Exception& )
		{
		}

		try {
			uno::Reference< lang::XComponent > xComp( xSubStorage, uno::UNO_QUERY );
			if ( xComp.is() )
				xComp->dispose();
		}
		catch ( uno::Exception& )
		{
		}
		xSubStorage = uno::Reference< embed::XStorage >();

#if 0
		::rtl::OUString aDocServiceName = m_aConfigHelper.GetDocumentServiceFromMediaType( aMediaType );
		if ( !aDocServiceName.getLength() )
		{
			// only own document can be based on storage
			// in case it is not possible to find related
			// document service name the storage entry is invalid

			throw io::IOException(); // unexpected mimetype of the storage
		}
#endif

		uno::Sequence< beans::NamedValue > aObject = m_aConfigHelper.GetObjectPropsByMediaType( aMediaType );
		if ( !aObject.getLength() )
			throw io::IOException(); // unexpected mimetype of the storage

		xResult = uno::Reference< uno::XInterface >(
					static_cast< ::cppu::OWeakObject* > ( new OCommonEmbeddedObject(
												m_xFactory,
												aObject ) ),
#if 0
												GetClassIDFromServName( aDocServiceName ),
												GetClassNameFromServName( aDocServiceName ),
												aDocServiceName ) ),
#endif
					uno::UNO_QUERY );
	}
	else
	{
		// the object must be OOo embedded object, if it is not an exception must be thrown
		throw io::IOException(); // TODO:
	}

	uno::Reference< embed::XEmbedPersist > xPersist( xResult, uno::UNO_QUERY );

	if ( !xPersist.is() )
		throw uno::RuntimeException(); // TODO: the interface must be supported by own document objects

	xPersist->setPersistentEntry( xStorage,
									sEntName,
									embed::EntryInitModes::DEFAULT_INIT,
									aMediaDescr,
									lObjArgs );

	return xResult;
}

//-------------------------------------------------------------------------
uno::Reference< uno::XInterface > SAL_CALL OOoEmbeddedObjectFactory::createInstanceInitFromMediaDescriptor(
		const uno::Reference< embed::XStorage >& xStorage,
		const ::rtl::OUString& sEntName,
		const uno::Sequence< beans::PropertyValue >& aMediaDescr,
		const uno::Sequence< beans::PropertyValue >& lObjArgs )
	throw ( lang::IllegalArgumentException,
			io::IOException,
			uno::Exception,
			uno::RuntimeException)
{
	RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OOoEmbeddedObjectFactory::createInstanceInitFromMediaDescriptor" );

	if ( !xStorage.is() )
		throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "No parent storage is provided!\n" ),
											uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ),
											1 );

	if ( !sEntName.getLength() )
		throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "Empty element name is provided!\n" ),
											uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ),
											2 );

	uno::Sequence< beans::PropertyValue > aTempMedDescr( aMediaDescr );

	// check if there is FilterName
	::rtl::OUString aFilterName = m_aConfigHelper.UpdateMediaDescriptorWithFilterName( aTempMedDescr, sal_False );

	uno::Reference< uno::XInterface > xResult;

	// find document service name
	if ( aFilterName.getLength() )
	{
		uno::Sequence< beans::NamedValue > aObject = m_aConfigHelper.GetObjectPropsByFilter( aFilterName );
		if ( !aObject.getLength() )
			throw io::IOException(); // unexpected mimetype of the storage


		xResult = uno::Reference< uno::XInterface >(
					static_cast< ::cppu::OWeakObject* > ( new OCommonEmbeddedObject(
											m_xFactory,
											aObject ) ),
					uno::UNO_QUERY );
	}
	else
	{
		// the object must be OOo embedded object, if it is not an exception must be thrown
		throw io::IOException(); // TODO:
	}

	uno::Reference< embed::XEmbedPersist > xPersist( xResult, uno::UNO_QUERY );

	if ( !xPersist.is() )
		throw uno::RuntimeException(); // TODO: the interface must be supported ( what about applets? )

	xPersist->setPersistentEntry( xStorage,
									sEntName,
									embed::EntryInitModes::MEDIA_DESCRIPTOR_INIT,
									aTempMedDescr,
									lObjArgs );

	return xResult;
}

//-------------------------------------------------------------------------
uno::Reference< uno::XInterface > SAL_CALL OOoEmbeddedObjectFactory::createInstanceInitNew(
											const uno::Sequence< sal_Int8 >& aClassID,
											const ::rtl::OUString& /*aClassName*/,
											const uno::Reference< embed::XStorage >& xStorage,
											const ::rtl::OUString& sEntName,
											const uno::Sequence< beans::PropertyValue >& lObjArgs )
	throw ( lang::IllegalArgumentException,
			io::IOException,
			uno::Exception,
			uno::RuntimeException)
{
	RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OOoEmbeddedObjectFactory::createInstanceInitNew" );

	uno::Reference< uno::XInterface > xResult;

	if ( !xStorage.is() )
		throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "No parent storage is provided!\n" ),
											uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ),
											3 );

	if ( !sEntName.getLength() )
		throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "Empty element name is provided!\n" ),
											uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ),
											4 );

	uno::Sequence< beans::NamedValue > aObject = m_aConfigHelper.GetObjectPropsByClassID( aClassID );
	if ( !aObject.getLength() )
		throw io::IOException(); // unexpected mimetype of the storage

	xResult = uno::Reference< uno::XInterface >(
					static_cast< ::cppu::OWeakObject* > ( new OCommonEmbeddedObject(
												m_xFactory,
												aObject ) ),
					uno::UNO_QUERY );


	uno::Reference< embed::XEmbedPersist > xPersist( xResult, uno::UNO_QUERY );

	if ( !xPersist.is() )
		throw uno::RuntimeException(); // TODO: the interface must be supported by own document objects

	xPersist->setPersistentEntry( xStorage,
									sEntName,
									embed::EntryInitModes::TRUNCATE_INIT,
									uno::Sequence< beans::PropertyValue >(),
									lObjArgs );

	return xResult;
}

//-------------------------------------------------------------------------
uno::Reference< uno::XInterface > SAL_CALL OOoEmbeddedObjectFactory::createInstanceUserInit(
			const uno::Sequence< sal_Int8 >& aClassID,
			const ::rtl::OUString& /*aClassName*/,
			const uno::Reference< embed::XStorage >& xStorage,
			const ::rtl::OUString& sEntName,
			sal_Int32 nEntryConnectionMode,
			const uno::Sequence< beans::PropertyValue >& lArguments,
			const uno::Sequence< beans::PropertyValue >& lObjArgs )
	throw ( lang::IllegalArgumentException,
			io::IOException,
			uno::Exception,
			uno::RuntimeException )
{
	RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OOoEmbeddedObjectFactory::createInstanceUserInit" );

	// the initialization is completely controlled by user
	if ( !xStorage.is() )
		throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "No parent storage is provided!\n" ),
											uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ),
											1 );

	if ( !sEntName.getLength() )
		throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "Empty element name is provided!\n" ),
											uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ),
											2 );

	uno::Sequence< beans::NamedValue > aObject = m_aConfigHelper.GetObjectPropsByClassID( aClassID );
	if ( !aObject.getLength() )
		throw io::IOException(); // unexpected mimetype of the storage

	uno::Sequence< beans::PropertyValue > aTempMedDescr( lArguments );
	if ( nEntryConnectionMode == embed::EntryInitModes::MEDIA_DESCRIPTOR_INIT )
	{
		::rtl::OUString aFilterName = m_aConfigHelper.UpdateMediaDescriptorWithFilterName( aTempMedDescr, aObject );
		if ( !aFilterName.getLength() )
		// the object must be OOo embedded object, if it is not an exception must be thrown
			throw io::IOException(); // TODO:
	}

	uno::Reference< uno::XInterface > xResult = uno::Reference< uno::XInterface > (
					static_cast< ::cppu::OWeakObject* > ( new OCommonEmbeddedObject(
												m_xFactory,
												aObject ) ),
					uno::UNO_QUERY );

	uno::Reference< embed::XEmbedPersist > xPersist( xResult, uno::UNO_QUERY );
	if ( xPersist.is() )
	{
		xPersist->setPersistentEntry( xStorage,
									sEntName,
									nEntryConnectionMode,
									aTempMedDescr,
									lObjArgs );

	}
	else
		throw uno::RuntimeException(); // TODO:

	return xResult;
}


//-------------------------------------------------------------------------
uno::Reference< uno::XInterface > SAL_CALL OOoEmbeddedObjectFactory::createInstanceLink(
											const uno::Reference< embed::XStorage >& /*xStorage*/,
											const ::rtl::OUString& /*sEntName*/,
											const uno::Sequence< beans::PropertyValue >& aMediaDescr,
											const uno::Sequence< beans::PropertyValue >& lObjArgs )
		throw ( lang::IllegalArgumentException,
				io::IOException,
				uno::Exception,
				uno::RuntimeException )
{
	RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OOoEmbeddedObjectFactory::createInstanceLink" );

	uno::Reference< uno::XInterface > xResult;

	uno::Sequence< beans::PropertyValue > aTempMedDescr( aMediaDescr );

	// check if there is URL, URL must exist
	::rtl::OUString aURL;
	for ( sal_Int32 nInd = 0; nInd < aTempMedDescr.getLength(); nInd++ )
		if ( aTempMedDescr[nInd].Name.equalsAscii( "URL" ) )
			aTempMedDescr[nInd].Value >>= aURL;

	if ( !aURL.getLength() )
		throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "No URL for the link is provided!\n" ),
										uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ),
										3 );

	::rtl::OUString aFilterName = m_aConfigHelper.UpdateMediaDescriptorWithFilterName( aTempMedDescr, sal_False );

	if ( aFilterName.getLength() )
	{
		uno::Sequence< beans::NamedValue > aObject = m_aConfigHelper.GetObjectPropsByFilter( aFilterName );
		if ( !aObject.getLength() )
			throw io::IOException(); // unexpected mimetype of the storage


		xResult = uno::Reference< uno::XInterface >(
					static_cast< ::cppu::OWeakObject* > ( new OCommonEmbeddedObject(
											m_xFactory,
											aObject,
											aTempMedDescr,
											lObjArgs ) ),
					uno::UNO_QUERY );
	}
	else
	{
		// the object must be OOo embedded object, if it is not an exception must be thrown
		throw io::IOException(); // TODO:
	}

	return xResult;
}

//-------------------------------------------------------------------------
uno::Reference< uno::XInterface > SAL_CALL OOoEmbeddedObjectFactory::createInstanceLinkUserInit(
												const uno::Sequence< sal_Int8 >& aClassID,
												const ::rtl::OUString& /*aClassName*/,
												const uno::Reference< embed::XStorage >& xStorage,
												const ::rtl::OUString& sEntName,
												const uno::Sequence< beans::PropertyValue >& lArguments,
												const uno::Sequence< beans::PropertyValue >& lObjArgs )
		throw ( lang::IllegalArgumentException,
				io::IOException,
				uno::Exception,
				uno::RuntimeException )
{
	RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OOoEmbeddedObjectFactory::createInstanceLinkUserInit" );

	uno::Reference< uno::XInterface > xResult;

	// the initialization is completely controlled by user
	if ( !xStorage.is() )
		throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "No parent storage is provided!\n" ),
											uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ),
											1 );

	if ( !sEntName.getLength() )
		throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "Empty element name is provided!\n" ),
											uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ),
											2 );

	uno::Sequence< beans::PropertyValue > aTempMedDescr( lArguments );

	::rtl::OUString aURL;
	for ( sal_Int32 nInd = 0; nInd < aTempMedDescr.getLength(); nInd++ )
		if ( aTempMedDescr[nInd].Name.equalsAscii( "URL" ) )
			aTempMedDescr[nInd].Value >>= aURL;

	if ( !aURL.getLength() )
		throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "No URL for the link is provided!\n" ),
										uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ),
										3 );

	uno::Sequence< beans::NamedValue > aObject = m_aConfigHelper.GetObjectPropsByClassID( aClassID );
	if ( !aObject.getLength() )
		throw io::IOException(); // unexpected mimetype of the storage

	::rtl::OUString aFilterName = m_aConfigHelper.UpdateMediaDescriptorWithFilterName( aTempMedDescr, aObject );

	if ( aFilterName.getLength() )
	{

		xResult = uno::Reference< uno::XInterface >(
					static_cast< ::cppu::OWeakObject* > ( new OCommonEmbeddedObject(
											m_xFactory,
											aObject,
											aTempMedDescr,
											lObjArgs ) ),
					uno::UNO_QUERY );
	}
	else
	{
		// the object must be OOo embedded object, if it is not an exception must be thrown
		throw io::IOException(); // TODO:
	}

	return xResult;
}

//-------------------------------------------------------------------------
::rtl::OUString SAL_CALL OOoEmbeddedObjectFactory::getImplementationName()
	throw ( uno::RuntimeException )
{
	return impl_staticGetImplementationName();
}

//-------------------------------------------------------------------------
sal_Bool SAL_CALL OOoEmbeddedObjectFactory::supportsService( const ::rtl::OUString& ServiceName )
	throw ( uno::RuntimeException )
{
	uno::Sequence< ::rtl::OUString > aSeq = impl_staticGetSupportedServiceNames();

	for ( sal_Int32 nInd = 0; nInd < aSeq.getLength(); nInd++ )
    	if ( ServiceName.compareTo( aSeq[nInd] ) == 0 )
        	return sal_True;

	return sal_False;
}

//-------------------------------------------------------------------------
uno::Sequence< ::rtl::OUString > SAL_CALL OOoEmbeddedObjectFactory::getSupportedServiceNames()
	throw ( uno::RuntimeException )
{
	return impl_staticGetSupportedServiceNames();
}

//-------------------------------------------------------------------------
uno::Sequence< ::rtl::OUString > SAL_CALL OOoSpecialEmbeddedObjectFactory::impl_staticGetSupportedServiceNames()
{
    uno::Sequence< ::rtl::OUString > aRet(2);
    aRet[0] = ::rtl::OUString::createFromAscii("com.sun.star.embed.OOoSpecialEmbeddedObjectFactory");
    aRet[1] = ::rtl::OUString::createFromAscii("com.sun.star.comp.embed.OOoSpecialEmbeddedObjectFactory");
    return aRet;
}

//-------------------------------------------------------------------------
::rtl::OUString SAL_CALL OOoSpecialEmbeddedObjectFactory::impl_staticGetImplementationName()
{
    return ::rtl::OUString::createFromAscii("com.sun.star.comp.embed.OOoSpecialEmbeddedObjectFactory");
}

//-------------------------------------------------------------------------
uno::Reference< uno::XInterface > SAL_CALL OOoSpecialEmbeddedObjectFactory::impl_staticCreateSelfInstance(
			const uno::Reference< lang::XMultiServiceFactory >& xServiceManager )
{
    return uno::Reference< uno::XInterface >( *new OOoSpecialEmbeddedObjectFactory( xServiceManager ) );
}

//-------------------------------------------------------------------------
uno::Reference< uno::XInterface > SAL_CALL OOoSpecialEmbeddedObjectFactory::createInstanceUserInit(
			const uno::Sequence< sal_Int8 >& aClassID,
			const ::rtl::OUString& /*aClassName*/,
			const uno::Reference< embed::XStorage >& /*xStorage*/,
			const ::rtl::OUString& /*sEntName*/,
			sal_Int32 /*nEntryConnectionMode*/,
			const uno::Sequence< beans::PropertyValue >& /*lArguments*/,
			const uno::Sequence< beans::PropertyValue >& /*lObjArgs*/ )
	throw ( lang::IllegalArgumentException,
			io::IOException,
			uno::Exception,
			uno::RuntimeException )
{
	uno::Sequence< beans::NamedValue > aObject = m_aConfigHelper.GetObjectPropsByClassID( aClassID );
	if ( !aObject.getLength() )
		throw io::IOException(); // unexpected mimetype of the storage

	uno::Reference< uno::XInterface > xResult(
                    static_cast< ::cppu::OWeakObject* > ( new OSpecialEmbeddedObject(
												m_xFactory,
												aObject ) ),
					uno::UNO_QUERY );
	return xResult;
}

//-------------------------------------------------------------------------
::rtl::OUString SAL_CALL OOoSpecialEmbeddedObjectFactory::getImplementationName()
	throw ( uno::RuntimeException )
{
	return impl_staticGetImplementationName();
}

//-------------------------------------------------------------------------
sal_Bool SAL_CALL OOoSpecialEmbeddedObjectFactory::supportsService( const ::rtl::OUString& ServiceName )
	throw ( uno::RuntimeException )
{
	uno::Sequence< ::rtl::OUString > aSeq = impl_staticGetSupportedServiceNames();

	for ( sal_Int32 nInd = 0; nInd < aSeq.getLength(); nInd++ )
    	if ( ServiceName.compareTo( aSeq[nInd] ) == 0 )
        	return sal_True;

	return sal_False;
}

//-------------------------------------------------------------------------
uno::Sequence< ::rtl::OUString > SAL_CALL OOoSpecialEmbeddedObjectFactory::getSupportedServiceNames()
	throw ( uno::RuntimeException )
{
	return impl_staticGetSupportedServiceNames();
}
