/**************************************************************
 *
 * 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_svx.hxx"
#include <com/sun/star/lang/XServiceInfo.hpp>
#ifndef _COM_SUN_STAR_BEANS_PROPERTYSTATE_HDL_
#include <com/sun/star/beans/PropertyState.hpp>
#endif

#include <comphelper/propertysetinfo.hxx>
#include <rtl/uuid.h>
#include <vos/mutex.hxx>
#include <vcl/svapp.hxx>
#include "svx/unopool.hxx"
#include <svx/svdmodel.hxx>
#include <svx/svdpool.hxx>
#include <svx/unoprov.hxx>
#include <svx/svdobj.hxx>
#include <svx/unoshprp.hxx>
#include <svx/xflbstit.hxx>
#include <svx/xflbmtit.hxx>
#include <svx/unopage.hxx>
#include <svx/svdetc.hxx>
#include <editeng/editeng.hxx>

#include "svx/unoapi.hxx"
#include <memory>

using namespace ::com::sun::star;
using namespace ::rtl;
using namespace ::cppu;

SvxUnoDrawPool::SvxUnoDrawPool( SdrModel* pModel, sal_Int32 nServiceId ) throw()
: PropertySetHelper( SvxPropertySetInfoPool::getOrCreate( nServiceId ) ), mpModel( pModel )
{
	init();
}

/* deprecated */
SvxUnoDrawPool::SvxUnoDrawPool( SdrModel* pModel ) throw()
: PropertySetHelper( SvxPropertySetInfoPool::getOrCreate( SVXUNO_SERVICEID_COM_SUN_STAR_DRAWING_DEFAULTS ) ), mpModel( pModel )
{
	init();
}

SvxUnoDrawPool::~SvxUnoDrawPool() throw()
{
    // memory leak #119991#: to release the secondary pool created in function SvxUnoDrawPool::init()
    SfxItemPool* pSecondaryPool = mpDefaultsPool->GetSecondaryPool();

    // #119991# delete master pool first, this will reset the pMaster entry in pSecondaryPool as needed.
    // This is the needed order (see SdrModel::~SdrModel for example)
    SfxItemPool::Free(mpDefaultsPool);

    // delete pSecondaryPool if exists
    if(pSecondaryPool)
    {
        SfxItemPool::Free(pSecondaryPool);
    }
}

void SvxUnoDrawPool::init()
{
    mpDefaultsPool = new SdrItemPool();
	SfxItemPool* pOutlPool=EditEngine::CreatePool();
    mpDefaultsPool->SetSecondaryPool(pOutlPool);

    SdrModel::SetTextDefaults( mpDefaultsPool, SdrEngineDefaults::GetFontHeight() );
    mpDefaultsPool->SetDefaultMetric((SfxMapUnit)SdrEngineDefaults::GetMapUnit());
    mpDefaultsPool->FreezeIdRanges();
}

SfxItemPool* SvxUnoDrawPool::getModelPool( sal_Bool bReadOnly ) throw()
{
	if( mpModel	)
	{
		return &mpModel->GetItemPool();
	}
	else
	{
		if( bReadOnly )
            return mpDefaultsPool;
		else
			return NULL;
	}
}

