/**************************************************************
 *
 * 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 "embeddoc.hxx"
#include <osl/diagnose.h>
#include <com/sun/star/frame/XController.hpp>
#include <com/sun/star/beans/PropertyValue.hpp>

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

extern ::rtl::OUString	getFilterNameFromGUID_Impl( GUID* );

//-------------------------------------------------------------------------------
// IOleObject

STDMETHODIMP EmbedDocument_Impl::SetClientSite( IOleClientSite* pSite )
{
	m_pClientSite = pSite;
	return S_OK;
}

STDMETHODIMP EmbedDocument_Impl::GetClientSite( IOleClientSite** pSite )
{
	*pSite = m_pClientSite;
	return S_OK;
}

STDMETHODIMP EmbedDocument_Impl::SetHostNames( LPCOLESTR szContainerApp, LPCOLESTR szContainerObj )
{
	// the code should be ignored for links
	if ( !m_aFileName.getLength() )
	{
		m_pDocHolder->setTitle(
			rtl::OUString(
				(sal_Unicode*)szContainerObj));
		m_pDocHolder->setContainerName(
			rtl::OUString(
				(sal_Unicode*)szContainerApp));
	}

	return S_OK;
}

STDMETHODIMP EmbedDocument_Impl::Close( DWORD dwSaveOption )
{
	HRESULT hr = S_OK;

	if ( m_pDocHolder->HasFrame() )
	{
		if ( dwSaveOption == 2 && m_aFileName.getLength() )
		{
			// ask the user about saving
			if ( m_pDocHolder->ExecuteSuspendCloseFrame() )
			{
				m_pDocHolder->CloseDocument();
				return S_OK;
			}
			else
				return OLE_E_PROMPTSAVECANCELLED;
		}

		if ( dwSaveOption != 1 )
			hr = SaveObject(); // ADVF_DATAONSTOP);

		m_pDocHolder->CloseFrame();
		OLENotifyDeactivation();
	}

	m_pDocHolder->FreeOffice();
	m_pDocHolder->CloseDocument();

	OLENotifyClosing();

	return hr;
}


HRESULT EmbedDocument_Impl::OLENotifyClosing()
{
	HRESULT hr = S_OK;

	AdviseSinkHashMap aAHM(m_aAdviseHashMap);

	for ( AdviseSinkHashMapIterator iAdvise = aAHM.begin();
		  iAdvise != aAHM.end(); iAdvise++ )
	{
		if ( iAdvise->second )
			iAdvise->second->OnClose();
	}

	return hr;

}

STDMETHODIMP EmbedDocument_Impl::SetMoniker( DWORD /*dwWhichMoniker*/, IMoniker * /*pmk*/ )
{
	return E_NOTIMPL;
}

STDMETHODIMP EmbedDocument_Impl::GetMoniker( DWORD /*dwAssign*/, DWORD /*dwWhichMoniker*/, IMoniker ** /*ppmk*/ )
{
	return E_NOTIMPL;
}

STDMETHODIMP EmbedDocument_Impl::InitFromData( IDataObject * /*pDataObject*/, BOOL /*fCreation*/, DWORD /*dwReserved*/ )
{
	return E_NOTIMPL;
}

STDMETHODIMP EmbedDocument_Impl::GetClipboardData( DWORD /*dwReserved*/, IDataObject ** /*ppDataObject*/ )
{
	return E_NOTIMPL;
}

/**
 *  Well, this is a not so very inefficient way to deliver
 *
 */

