/**************************************************************
 * 
 * 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_xmloff.hxx"
#include <tools/debug.hxx>
#ifndef _COM_SUN_STAR_DOCUMENT_XEVENTSSUPPLIER_HPP
#include <com/sun/star/document/XEventsSupplier.hpp>
#endif
#include "xmloff/xmlnmspe.hxx"
#include <xmloff/xmltoken.hxx>
#include "XMLTextPropertySetContext.hxx"
#include <xmloff/xmlimp.hxx>
#include <xmloff/XMLEventsImportContext.hxx>
#include "XMLShapePropertySetContext.hxx"
#include "XMLTextColumnsContext.hxx"
#include "XMLBackgroundImageContext.hxx"
#ifndef _XMLOFF_TXTPRMAP_HXX
#include <xmloff/txtprmap.hxx>
#endif

#ifndef _XMLOFF_XMLTEXTSHAPESTYLECONTEXT_HXX
#include <xmloff/XMLTextShapeStyleContext.hxx>
#endif

using ::rtl::OUString;
using ::rtl::OUStringBuffer;

using namespace ::com::sun::star::document;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::xml::sax;
using namespace ::com::sun::star::style;
using namespace ::com::sun::star::beans;
using namespace ::xmloff::token;

class XMLTextShapePropertySetContext_Impl : public XMLShapePropertySetContext
{
public:
	XMLTextShapePropertySetContext_Impl( SvXMLImport& rImport, sal_uInt16 nPrfx,
		const OUString& rLName,
		const Reference< XAttributeList >& xAttrList,
				 sal_uInt32 nFamily,
		::std::vector< XMLPropertyState > &rProps,
		const UniReference < SvXMLImportPropertyMapper > &rMap );

	virtual ~XMLTextShapePropertySetContext_Impl();

    using SvXMLPropertySetContext::CreateChildContext;
	virtual SvXMLImportContext *CreateChildContext( sal_uInt16 nPrefix,
		const OUString& rLocalName,
		const Reference< XAttributeList >& xAttrList,
	    ::std::vector< XMLPropertyState > &rProperties,
	    const XMLPropertyState& rProp);
};

XMLTextShapePropertySetContext_Impl::XMLTextShapePropertySetContext_Impl(
				 SvXMLImport& rImport, sal_uInt16 nPrfx,
				 const OUString& rLName,
				 const Reference< XAttributeList > & xAttrList,
				 sal_uInt32 nFamily,
				 ::std::vector< XMLPropertyState > &rProps,
				 const UniReference < SvXMLImportPropertyMapper > &rMap ) :
	XMLShapePropertySetContext( rImport, nPrfx, rLName, xAttrList, nFamily,
								rProps, rMap )
{
}

XMLTextShapePropertySetContext_Impl::~XMLTextShapePropertySetContext_Impl()
{
}

SvXMLImportContext *XMLTextShapePropertySetContext_Impl::CreateChildContext(
				   sal_uInt16 nPrefix,
				   const OUString& rLocalName,
				   const Reference< XAttributeList > & xAttrList,
				   ::std::vector< XMLPropertyState > &rProperties,
				   const XMLPropertyState& rProp )
{
	SvXMLImportContext *pContext = 0;

	switch( mxMapper->getPropertySetMapper()
					->GetEntryContextId( rProp.mnIndex ) )
	{
	case CTF_TEXTCOLUMNS:
		pContext = new XMLTextColumnsContext( GetImport(), nPrefix,
												   rLocalName, xAttrList, rProp,
												   rProperties );
		break;

	case CTF_BACKGROUND_URL:
		DBG_ASSERT( rProp.mnIndex >= 3 &&
					CTF_BACKGROUND_TRANSPARENCY == 
                        mxMapper->getPropertySetMapper()
						->GetEntryContextId( rProp.mnIndex-3 ) &&
					CTF_BACKGROUND_POS  == mxMapper->getPropertySetMapper()
						->GetEntryContextId( rProp.mnIndex-2 ) &&
					CTF_BACKGROUND_FILTER  == mxMapper->getPropertySetMapper()
						->GetEntryContextId( rProp.mnIndex-1 ),
					"invalid property map!");
		pContext = 
			new XMLBackgroundImageContext( GetImport(), nPrefix,
										   rLocalName, xAttrList,
										   rProp,
										   rProp.mnIndex-2,
										   rProp.mnIndex-1,
                                           rProp.mnIndex-3,
										   rProperties );
		break;
	}
	
	if( !pContext )
		pContext = XMLShapePropertySetContext::CreateChildContext(
						nPrefix, rLocalName, xAttrList, rProperties, rProp );
	
	return pContext;
}

//----------------------------------------------------------------------------- 

void XMLTextShapeStyleContext::SetAttribute( sal_uInt16 nPrefixKey,
										const OUString& rLocalName,
										const OUString& rValue )
{
	if( XML_NAMESPACE_STYLE == nPrefixKey &&
		IsXMLToken( rLocalName, XML_AUTO_UPDATE ) )
	{
	  	if( IsXMLToken( rValue, XML_TRUE ) )
			bAutoUpdate = sal_True;
	}
	else
	{
		XMLShapeStyleContext::SetAttribute( nPrefixKey, rLocalName, rValue );
	}
}

XMLTextShapeStyleContext::XMLTextShapeStyleContext( SvXMLImport& rImport,
		sal_uInt16 nPrfx, const OUString& rLName,
		const Reference< XAttributeList > & xAttrList,
		SvXMLStylesContext& rStyles, sal_uInt16 nFamily,
		sal_Bool /*bDefaultStyle*/ ) :
	XMLShapeStyleContext( rImport, nPrfx, rLName, xAttrList, rStyles,
					      nFamily ),
	sIsAutoUpdate( RTL_CONSTASCII_USTRINGPARAM( "IsAutoUpdate" ) ),
	bAutoUpdate( sal_False )
{
}