void SvxUnoDrawPool::getAny( SfxItemPool* pPool, const comphelper::PropertyMapEntry* pEntry, uno::Any& rValue )
	throw(beans::UnknownPropertyException)
{
	switch( pEntry->mnHandle )
	{
	case OWN_ATTR_FILLBMP_MODE:
		{
			XFillBmpStretchItem* pStretchItem = (XFillBmpStretchItem*)&pPool->GetDefaultItem(XATTR_FILLBMP_STRETCH);
			XFillBmpTileItem* pTileItem = (XFillBmpTileItem*)&pPool->GetDefaultItem(XATTR_FILLBMP_TILE);
			if( pTileItem && pTileItem->GetValue() )
			{
				rValue <<= drawing::BitmapMode_REPEAT;
			}
			else if( pStretchItem && pStretchItem->GetValue() )
			{
				rValue <<= drawing::BitmapMode_STRETCH;
			}
			else
			{
				rValue <<= drawing::BitmapMode_NO_REPEAT;
			}
			break;
		}
    default:
		{
			const SfxMapUnit eMapUnit = pPool ? pPool->GetMetric((sal_uInt16)pEntry->mnHandle) : SFX_MAPUNIT_100TH_MM;

			sal_uInt8 nMemberId = pEntry->mnMemberId & (~SFX_METRIC_ITEM);
			if( eMapUnit == SFX_MAPUNIT_100TH_MM )
				nMemberId &= (~CONVERT_TWIPS);

            // DVO, OD 10.10.2003 #i18732#
            // Assure, that ID is a Which-ID (it could be a Slot-ID.)
            // Thus, convert handle to Which-ID.
            pPool->GetDefaultItem( pPool->GetWhich( (sal_uInt16)pEntry->mnHandle ) ).QueryValue( rValue, nMemberId );
		}
	}


	// check for needed metric translation
	const SfxMapUnit eMapUnit = pPool->GetMetric((sal_uInt16)pEntry->mnHandle);
	if(pEntry->mnMemberId & SFX_METRIC_ITEM && eMapUnit != SFX_MAPUNIT_100TH_MM)
	{
		SvxUnoConvertToMM( eMapUnit, rValue );
	}
	// convert int32 to correct enum type if needed
	else if ( pEntry->mpType->getTypeClass() == uno::TypeClass_ENUM && rValue.getValueType() == ::getCppuType((const sal_Int32*)0) )
	{
		sal_Int32 nEnum;
		rValue >>= nEnum;

		rValue.setValue( &nEnum, *pEntry->mpType );
	}
}

void SvxUnoDrawPool::putAny( SfxItemPool* pPool, const comphelper::PropertyMapEntry* pEntry, const uno::Any& rValue )
	throw(beans::UnknownPropertyException, lang::IllegalArgumentException)
{
	uno::Any aValue( rValue );

	const SfxMapUnit eMapUnit = pPool->GetMetric((sal_uInt16)pEntry->mnHandle);
	if(pEntry->mnMemberId & SFX_METRIC_ITEM && eMapUnit != SFX_MAPUNIT_100TH_MM)
	{
		SvxUnoConvertFromMM( eMapUnit, aValue );
	}

    // DVO, OD 10.10.2003 #i18732#
    // Assure, that ID is a Which-ID (it could be a Slot-ID.)
    // Thus, convert handle to Which-ID.
    const sal_uInt16 nWhich = pPool->GetWhich( (sal_uInt16)pEntry->mnHandle );
	switch( nWhich )
	{
		case OWN_ATTR_FILLBMP_MODE:
			do
			{
				drawing::BitmapMode eMode;
				if(!(aValue >>= eMode) )
				{
					sal_Int32 nMode = 0;
					if(!(aValue >>= nMode))
						throw lang::IllegalArgumentException();

					eMode = (drawing::BitmapMode)nMode;
				}

				pPool->SetPoolDefaultItem( XFillBmpStretchItem( eMode == drawing::BitmapMode_STRETCH ) );
				pPool->SetPoolDefaultItem( XFillBmpTileItem( eMode == drawing::BitmapMode_REPEAT ) );
				return;
			}
			while(0);

    default:
		{
			::std::auto_ptr<SfxPoolItem> pNewItem( pPool->GetDefaultItem( nWhich ).Clone() );
			sal_uInt8 nMemberId = pEntry->mnMemberId & (~SFX_METRIC_ITEM);
			if( !pPool || (pPool->GetMetric(nWhich) == SFX_MAPUNIT_100TH_MM) )
				nMemberId &= (~CONVERT_TWIPS);

			if( !pNewItem->PutValue( aValue, nMemberId ) )
				throw lang::IllegalArgumentException();

			pPool->SetPoolDefaultItem( *pNewItem );
		}
	}
}

void SvxUnoDrawPool::_setPropertyValues( const comphelper::PropertyMapEntry** ppEntries, const uno::Any* pValues )
	throw(beans::UnknownPropertyException, beans::PropertyVetoException, lang::IllegalArgumentException, lang::WrappedTargetException )
{
	vos::OGuard aGuard( Application::GetSolarMutex() );

	SfxItemPool* pPool = getModelPool( sal_False );

	DBG_ASSERT( pPool, "I need a SfxItemPool!" );
	if( NULL == pPool )
		throw beans::UnknownPropertyException();

	while( *ppEntries )
		putAny( pPool, *ppEntries++, *pValues++ );
}