STDMETHODIMP EmbedDocument_Impl::DoVerb(
	LONG iVerb,
	LPMSG,
	IOleClientSite *pActiveSite,
	LONG,
	HWND,
	LPCRECT )
{
	// no locking is used since the OLE must use the same thread always
	if ( m_bIsInVerbHandling )
		return OLEOBJ_S_CANNOT_DOVERB_NOW;

	// an object can not handle any Verbs in Hands off mode
	if ( m_pMasterStorage == NULL || m_pOwnStream == NULL )
		return OLE_E_CANT_BINDTOSOURCE;


	BooleanGuard_Impl aGuard( m_bIsInVerbHandling );

	if ( iVerb == OLEIVERB_PRIMARY )
	{
		if ( m_aFileName.getLength() )
		{
			// that should be a link
			iVerb = OLEIVERB_OPEN;
		}
		else
			iVerb = OLEIVERB_SHOW;
	}

	try
	{
		switch(iVerb) {
			case OLEIVERB_DISCARDUNDOSTATE:
				// free any undostate?
				break;
			case OLEIVERB_INPLACEACTIVATE:
				OSL_ENSURE(m_pDocHolder,"no document for inplace activation");

				return m_pDocHolder->InPlaceActivate(pActiveSite,FALSE);
				break;
			case OLEIVERB_UIACTIVATE:
				OSL_ENSURE(m_pDocHolder,"no document for	 inplace activation");

				return m_pDocHolder->InPlaceActivate(pActiveSite,TRUE);
				break;
			case OLEIVERB_PRIMARY:
			case OLEIVERB_SHOW:
				OSL_ENSURE(m_pDocHolder,"no document for inplace activation");

				if(m_pDocHolder->isActive())
					return NOERROR; //Already active

				if(SUCCEEDED(
					m_pDocHolder->InPlaceActivate(
						pActiveSite,TRUE)))
					return NOERROR;

				// intended fall through
			case OLEIVERB_OPEN:
				OSL_ENSURE(m_pDocHolder,"no document to open");

				// the commented code could be useful in case
				// outer window would be resized depending from inner one
				// RECTL aEmbArea;
				// m_pDocHolder->GetVisArea( &aEmbArea );
				// m_pDocHolder->show();
				// m_pDocHolder->SetVisArea( &aEmbArea );

				if(m_pDocHolder->isActive())
				{
					m_pDocHolder->InPlaceDeactivate();
					m_pDocHolder->DisableInplaceActivation(true);
				}

				SIZEL aEmbSize;
				m_pDocHolder->GetExtent( &aEmbSize );
				m_pDocHolder->show();
				m_pDocHolder->resizeWin( aEmbSize );

				if ( m_pClientSite )
					m_pClientSite->OnShowWindow( TRUE );

				notify();
				break;
			case OLEIVERB_HIDE:
				OSL_ENSURE(m_pDocHolder,"no document to hide");

				if(m_pDocHolder->isActive())
					m_pDocHolder->InPlaceDeactivate();
				else {
					m_pDocHolder->hide();

					if( m_pClientSite )
						m_pClientSite->OnShowWindow(FALSE);
				}
				break;
			default:
				break;
		}
	}
	catch( uno::Exception& )
	{
		return OLEOBJ_S_CANNOT_DOVERB_NOW;
	}

	return NOERROR;
}



STDMETHODIMP EmbedDocument_Impl::EnumVerbs( IEnumOLEVERB ** /*ppEnumOleVerb*/ )
{
	return OLE_S_USEREG;
}

STDMETHODIMP EmbedDocument_Impl::Update()
{
	return S_OK;
//	HRESULT hr = CACHE_E_NOCACHE_UPDATED;
//	return hr;
}

STDMETHODIMP EmbedDocument_Impl::IsUpToDate()
{
	return S_OK;
}

STDMETHODIMP EmbedDocument_Impl::GetUserClassID( CLSID *pClsid )
{
	return GetClassID( pClsid );
}

STDMETHODIMP EmbedDocument_Impl::GetUserType( DWORD /*dwFormOfTypeUe*/, LPOLESTR * /*pszUserType*/ )
{
	return OLE_S_USEREG;
}

STDMETHODIMP EmbedDocument_Impl::SetExtent( DWORD /*dwDrawAspect*/, SIZEL *psizel )
{
	if ( !psizel )
		return E_FAIL;

	m_pDocHolder->SetExtent( psizel );

	return S_OK;
}

STDMETHODIMP EmbedDocument_Impl::GetExtent( DWORD /*dwDrawAspect*/, SIZEL * psizel )
{
	if ( !psizel )
		return E_INVALIDARG;

	if ( FAILED( m_pDocHolder->GetExtent( psizel ) ) )
	{
		// return default values
		psizel->cx = 500;
		psizel->cy = 500;
	}

	return S_OK;
}

STDMETHODIMP EmbedDocument_Impl::Advise( IAdviseSink *pAdvSink, DWORD *pdwConnection )
{
	if ( m_nAdviseNum == 0xFFFFFFFF )
		return E_OUTOFMEMORY;

	pAdvSink->AddRef();
	m_aAdviseHashMap.insert( ::std::pair< DWORD, IAdviseSink* >( m_nAdviseNum, pAdvSink ) );
	*pdwConnection = m_nAdviseNum++;

	return S_OK;
}

STDMETHODIMP EmbedDocument_Impl::Unadvise( DWORD dwConnection )
{
	AdviseSinkHashMapIterator iAdvise = m_aAdviseHashMap.find( dwConnection );
	if ( iAdvise != m_aAdviseHashMap.end() )
	{
		iAdvise->second->Release();
		m_aAdviseHashMap.erase( iAdvise );
	}
	else
		return OLE_E_NOCONNECTION;

	return S_OK;
}

STDMETHODIMP EmbedDocument_Impl::EnumAdvise( IEnumSTATDATA ** /*ppenumAdvise*/ )
{
	return E_NOTIMPL;
}

STDMETHODIMP EmbedDocument_Impl::GetMiscStatus( DWORD /*dwAspect*/, DWORD * /*pdwStatus*/ )
{
	return OLE_S_USEREG;
}