XMLTextShapeStyleContext::~XMLTextShapeStyleContext()
{
}

SvXMLImportContext *XMLTextShapeStyleContext::CreateChildContext(
		sal_uInt16 nPrefix,
		const OUString& rLocalName,
		const Reference< XAttributeList > & xAttrList )
{
	SvXMLImportContext *pContext = 0;

	if( XML_NAMESPACE_STYLE == nPrefix )
	{
		sal_uInt32 nFamily = 0;
		if( IsXMLToken( rLocalName, XML_TEXT_PROPERTIES ) )
			nFamily = XML_TYPE_PROP_TEXT;
		else if( IsXMLToken( rLocalName, XML_PARAGRAPH_PROPERTIES ) )
			nFamily = XML_TYPE_PROP_PARAGRAPH;
		else if( IsXMLToken( rLocalName, XML_GRAPHIC_PROPERTIES ) )
			nFamily = XML_TYPE_PROP_GRAPHIC;
		if( nFamily )
		{
			UniReference < SvXMLImportPropertyMapper > xImpPrMap =
				GetStyles()->GetImportPropertyMapper( GetFamily() );
			if( xImpPrMap.is() )
			{		
				pContext = new XMLTextShapePropertySetContext_Impl(
						GetImport(), nPrefix, rLocalName, xAttrList, nFamily,
						GetProperties(), xImpPrMap );
			}
		}
	}
	else if ( (XML_NAMESPACE_OFFICE == nPrefix) &&
			  IsXMLToken( rLocalName, XML_EVENT_LISTENERS ) )
	{
		// create and remember events import context 
		// (for delayed processing of events)
		pContext = new XMLEventsImportContext( GetImport(), nPrefix,
												   rLocalName);
		xEventContext = pContext;
	}
		
	if( !pContext )
		pContext = XMLShapeStyleContext::CreateChildContext( nPrefix, rLocalName,
														  xAttrList );

	return pContext;
}

void XMLTextShapeStyleContext::CreateAndInsert( sal_Bool bOverwrite )
{
	XMLShapeStyleContext::CreateAndInsert( bOverwrite );
	Reference < XStyle > xStyle = GetStyle();
	if( !xStyle.is() || !(bOverwrite || IsNew()) )
		return;
	
	Reference < XPropertySet > xPropSet( xStyle, UNO_QUERY );
	Reference< XPropertySetInfo > xPropSetInfo =
				xPropSet->getPropertySetInfo();
	if( xPropSetInfo->hasPropertyByName( sIsAutoUpdate ) )
	{
		Any aAny;
		sal_Bool bTmp = bAutoUpdate;
		aAny.setValue( &bTmp, ::getBooleanCppuType() );
		xPropSet->setPropertyValue( sIsAutoUpdate, aAny );
	}

	// tell the style about it's events (if applicable)
	if( xEventContext.Is() )
	{
		// set event suppplier and release reference to context
		Reference<XEventsSupplier> xEventsSupplier(xStyle, UNO_QUERY);
		((XMLEventsImportContext *)&xEventContext)->SetEvents(xEventsSupplier);
		xEventContext = 0;
	}
}


void XMLTextShapeStyleContext::Finish( sal_Bool bOverwrite )
{
    XMLPropStyleContext::Finish( bOverwrite );
}