void SvxUnoDrawPool::_getPropertyValues( const comphelper::PropertyMapEntry** ppEntries, uno::Any* pValue )
	throw(beans::UnknownPropertyException, lang::WrappedTargetException )
{
	vos::OGuard aGuard( Application::GetSolarMutex() );

	SfxItemPool* pPool = getModelPool( sal_True );

	DBG_ASSERT( pPool, "I need a SfxItemPool!" );
	if( NULL == pPool )
		throw beans::UnknownPropertyException();

	while( *ppEntries )
		getAny( pPool, *ppEntries++, *pValue++ );
}

void SvxUnoDrawPool::_getPropertyStates( const comphelper::PropertyMapEntry** ppEntries, beans::PropertyState* pStates )
	throw(beans::UnknownPropertyException )
{
	vos::OGuard aGuard( Application::GetSolarMutex() );

	SfxItemPool* pPool = getModelPool( sal_True );

    if( pPool && pPool != mpDefaultsPool )
	{
		while( *ppEntries )
		{
            // OD 13.10.2003 #i18732#
            // Assure, that ID is a Which-ID (it could be a Slot-ID.)
            // Thus, convert handle to Which-ID.
            const sal_uInt16 nWhich = pPool->GetWhich( ((sal_uInt16)(*ppEntries)->mnHandle) );

			switch( nWhich )
			{
			case OWN_ATTR_FILLBMP_MODE:
				{
                    // use method <IsStaticDefaultItem(..)> instead of using
                    // probably incompatible item pool <mpDefaultPool>.
                    if ( IsStaticDefaultItem( &(pPool->GetDefaultItem( XATTR_FILLBMP_STRETCH )) ) ||
                         IsStaticDefaultItem( &(pPool->GetDefaultItem( XATTR_FILLBMP_TILE )) ) )
					{
						*pStates = beans::PropertyState_DEFAULT_VALUE;
					}
					else
					{
						*pStates = beans::PropertyState_DIRECT_VALUE;
					}
				}
				break;
			default:
                // OD 13.10.2003 #i18732# - correction:
                // use method <IsStaticDefaultItem(..)> instead of using probably
                // incompatible item pool <mpDefaultPool>.
                const SfxPoolItem& r1 = pPool->GetDefaultItem( nWhich );
                //const SfxPoolItem& r2 = mpDefaultPool->GetDefaultItem( nWhich );

                if ( IsStaticDefaultItem( &r1 ) )
				{
					*pStates = beans::PropertyState_DEFAULT_VALUE;
				}
				else
				{
					*pStates = beans::PropertyState_DIRECT_VALUE;
				}
			}

			pStates++;
			ppEntries++;
		}
	}
	else
	{
		// as long as we have no model, all properties are default
		while( *ppEntries++ )
			*pStates++ = beans::PropertyState_DEFAULT_VALUE;
		return;
	}
}

void SvxUnoDrawPool::_setPropertyToDefault( const comphelper::PropertyMapEntry* pEntry )
	throw(beans::UnknownPropertyException )
{
	vos::OGuard aGuard( Application::GetSolarMutex() );

	SfxItemPool* pPool = getModelPool( sal_True );

    // OD 10.10.2003 #i18732#
    // Assure, that ID is a Which-ID (it could be a Slot-ID.)
    // Thus, convert handle to Which-ID.
    const sal_uInt16 nWhich = pPool->GetWhich( (sal_uInt16)pEntry->mnHandle );
    if ( pPool && pPool != mpDefaultsPool )
    {
        // OD 13.10.2003 #i18732# - use method <ResetPoolDefaultItem(..)>
        // instead of using probably incompatible item pool <mpDefaultsPool>.
        pPool->ResetPoolDefaultItem( nWhich );
    }
}

uno::Any SvxUnoDrawPool::_getPropertyDefault( const comphelper::PropertyMapEntry* pEntry )
	throw(beans::UnknownPropertyException, lang::WrappedTargetException )
{
	vos::OGuard aGuard( Application::GetSolarMutex() );

    // OD 13.10.2003 #i18732# - use method <GetPoolDefaultItem(..)> instead of
    // using probably incompatible item pool <mpDefaultsPool>
    uno::Any aAny;
    SfxItemPool* pPool = getModelPool( sal_True );
    const sal_uInt16 nWhich = pPool->GetWhich( (sal_uInt16)pEntry->mnHandle );
    const SfxPoolItem *pItem = pPool->GetPoolDefaultItem ( nWhich );
    pItem->QueryValue( aAny, pEntry->mnMemberId );

    return aAny;
}

