/**************************************************************
 *
 * 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_sd.hxx"
#include <com/sun/star/drawing/BitmapMode.hpp>
#include <vos/mutex.hxx>
#include <vcl/svapp.hxx>
#include <svl/itemset.hxx>
#include <svx/svdpool.hxx>
#include <comphelper/extract.hxx>
#include <rtl/uuid.h>
#include <rtl/memory.h>
#include <svx/xflbstit.hxx>
#include <svx/xflbmtit.hxx>
#include <svx/svdobj.hxx>
#include <svx/unoprov.hxx>
#include <svx/unoshape.hxx>
#include <comphelper/serviceinfohelper.hxx>

#include "unopback.hxx"
#include "unohelp.hxx"
#include "drawdoc.hxx"
#include "unokywds.hxx"

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

const SvxItemPropertySet* ImplGetPageBackgroundPropertySet()
{
	static const SfxItemPropertyMapEntry aPageBackgroundPropertyMap_Impl[] =
	{
		FILL_PROPERTIES
		{0,0,0,0,0,0}
	};

    static SvxItemPropertySet aPageBackgroundPropertySet_Impl( aPageBackgroundPropertyMap_Impl, SdrObject::GetGlobalDrawObjectItemPool() );
	return &aPageBackgroundPropertySet_Impl;
}

UNO3_GETIMPLEMENTATION_IMPL( SdUnoPageBackground );

SdUnoPageBackground::SdUnoPageBackground(
    SdDrawDocument* pDoc /* = NULL */,
    const SfxItemSet* pSet /* = NULL */) throw()
:   mpPropSet(ImplGetPageBackgroundPropertySet()),
    mpSet(NULL),
    mpDoc(pDoc)
{
	if( pDoc )
	{
		StartListening( *pDoc );
		mpSet = new SfxItemSet( pDoc->GetPool(), XATTR_FILL_FIRST, XATTR_FILL_LAST );

		if( pSet )
			mpSet->Put(*pSet);
	}
}

SdUnoPageBackground::~SdUnoPageBackground() throw()
{
	if( mpDoc )
		EndListening( *mpDoc );

	if( mpSet )
		delete mpSet;
}

void SdUnoPageBackground::Notify( SfxBroadcaster&, const SfxHint& rHint )
{
	const SdrHint* pSdrHint = PTR_CAST( SdrHint, &rHint );

	if( pSdrHint )
	{
		// delete item set if document is dying because then the pool
		// will also die
		if( pSdrHint->GetKind() == HINT_MODELCLEARED )
		{
			delete mpSet;
			mpSet = NULL;
			mpDoc = NULL;
		}
	}

}

