/**************************************************************
 * 
 * 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 trough
			case OLEIVERB_OPEN:
				OSL_ENSURE(m_pDocHolder,"no document to open");

				// the commented code could be usefull 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