// XInterface

uno::Any SAL_CALL SvxUnoDrawPool::queryInterface( const uno::Type & rType )
	throw( uno::RuntimeException )
{
	return OWeakAggObject::queryInterface( rType );
}

uno::Any SAL_CALL SvxUnoDrawPool::queryAggregation( const uno::Type & rType )
	throw(uno::RuntimeException)
{
	uno::Any aAny;

	if( rType == ::getCppuType((const uno::Reference< lang::XServiceInfo >*)0) )
		aAny <<= uno::Reference< lang::XServiceInfo >(this);
	else if( rType == ::getCppuType((const uno::Reference< lang::XTypeProvider >*)0) )
		aAny <<= uno::Reference< lang::XTypeProvider >(this);
	else if( rType == ::getCppuType((const uno::Reference< beans::XPropertySet >*)0) )
		aAny <<= uno::Reference< beans::XPropertySet >(this);
	else if( rType == ::getCppuType((const uno::Reference< beans::XPropertyState >*)0) )
		aAny <<= uno::Reference< beans::XPropertyState >(this);
	else if( rType == ::getCppuType((const uno::Reference< beans::XMultiPropertySet >*)0) )
		aAny <<= uno::Reference< beans::XMultiPropertySet >(this);
	else
		aAny <<= OWeakAggObject::queryAggregation( rType );

	return aAny;
}

void SAL_CALL SvxUnoDrawPool::acquire() throw ( )
{
	OWeakAggObject::acquire();
}

void SAL_CALL SvxUnoDrawPool::release() throw ( )
{
	OWeakAggObject::release();
}

uno::Sequence< uno::Type > SAL_CALL SvxUnoDrawPool::getTypes()
	throw (uno::RuntimeException)
{
	uno::Sequence< uno::Type > aTypes( 6 );
	uno::Type* pTypes = aTypes.getArray();

	*pTypes++ = ::getCppuType((const uno::Reference< uno::XAggregation>*)0);
	*pTypes++ = ::getCppuType((const uno::Reference< lang::XServiceInfo>*)0);
	*pTypes++ = ::getCppuType((const uno::Reference< lang::XTypeProvider>*)0);
	*pTypes++ = ::getCppuType((const uno::Reference< beans::XPropertySet>*)0);
	*pTypes++ = ::getCppuType((const uno::Reference< beans::XPropertyState>*)0);
	*pTypes++ = ::getCppuType((const uno::Reference< beans::XMultiPropertySet>*)0);

	return aTypes;
}

uno::Sequence< sal_Int8 > SAL_CALL SvxUnoDrawPool::getImplementationId()
	throw (uno::RuntimeException)
{
	vos::OGuard aGuard( Application::GetSolarMutex() );

	static uno::Sequence< sal_Int8 > aId;
	if( aId.getLength() == 0 )
	{
		aId.realloc( 16 );
		rtl_createUuid( (sal_uInt8 *)aId.getArray(), 0, sal_True );
	}
	return aId;
}

// XServiceInfo

sal_Bool SAL_CALL SvxUnoDrawPool::supportsService( const  OUString& ServiceName ) throw(uno::RuntimeException)
{
    uno::Sequence< OUString > aSNL( getSupportedServiceNames() );
    const OUString * pArray = aSNL.getConstArray();

    for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
        if( pArray[i] == ServiceName )
            return sal_True;

    return sal_False;
}

OUString SAL_CALL SvxUnoDrawPool::getImplementationName() throw( uno::RuntimeException )
{
	return OUString( RTL_CONSTASCII_USTRINGPARAM("SvxUnoDrawPool") );
}

uno::Sequence< OUString > SAL_CALL SvxUnoDrawPool::getSupportedServiceNames(  )
	throw( uno::RuntimeException )
{
    uno::Sequence< OUString > aSNS( 1 );
    aSNS.getArray()[0] = OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.Defaults" ));
    return aSNS;
}