void SdUnoPageBackground::fillItemSet( SdDrawDocument* pDoc, SfxItemSet& rSet ) throw()
{
	rSet.ClearItem();

	if( mpSet == NULL )
	{
		StartListening( *pDoc );
		mpDoc = pDoc;

		mpSet = new SfxItemSet( *rSet.GetPool(), XATTR_FILL_FIRST, XATTR_FILL_LAST );

		if( mpPropSet->AreThereOwnUsrAnys() )
		{
			uno::Any* pAny;
            PropertyEntryVector_t aProperties = mpPropSet->getPropertyMap()->getPropertyEntries();
            PropertyEntryVector_t::const_iterator aIt = aProperties.begin();

			while( aIt != aProperties.end() )
			{
				pAny = mpPropSet->GetUsrAnyForID( aIt->nWID );
				if( pAny )
				{
					OUString aPropertyName( aIt->sName );
					switch( aIt->nWID )
					{
						case XATTR_FILLFLOATTRANSPARENCE :
						case XATTR_FILLGRADIENT :
						{
							if ( ( pAny->getValueType() == ::getCppuType((const ::com::sun::star::awt::Gradient*)0) )
								&& ( aIt->nMemberId == MID_FILLGRADIENT ) )
							{
								setPropertyValue( aPropertyName, *pAny );
							}
							else if ( ( pAny->getValueType() == ::getCppuType((const ::rtl::OUString*)0) ) &&
										( aIt->nMemberId == MID_NAME ) )
							{
								setPropertyValue( aPropertyName, *pAny );
							}
						}
						break;
						case XATTR_FILLHATCH :
						{
							if ( ( pAny->getValueType() == ::getCppuType((const ::com::sun::star::drawing::Hatch*)0) )
								&& ( aIt->nMemberId == MID_FILLHATCH ) )
							{
								setPropertyValue( aPropertyName, *pAny );
							}
							else if ( ( pAny->getValueType() == ::getCppuType((const ::rtl::OUString*)0) ) &&
										( aIt->nMemberId == MID_NAME ) )
							{
								setPropertyValue( aPropertyName, *pAny );
							}
						}
						break;
						case XATTR_FILLBITMAP :
						{
							if ( ( ( pAny->getValueType() == ::getCppuType((const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XBitmap >*)0) ) ||
									( pAny->getValueType() == ::getCppuType((const ::com::sun::star::uno::Reference< ::com::sun::star::graphic::XGraphic >*)0) ) ) &&
									( aIt->nMemberId == MID_BITMAP ) )
							{
								setPropertyValue( aPropertyName, *pAny );
							}
							else if ( ( pAny->getValueType() == ::getCppuType((const ::rtl::OUString*)0) ) &&
										( ( aIt->nMemberId == MID_NAME ) || ( aIt->nMemberId == MID_GRAFURL ) ) )
							{
								setPropertyValue( aPropertyName, *pAny );
							}
						}
						break;

						default:
							setPropertyValue( aPropertyName, *pAny );
					}
			    }
				++aIt;
			}
		}
	}

	rSet.Put( *mpSet );
}

// XServiceInfo
OUString SAL_CALL SdUnoPageBackground::getImplementationName()
	throw(uno::RuntimeException)
{
	return OUString::createFromAscii( sUNO_SdUnoPageBackground );
}

sal_Bool SAL_CALL SdUnoPageBackground::supportsService( const OUString& ServiceName )
	throw(uno::RuntimeException)
{
	return comphelper::ServiceInfoHelper::supportsService( ServiceName, getSupportedServiceNames() );
}

uno::Sequence< OUString > SAL_CALL SdUnoPageBackground::getSupportedServiceNames()
	throw(uno::RuntimeException)
{
	uno::Sequence< OUString > aNameSequence( 2 );
	OUString* pStrings = aNameSequence.getArray();

	*pStrings++ = OUString( RTL_CONSTASCII_USTRINGPARAM( sUNO_Service_PageBackground ) );
	*pStrings   = OUString( RTL_CONSTASCII_USTRINGPARAM( sUNO_Service_FillProperties ) );

	return aNameSequence;
}

// XPropertySet
uno::Reference< beans::XPropertySetInfo > SAL_CALL SdUnoPageBackground::getPropertySetInfo()
	throw(uno::RuntimeException)
{
	return mpPropSet->getPropertySetInfo();
}

void SAL_CALL SdUnoPageBackground::setPropertyValue( const OUString& aPropertyName, const uno::Any& aValue )
	throw(beans::UnknownPropertyException, beans::PropertyVetoException, lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException)
{
	OGuard aGuard( Application::GetSolarMutex() );

	const SfxItemPropertySimpleEntry* pEntry = getPropertyMapEntry( aPropertyName );

	if( pEntry == NULL )
	{
		throw beans::UnknownPropertyException();
	}
	else
	{
		if( mpSet )
		{
			if( pEntry->nWID == OWN_ATTR_FILLBMP_MODE )
			{
				drawing::BitmapMode eMode;
				if( aValue >>= eMode )
				{
					mpSet->Put( XFillBmpStretchItem( eMode == drawing::BitmapMode_STRETCH ) );
					mpSet->Put( XFillBmpTileItem( eMode == drawing::BitmapMode_REPEAT ) );
					return;
				}
				throw lang::IllegalArgumentException();
			}

			SfxItemPool& rPool = *mpSet->GetPool();
			SfxItemSet aSet( rPool,	pEntry->nWID, pEntry->nWID);
			aSet.Put( *mpSet );

			if( !aSet.Count() )
				aSet.Put( rPool.GetDefaultItem( pEntry->nWID ) );

			if( pEntry->nMemberId == MID_NAME && ( pEntry->nWID == XATTR_FILLBITMAP || pEntry->nWID == XATTR_FILLGRADIENT || pEntry->nWID == XATTR_FILLHATCH || pEntry->nWID == XATTR_FILLFLOATTRANSPARENCE ) )
			{
				OUString aName;
				if(!(aValue >>= aName ))
					throw lang::IllegalArgumentException();

				SvxShape::SetFillAttribute( pEntry->nWID, aName, aSet );
			}
			else
			{
				SvxItemPropertySet_setPropertyValue( *mpPropSet, pEntry, aValue, aSet );
			}

			mpSet->Put( aSet );
		}
		else
		{
			if(pEntry && pEntry->nWID)
				mpPropSet->setPropertyValue( pEntry, aValue );
		}
	}
}

