/**************************************************************
 *
 * 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.
 *
 *************************************************************/


#include <cppuhelper/weak.hxx>

#include <embeddoc.hxx>
#include <docholder.hxx>
#include <intercept.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 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 );
}


void SAL_CALL Interceptor::dispose()
	throw(::com::sun::star::uno::RuntimeException)
{
	lang::EventObject aEvt;
	aEvt.Source = static_cast< frame::XDispatch* >( this );

	osl::MutexGuard aGuard(m_aMutex);

	if ( m_pDisposeEventListeners && m_pDisposeEventListeners->getLength() )
		m_pDisposeEventListeners->disposeAndClear( aEvt );

	if(m_pStatCL)
		m_pStatCL->disposeAndClear( aEvt );

	m_xSlaveDispatchProvider = 0;
	m_xMasterDispatchProvider = 0;
}



Interceptor::Interceptor(
	const ::rtl::Reference< EmbeddedDocumentInstanceAccess_Impl >& xOleAccess,
	DocumentHolder* pDocH,
	sal_Bool bLink )
	: m_xOleAccess( xOleAccess ),
	  m_xDocHLocker( static_cast< ::cppu::OWeakObject* >( pDocH ) ),
	  m_pDocH(pDocH),
	  m_pStatCL(0),
	  m_pDisposeEventListeners(0),
	  m_bLink( bLink )
{
	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;

	DocumentHolder* pTmpDocH = NULL;
	uno::Reference< uno::XInterface > xLock;
	{
		osl::MutexGuard aGuard(m_aMutex);
		xLock = m_xDocHLocker.get();
		if ( xLock.is() )
			pTmpDocH = m_pDocH;
	}

	if ( pTmpDocH )
		pTmpDocH->ClearInterceptor();
}

void Interceptor::DisconnectDocHolder()
{
	osl::MutexGuard aGuard(m_aMutex);
	m_xDocHLocker.clear();
	m_pDocH = NULL;
	m_xOleAccess = NULL;
}

