/**************************************************************
 * 
 * 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/EmbedStates.hpp>
#include <cppuhelper/weak.hxx>

#include "intercept.hxx"
#include "docholder.hxx"
#include "commonembobj.hxx"

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


#define IUL 6


uno::Sequence< ::rtl::OUString > Interceptor::m_aInterceptedURL(IUL);

struct equalOUString
{
	bool operator()( 
		const rtl::OUString& rKey1,
		const rtl::OUString& rKey2 ) const
	{
		return !!( rKey1 == rKey2 );
	}
};


struct hashOUString
{
	size_t operator()( const rtl::OUString& rName ) const
	{
		return rName.hashCode();
	}
};



class StatusChangeListenerContainer
	: public ::cppu::OMultiTypeInterfaceContainerHelperVar<
rtl::OUString,hashOUString,equalOUString>
{
public:
	StatusChangeListenerContainer( ::osl::Mutex& aMutex )
		:  cppu::OMultiTypeInterfaceContainerHelperVar<
	rtl::OUString,hashOUString,equalOUString>(aMutex)
	{
	}
};


void Interceptor::DisconnectDocHolder()
{
	osl::MutexGuard aGuard( m_aMutex );
	m_pDocHolder = NULL;
}

void SAL_CALL
Interceptor::addEventListener( 
	const uno::Reference<lang::XEventListener >& Listener )
	throw( uno::RuntimeException )
{
	osl::MutexGuard aGuard( m_aMutex );
	
	if ( ! m_pDisposeEventListeners )
		m_pDisposeEventListeners =
			new cppu::OInterfaceContainerHelper( m_aMutex );
	
	m_pDisposeEventListeners->addInterface( Listener );
}


void SAL_CALL
Interceptor::removeEventListener( 
	const uno::Reference< lang::XEventListener >& Listener )
	throw( uno::RuntimeException )
{
	osl::MutexGuard aGuard( m_aMutex );
	
	if ( m_pDisposeEventListeners )
		m_pDisposeEventListeners->removeInterface( Listener );
}


Interceptor::Interceptor( DocumentHolder* pDocHolder )
	: m_pDocHolder( pDocHolder ),
	  m_pDisposeEventListeners(0),
	  m_pStatCL(0)
{
	m_aInterceptedURL[0] = rtl::OUString(
		RTL_CONSTASCII_USTRINGPARAM(".uno:Save"));
	m_aInterceptedURL[1] = rtl::OUString(
		RTL_CONSTASCII_USTRINGPARAM(".uno:SaveAll"));
	m_aInterceptedURL[2] = rtl::OUString(
		RTL_CONSTASCII_USTRINGPARAM(".uno:CloseDoc"));	
	m_aInterceptedURL[3] = rtl::OUString(
		RTL_CONSTASCII_USTRINGPARAM(".uno:CloseWin"));	
	m_aInterceptedURL[4] = rtl::OUString(
		RTL_CONSTASCII_USTRINGPARAM(".uno:CloseFrame"));	
	m_aInterceptedURL[5] = rtl::OUString(
		RTL_CONSTASCII_USTRINGPARAM(".uno:SaveAs"));

}


Interceptor::~Interceptor()
{
	if( m_pDisposeEventListeners )
		delete m_pDisposeEventListeners;

	if(m_pStatCL)
		delete m_pStatCL;
}



//XDispatch
void SAL_CALL 
Interceptor::dispatch( 
	const util::URL& URL,
	const uno::Sequence<
	beans::PropertyValue >& Arguments )
	throw (uno::RuntimeException)
{
	osl::MutexGuard aGuard(m_aMutex);
	if( m_pDocHolder )
	{
		if(URL.Complete == m_aInterceptedURL[0])
			m_pDocHolder->GetEmbedObject()->SaveObject_Impl();
		else if(URL.Complete == m_aInterceptedURL[2] ||
				URL.Complete == m_aInterceptedURL[3] ||
				URL.Complete == m_aInterceptedURL[4])
		{
			try {
				m_pDocHolder->GetEmbedObject()->changeState( embed::EmbedStates::RUNNING );
			}
			catch( uno::Exception& )
			{
			}
		}
		else if ( URL.Complete == m_aInterceptedURL[5] )
		{
			uno::Sequence< beans::PropertyValue > aNewArgs = Arguments;
			sal_Int32 nInd = 0;

			while( nInd < aNewArgs.getLength() )
			{
				if ( aNewArgs[nInd].Name.equalsAscii( "SaveTo" ) )
				{
					aNewArgs[nInd].Value <<= sal_True;
					break;
				}
				nInd++;
			}
			
			if ( nInd == aNewArgs.getLength() )
			{
				aNewArgs.realloc( nInd + 1 );
				aNewArgs[nInd].Name = ::rtl::OUString::createFromAscii( "SaveTo" );
				aNewArgs[nInd].Value <<= sal_True;
			}

			uno::Reference< frame::XDispatch > xDispatch = m_xSlaveDispatchProvider->queryDispatch(
				URL, ::rtl::OUString::createFromAscii( "_self" ), 0 );
			if ( xDispatch.is() )
				xDispatch->dispatch( URL, aNewArgs );
		}
	}
}

void SAL_CALL
Interceptor::addStatusListener( 
	const uno::Reference< 
	frame::XStatusListener >& Control, 
	const util::URL& URL )
	throw (
		uno::RuntimeException
	)
{
	if(!Control.is())
		return;
	
	if(URL.Complete == m_aInterceptedURL[0]) 
	{   // Save
		frame::FeatureStateEvent aStateEvent;
		aStateEvent.FeatureURL.Complete = m_aInterceptedURL[0];
		aStateEvent.FeatureDescriptor = rtl::OUString(
			RTL_CONSTASCII_USTRINGPARAM("Update"));
		aStateEvent.IsEnabled = sal_True;
		aStateEvent.Requery = sal_False;
		aStateEvent.State <<= (rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("($1) ")) + m_pDocHolder->GetTitle() );
		Control->statusChanged(aStateEvent);
		
		{
			osl::MutexGuard aGuard(m_aMutex);
			if(!m_pStatCL)
				m_pStatCL = 
					new StatusChangeListenerContainer(m_aMutex);
		}
		
		m_pStatCL->addInterface(URL.Complete,Control);
		return;
	}
	
	sal_Int32 i = 2;
	if(URL.Complete == m_aInterceptedURL[i] ||
	   URL.Complete == m_aInterceptedURL[++i] ||
	   URL.Complete == m_aInterceptedURL[++i] )
	{   // Close and return
		frame::FeatureStateEvent aStateEvent;
		aStateEvent.FeatureURL.Complete = m_aInterceptedURL[i];
		aStateEvent.FeatureDescriptor = rtl::OUString(
			RTL_CONSTASCII_USTRINGPARAM("Close and Return"));
		aStateEvent.IsEnabled = sal_True;
		aStateEvent.Requery = sal_False;
		aStateEvent.State <<= (rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("($2) ")) + m_pDocHolder->GetTitle() );
		Control->statusChanged(aStateEvent);
		
		
		{
			osl::MutexGuard aGuard(m_aMutex);
			if(!m_pStatCL)
				m_pStatCL = 
					new StatusChangeListenerContainer(m_aMutex);
		}
		
		m_pStatCL->addInterface(URL.Complete,Control);
		return;
	}

	if(URL.Complete == m_aInterceptedURL[5]) 
	{   // SaveAs
		frame::FeatureStateEvent aStateEvent;
		aStateEvent.FeatureURL.Complete = m_aInterceptedURL[5];
		aStateEvent.FeatureDescriptor = rtl::OUString(
			RTL_CONSTASCII_USTRINGPARAM("SaveCopyTo"));
		aStateEvent.IsEnabled = sal_True;
		aStateEvent.Requery = sal_False;
		aStateEvent.State <<= (rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("($3)")));
		Control->statusChanged(aStateEvent);
		
		{
			osl::MutexGuard aGuard(m_aMutex);
			if(!m_pStatCL)
				m_pStatCL = 
					new StatusChangeListenerContainer(m_aMutex);
		}
		
		m_pStatCL->addInterface(URL.Complete,Control);
		return;
	}

}


void SAL_CALL
Interceptor::removeStatusListener(
	const uno::Reference< 
	frame::XStatusListener >& Control, 
	const util::URL& URL ) 
	throw (
		uno::RuntimeException
	)
{
	if(!(Control.is() && m_pStatCL))
		return;
	else {
		m_pStatCL->removeInterface(URL.Complete,Control);
		return;
	}
}


//XInterceptorInfo
uno::Sequence< ::rtl::OUString > 
SAL_CALL 
Interceptor::getInterceptedURLs(  )
	throw (
		uno::RuntimeException
	)
{
	// now implemented as update
	
	return m_aInterceptedURL;
}


// XDispatchProvider

uno::Reference< frame::XDispatch > SAL_CALL
Interceptor::queryDispatch( 
	const util::URL& URL,
	const ::rtl::OUString& TargetFrameName, 
	sal_Int32 SearchFlags )
	throw (
		uno::RuntimeException
	)
{
	osl::MutexGuard aGuard(m_aMutex);
	if(URL.Complete == m_aInterceptedURL[0])
		return (frame::XDispatch*)this;
	else if(URL.Complete == m_aInterceptedURL[1])
		return (frame::XDispatch*)0   ;
	else if(URL.Complete == m_aInterceptedURL[2])
		return (frame::XDispatch*)this;
	else if(URL.Complete == m_aInterceptedURL[3])
		return (frame::XDispatch*)this;
	else if(URL.Complete == m_aInterceptedURL[4])
		return (frame::XDispatch*)this;
	else if(URL.Complete == m_aInterceptedURL[5])
		return (frame::XDispatch*)this;
	else {
		if(m_xSlaveDispatchProvider.is())
			return m_xSlaveDispatchProvider->queryDispatch(
				URL,TargetFrameName,SearchFlags);
		else
			return uno::Reference<frame::XDispatch>(0);
	}
}

uno::Sequence< uno::Reference< frame::XDispatch > > SAL_CALL
Interceptor::queryDispatches(
	const uno::Sequence<frame::DispatchDescriptor >& Requests )
	throw (
		uno::RuntimeException
	)
{
	uno::Sequence< uno::Reference< frame::XDispatch > > aRet;
	osl::MutexGuard aGuard(m_aMutex);
	if(m_xSlaveDispatchProvider.is())
		aRet = m_xSlaveDispatchProvider->queryDispatches(Requests);
	else
		aRet.realloc(Requests.getLength());
	
	for(sal_Int32 i = 0; i < Requests.getLength(); ++i)
		if(m_aInterceptedURL[0] == Requests[i].FeatureURL.Complete)
			aRet[i] = (frame::XDispatch*) this;
		else if(m_aInterceptedURL[1] == Requests[i].FeatureURL.Complete)
			aRet[i] = (frame::XDispatch*) 0;
		else if(m_aInterceptedURL[2] == Requests[i].FeatureURL.Complete)
			aRet[i] = (frame::XDispatch*) this;
		else if(m_aInterceptedURL[3] == Requests[i].FeatureURL.Complete)
			aRet[i] = (frame::XDispatch*) this;
		else if(m_aInterceptedURL[4] == Requests[i].FeatureURL.Complete)
			aRet[i] = (frame::XDispatch*) this;
		else if(m_aInterceptedURL[5] == Requests[i].FeatureURL.Complete)
			aRet[i] = (frame::XDispatch*) this;

	return aRet;
}



//XDispatchProviderInterceptor

uno::Reference< frame::XDispatchProvider > SAL_CALL 
Interceptor::getSlaveDispatchProvider(  ) 
	throw (
		uno::RuntimeException
	)
{
	osl::MutexGuard aGuard(m_aMutex);
	return m_xSlaveDispatchProvider;
}

void SAL_CALL
Interceptor::setSlaveDispatchProvider( 
	const uno::Reference< frame::XDispatchProvider >& NewDispatchProvider )
	throw (
		uno::RuntimeException
	)
{
	osl::MutexGuard aGuard(m_aMutex);
	m_xSlaveDispatchProvider = NewDispatchProvider;
}


uno::Reference< frame::XDispatchProvider > SAL_CALL
Interceptor::getMasterDispatchProvider(  ) 
	throw (
		uno::RuntimeException
	)
{
	osl::MutexGuard aGuard(m_aMutex);
	return m_xMasterDispatchProvider;	
}

	
void SAL_CALL
Interceptor::setMasterDispatchProvider( 
	const uno::Reference< frame::XDispatchProvider >& NewSupplier )
	throw (
		uno::RuntimeException
	)
{
	osl::MutexGuard aGuard(m_aMutex);
	m_xMasterDispatchProvider = NewSupplier;
}