uno::Any SAL_CALL SdUnoPageBackground::getPropertyValue( const OUString& PropertyName )
	throw(beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
{
	OGuard aGuard( Application::GetSolarMutex() );

	uno::Any aAny;
	const SfxItemPropertySimpleEntry* pEntry = getPropertyMapEntry(PropertyName);

	if( pEntry == NULL )
	{
		throw beans::UnknownPropertyException();
	}
	else
	{
		if( mpSet )
		{
			if( pEntry->nWID == OWN_ATTR_FILLBMP_MODE )
			{
				XFillBmpStretchItem* pStretchItem = (XFillBmpStretchItem*)mpSet->GetItem(XATTR_FILLBMP_STRETCH);
				XFillBmpTileItem* pTileItem = (XFillBmpTileItem*)mpSet->GetItem(XATTR_FILLBMP_TILE);

				if( pStretchItem && pTileItem )
				{
					if( pTileItem->GetValue() )
						aAny <<= drawing::BitmapMode_REPEAT;
					else if( pStretchItem->GetValue() )
						aAny <<= drawing::BitmapMode_STRETCH;
					else
						aAny <<= drawing::BitmapMode_NO_REPEAT;
				}
			}
			else
			{
				SfxItemPool& rPool = *mpSet->GetPool();
				SfxItemSet aSet( rPool,	pEntry->nWID, pEntry->nWID);
				aSet.Put( *mpSet );

				if( !aSet.Count() )
					aSet.Put( rPool.GetDefaultItem( pEntry->nWID ) );

				// Hole Wert aus ItemSet
				aAny = SvxItemPropertySet_getPropertyValue( *mpPropSet, pEntry, aSet );
			}
		}
		else
		{
			if(pEntry && pEntry->nWID)
				aAny = mpPropSet->getPropertyValue( pEntry );
		}
	}
	return aAny;
}

void SAL_CALL SdUnoPageBackground::addPropertyChangeListener( const OUString& , const uno::Reference< beans::XPropertyChangeListener >&  ) throw(beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException) {}
void SAL_CALL SdUnoPageBackground::removePropertyChangeListener( const OUString& , const uno::Reference< beans::XPropertyChangeListener >&  ) throw(beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException) {}
void SAL_CALL SdUnoPageBackground::addVetoableChangeListener( const OUString& , const uno::Reference< beans::XVetoableChangeListener >&  ) throw(beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException) {}
void SAL_CALL SdUnoPageBackground::removeVetoableChangeListener( const OUString& , const uno::Reference< beans::XVetoableChangeListener >&  ) throw(beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException) {}

// XPropertyState
beans::PropertyState SAL_CALL SdUnoPageBackground::getPropertyState( const OUString& PropertyName )
	throw(beans::UnknownPropertyException, uno::RuntimeException)
{
	OGuard aGuard( Application::GetSolarMutex() );

	const SfxItemPropertySimpleEntry* pEntry = getPropertyMapEntry(PropertyName);

	if( pEntry == NULL )
		throw beans::UnknownPropertyException();

	if( mpSet )
	{
		if( pEntry->nWID == OWN_ATTR_FILLBMP_MODE )
		{
			if( mpSet->GetItemState( XATTR_FILLBMP_STRETCH, false ) == SFX_ITEM_SET ||
				mpSet->GetItemState( XATTR_FILLBMP_TILE, false ) == SFX_ITEM_SET )
			{
				return beans::PropertyState_DIRECT_VALUE;
			}
			else
			{
				return beans::PropertyState_AMBIGUOUS_VALUE;
			}
		}

		switch( mpSet->GetItemState( pEntry->nWID, sal_False ) )
		{
		case SFX_ITEM_READONLY:
		case SFX_ITEM_SET:
			return beans::PropertyState_DIRECT_VALUE;
		case SFX_ITEM_DEFAULT:
			return beans::PropertyState_DEFAULT_VALUE;
		default:
//		case SFX_ITEM_DONTCARE:
//		case SFX_ITEM_DISABLED:
			return beans::PropertyState_AMBIGUOUS_VALUE;
		}
	}
	else
	{
		if( NULL == mpPropSet->GetUsrAnyForID(pEntry->nWID) )
			return beans::PropertyState_DEFAULT_VALUE;
		else
			return beans::PropertyState_DIRECT_VALUE;
	}
}

uno::Sequence< beans::PropertyState > SAL_CALL SdUnoPageBackground::getPropertyStates( const uno::Sequence< OUString >& aPropertyName )
	throw(beans::UnknownPropertyException, uno::RuntimeException)
{
	OGuard aGuard( Application::GetSolarMutex() );

	sal_Int32 nCount = aPropertyName.getLength();
	const OUString* pNames = aPropertyName.getConstArray();

	uno::Sequence< beans::PropertyState > aPropertyStateSequence( nCount );
	beans::PropertyState* pState = aPropertyStateSequence.getArray();

	while( nCount-- )
		*pState++ = getPropertyState( *pNames++ );

	return aPropertyStateSequence;
}

void SAL_CALL SdUnoPageBackground::setPropertyToDefault( const OUString& PropertyName )
	throw(beans::UnknownPropertyException, uno::RuntimeException)
{
	OGuard aGuard( Application::GetSolarMutex() );

	const SfxItemPropertySimpleEntry* pEntry = getPropertyMapEntry(PropertyName);

	if( pEntry == NULL )
		throw beans::UnknownPropertyException();

	if( mpSet )
	{
		if( pEntry->nWID == OWN_ATTR_FILLBMP_MODE )
		{
			mpSet->ClearItem( XATTR_FILLBMP_STRETCH );
			mpSet->ClearItem( XATTR_FILLBMP_TILE );
		}
		else
		{
			mpSet->ClearItem( pEntry->nWID );
		}
	}
}

uno::Any SAL_CALL SdUnoPageBackground::getPropertyDefault( const OUString& aPropertyName )
	throw(beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
{
	OGuard aGuard( Application::GetSolarMutex() );

	const SfxItemPropertySimpleEntry* pEntry = getPropertyMapEntry(aPropertyName);
	if( pEntry == NULL || mpSet == NULL )
		throw beans::UnknownPropertyException();

	uno::Any aAny;
	if( mpSet )
	{
		if( pEntry->nWID == OWN_ATTR_FILLBMP_MODE )
		{
			aAny <<= drawing::BitmapMode_REPEAT;
		}
		else
		{
			SfxItemPool& rPool = *mpSet->GetPool();
			SfxItemSet aSet( rPool,	pEntry->nWID, pEntry->nWID);
			aSet.Put( rPool.GetDefaultItem( pEntry->nWID ) );

			aAny = SvxItemPropertySet_getPropertyValue( *mpPropSet, pEntry, aSet );
		}
	}
	return aAny;
}

/** this is used because our property map is not sorted yet */
const SfxItemPropertySimpleEntry* SdUnoPageBackground::getPropertyMapEntry( const OUString& rPropertyName ) const throw()
{
	return mpPropSet->getPropertyMap()->getByName(rPropertyName);
}