STDMETHODIMP EmbedDocument_Impl::SetColorScheme( LOGPALETTE * /*pLogpal*/ )
{
	return E_NOTIMPL;
}

//-------------------------------------------------------------------------------
// IDispatch

STDMETHODIMP EmbedDocument_Impl::GetTypeInfoCount( unsigned int FAR* pctinfo )
{
	if ( m_pDocHolder->GetIDispatch() )
		return m_pDocHolder->GetIDispatch()->GetTypeInfoCount( pctinfo );

	return E_NOTIMPL;
}

STDMETHODIMP EmbedDocument_Impl::GetTypeInfo( unsigned int iTInfo, LCID lcid, ITypeInfo FAR* FAR* ppTInfo )
{
	if ( m_pDocHolder->GetIDispatch() )
		return m_pDocHolder->GetIDispatch()->GetTypeInfo( iTInfo, lcid, ppTInfo );

	return DISP_E_BADINDEX; // the only error that can be returned
}

STDMETHODIMP EmbedDocument_Impl::GetIDsOfNames( REFIID riid,
												OLECHAR FAR* FAR* rgszNames,
												unsigned int cNames,
												LCID lcid,
												DISPID FAR* rgDispId )
{
	if ( m_pDocHolder->GetIDispatch() )
		return m_pDocHolder->GetIDispatch()->GetIDsOfNames( riid, rgszNames, cNames, lcid, rgDispId );

	for ( unsigned int ind = 0; ind < cNames; ind++ )
		rgDispId[ind] = DISPID_UNKNOWN;

	return DISP_E_UNKNOWNNAME;
}

STDMETHODIMP EmbedDocument_Impl::Invoke( DISPID dispIdMember,
										 REFIID riid,
										 LCID lcid,
										 WORD wFlags,
										 DISPPARAMS FAR* pDispParams,
										 VARIANT FAR* pVarResult,
										 EXCEPINFO FAR* pExcepInfo,
										 unsigned int FAR* puArgErr )
{
	if ( m_pDocHolder->GetIDispatch() )
		return m_pDocHolder->GetIDispatch()->Invoke( dispIdMember,
													 riid,
													 lcid,
													 wFlags,
													 pDispParams,
													 pVarResult,
													 pExcepInfo,
													 puArgErr );

	return DISP_E_MEMBERNOTFOUND;
}

//-------------------------------------------------------------------------------
// IExternalConnection

DWORD STDMETHODCALLTYPE EmbedDocument_Impl::AddConnection( DWORD , DWORD )
{
	return AddRef();
}

DWORD STDMETHODCALLTYPE EmbedDocument_Impl::ReleaseConnection( DWORD , DWORD , BOOL )
{
	return Release();
}

// C++ - methods

HRESULT EmbedDocument_Impl::SaveObject()
{
	HRESULT hr = S_OK;

	if(m_pClientSite) {
		hr = m_pClientSite->SaveObject();

		for ( AdviseSinkHashMapIterator iAdvise =
				  m_aAdviseHashMap.begin();
			  iAdvise != m_aAdviseHashMap.end();
			  iAdvise++ )
			if ( iAdvise->second )
				iAdvise->second->OnSave( );
	}
	else if ( m_aFileName.getLength() && IsDirty() == S_OK )
	{
		::rtl::OUString aPreservFileName = m_aFileName;

		// in case of links the containers does not provide client site sometimes
		hr = Save( (LPCOLESTR)NULL, FALSE ); // triggers saving to the link location
		SaveCompleted( (LPCOLESTR)aPreservFileName.getStr() );
	}

	notify( false );

	return hr;
}


HRESULT EmbedDocument_Impl::ShowObject()
{
	HRESULT hr = S_OK;

	if(m_pClientSite)
		hr = m_pClientSite->ShowObject();

	return hr;
}


void EmbedDocument_Impl::notify( bool bDataChanged )
{
	for ( AdviseSinkHashMapIterator iAdvise =
			  m_aAdviseHashMap.begin();
		  iAdvise != m_aAdviseHashMap.end();
		  iAdvise++ )
		if ( iAdvise->second )
			iAdvise->second->OnViewChange( DVASPECT_CONTENT, -1 );

	if ( m_pDAdviseHolder && bDataChanged )
		m_pDAdviseHolder->SendOnDataChange( (IDataObject*)this, 0, 0 );
}

void EmbedDocument_Impl::Deactivate()
{
	HRESULT hr = S_OK;

	if ( m_pDocHolder->HasFrame() )
	{
		hr = SaveObject();
		m_pDocHolder->CloseFrame();
		OLENotifyDeactivation();
	}
}

HRESULT EmbedDocument_Impl::OLENotifyDeactivation()
{
	HRESULT hr = S_OK;

	if ( m_pClientSite )
		hr = m_pClientSite->OnShowWindow( FALSE );

	return hr;

}

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

/* vim: set noet sw=4 ts=4: */