//XDispatch
void SAL_CALL
Interceptor::dispatch(
	const util::URL& URL,
	const uno::Sequence<
	beans::PropertyValue >& Arguments )
	throw (uno::RuntimeException)
{
	::rtl::Reference< EmbeddedDocumentInstanceAccess_Impl > xOleAccess;
	{
		osl::MutexGuard aGuard(m_aMutex);
		xOleAccess = m_xOleAccess;
	}

	if ( xOleAccess.is() )
	{
		LockedEmbedDocument_Impl aDocLock = xOleAccess->GetEmbedDocument();
		if ( aDocLock.GetEmbedDocument() )
		{
            if( !m_bLink && URL.Complete == m_aInterceptedURL[0])
                aDocLock.GetEmbedDocument()->SaveObject();
            else if(!m_bLink
                 && ( URL.Complete == m_aInterceptedURL[2] ||
                      URL.Complete == m_aInterceptedURL[3] ||
                      URL.Complete == m_aInterceptedURL[4] ) )
                aDocLock.GetEmbedDocument()->Close( 0 );
			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 Interceptor::generateFeatureStateEvent()
{
	if( m_pStatCL )
	{
		DocumentHolder* pTmpDocH = NULL;
		uno::Reference< uno::XInterface > xLock;
		{
			osl::MutexGuard aGuard(m_aMutex);
			xLock = m_xDocHLocker.get();
			if ( xLock.is() )
				pTmpDocH = m_pDocH;
		}

		::rtl::OUString aTitle;
		if ( pTmpDocH )
			aTitle = pTmpDocH->getTitle();

		for(int i = 0; i < IUL; ++i)
		{
			if( i == 1 || m_bLink && i != 5 )
				continue;

			cppu::OInterfaceContainerHelper* pICH =
				m_pStatCL->getContainer(m_aInterceptedURL[i]);
			uno::Sequence<uno::Reference<uno::XInterface> > aSeq;
			if(pICH)
				aSeq = pICH->getElements();
			if(!aSeq.getLength())
				continue;

			frame::FeatureStateEvent aStateEvent;
			aStateEvent.IsEnabled = sal_True;
			aStateEvent.Requery = sal_False;
			if(i == 0)
			{

				aStateEvent.FeatureURL.Complete = m_aInterceptedURL[0];
				aStateEvent.FeatureDescriptor = rtl::OUString(
					RTL_CONSTASCII_USTRINGPARAM("Update"));
				aStateEvent.State <<= (rtl::OUString(
					RTL_CONSTASCII_USTRINGPARAM("($1) ")) +
									   aTitle);

			}
			else if ( i == 5 )
			{
				aStateEvent.FeatureURL.Complete = m_aInterceptedURL[5];
				aStateEvent.FeatureDescriptor = rtl::OUString(
					RTL_CONSTASCII_USTRINGPARAM("SaveCopyTo"));
				aStateEvent.State <<= (rtl::OUString(
					RTL_CONSTASCII_USTRINGPARAM("($3)")));
			}
			else
			{
				aStateEvent.FeatureURL.Complete = m_aInterceptedURL[i];
				aStateEvent.FeatureDescriptor = rtl::OUString(
					RTL_CONSTASCII_USTRINGPARAM("Close and Return"));
				aStateEvent.State <<= (rtl::OUString(
					RTL_CONSTASCII_USTRINGPARAM("($2) ")) +
									   aTitle);

			}

			for(sal_Int32 k = 0; k < aSeq.getLength(); ++k)
			{
				uno::Reference<frame::XStatusListener>
					Control(aSeq[k],uno::UNO_QUERY);
				if(Control.is())
					Control->statusChanged(aStateEvent);

			}
		}
	}
}


void SAL_CALL
Interceptor::addStatusListener(
	const uno::Reference<
	frame::XStatusListener >& Control,
	const util::URL& URL )
	throw (
		uno::RuntimeException
	)
{
	if(!Control.is())
		return;

	if( !m_bLink && URL.Complete == m_aInterceptedURL[0] )
	{   // Save
		DocumentHolder* pTmpDocH = NULL;
		uno::Reference< uno::XInterface > xLock;
		{
			osl::MutexGuard aGuard(m_aMutex);
			xLock = m_xDocHLocker.get();
			if ( xLock.is() )
				pTmpDocH = m_pDocH;
		}

		::rtl::OUString aTitle;
		if ( pTmpDocH )
			aTitle = pTmpDocH->getTitle();

		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) ")) +
							   aTitle );
		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 ( !m_bLink
	  && ( URL.Complete == m_aInterceptedURL[i] ||
	       URL.Complete == m_aInterceptedURL[++i] ||
	       URL.Complete == m_aInterceptedURL[++i] ) )
	{   // Close and return
		DocumentHolder* pTmpDocH = NULL;
		uno::Reference< uno::XInterface > xLock;
		{
			osl::MutexGuard aGuard(m_aMutex);
			xLock = m_xDocHLocker.get();
			if ( xLock.is() )
				pTmpDocH = m_pDocH;
		}

		::rtl::OUString aTitle;
		if ( pTmpDocH )
			aTitle = pTmpDocH->getTitle();

		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) ")) +
							   aTitle );
		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
	if ( m_bLink )
	{
		uno::Sequence< ::rtl::OUString > aResult( 2 );
		aResult[0] = m_aInterceptedURL[1];
		aResult[1] = m_aInterceptedURL[5];

		return aResult;
	}

	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( !m_bLink && URL.Complete == m_aInterceptedURL[0] )
		return (frame::XDispatch*)this;
	else if(URL.Complete == m_aInterceptedURL[1])
		return (frame::XDispatch*)0   ;
	else if( !m_bLink && URL.Complete == m_aInterceptedURL[2] )
		return (frame::XDispatch*)this;
	else if( !m_bLink && URL.Complete == m_aInterceptedURL[3] )
		return (frame::XDispatch*)this;
	else if( !m_bLink && 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_bLink && 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_bLink && m_aInterceptedURL[2] == Requests[i].FeatureURL.Complete )
			aRet[i] = (frame::XDispatch*) this;
		else if( !m_bLink && m_aInterceptedURL[3] == Requests[i].FeatureURL.Complete )
			aRet[i] = (frame::XDispatch*) this;
		else if( !m_bLink && 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;
}

// Fix strange warnings about some
// ATL::CAxHostWindow::QueryInterface|AddRef|Releae functions.
// warning C4505: 'xxx' : unreferenced local function has been removed
#if defined(_MSC_VER)
#pragma warning(disable: 4505)
#endif
