/**************************************************************
 *
 * 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 <com/sun/star/xml/sax/SAXParseException.hpp>
#include <com/sun/star/xml/sax/SAXException.hpp>
#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
#include <com/sun/star/xml/sax/XAttributeList.hpp>
#include <xmloff/nmspmap.hxx>
#include <xmloff/xmltoken.hxx>
#include "xmloff/xmlnmspe.hxx"

#ifndef _XMLOFF_TRANSFOERMERBASE_HXX
#include "TransformerBase.hxx"
#endif
#include "TransformerActions.hxx"
#include "AttrTransformerAction.hxx"
#include "ActionMapTypesOASIS.hxx"
#include "MutableAttrList.hxx"
#include "RenameElemTContext.hxx"
#include "FlatTContext.hxx"

#ifndef _XMLOFF_NOTESCONTEXT_HXX
#include "NotesTContext.hxx"
#endif

using ::rtl::OUString;
using namespace ::xmloff::token;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::xml::sax;

TYPEINIT1( XMLNotesTransformerContext, XMLPersElemContentTContext );

XMLNotesTransformerContext::XMLNotesTransformerContext(
		XMLTransformerBase& rImp,
	    const OUString& rQName,
	    XMLTokenEnum eToken, sal_Bool bPersistent ) :
	XMLPersElemContentTContext( rImp, rQName ),
	m_bEndNote( sal_False ),
	m_bPersistent( bPersistent ),
	m_eTypeToken( eToken )
{
}

XMLNotesTransformerContext::~XMLNotesTransformerContext()
{
}

void XMLNotesTransformerContext::StartElement(
		const Reference< XAttributeList >& rAttrList )
{
	XMLTransformerActions *pActions =
		GetTransformer().GetUserDefinedActions( OASIS_NOTES_ACTIONS );
	OSL_ENSURE( pActions, "go no actions" );

	Reference< XAttributeList > xAttrList( rAttrList );
	XMLMutableAttributeList *pMutableAttrList = 0;
	sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
	for( sal_Int16 i=0; i < nAttrCount; i++ )
	{
		const OUString& rAttrName = xAttrList->getNameByIndex( i );
		OUString aLocalName;
		sal_uInt16 nPrefix =
			GetTransformer().GetNamespaceMap().GetKeyByAttrName( rAttrName,
																 &aLocalName );
		XMLTransformerActions::key_type aKey( nPrefix, aLocalName );
		XMLTransformerActions::const_iterator aIter =
			pActions->find( aKey );
		if( !(aIter == pActions->end() ) )
		{
			const OUString& rAttrValue = xAttrList->getValueByIndex( i );

			if( !pMutableAttrList )
			{
				pMutableAttrList =
					new XMLMutableAttributeList( xAttrList );
				xAttrList = pMutableAttrList;
			}
			switch( (*aIter).second.m_nActionType )
			{
			case XML_ATACTION_STYLE_FAMILY:
				{
					if( IsXMLToken( rAttrValue, XML_FOOTNOTE ) )
					{
					}
					else if( IsXMLToken( rAttrValue, XML_ENDNOTE ) )
					{
						m_bEndNote = sal_True;
					}
					pMutableAttrList->RemoveAttributeByIndex( i );
					--i;
					--nAttrCount;
				}
				break;
			case XML_ATACTION_DECODE_STYLE_NAME:
			case XML_ATACTION_DECODE_STYLE_NAME_REF:
				{
					OUString aAttrValue( rAttrValue );
					if( GetTransformer().DecodeStyleName(aAttrValue) )
						pMutableAttrList->SetValueByIndex( i, aAttrValue );
				}
				break;
			}
		}
	}

	XMLTokenEnum eToken = XML_FOOTNOTE;
	switch( m_eTypeToken )
	{
	case XML_NOTE:
		eToken = (m_bEndNote ? XML_ENDNOTE : XML_FOOTNOTE);
		break;
	case XML_NOTES_CONFIGURATION:
		eToken = (m_bEndNote ? XML_ENDNOTES_CONFIGURATION
							 : XML_FOOTNOTES_CONFIGURATION);
		break;
	case XML_NOTE_REF:
		eToken = (m_bEndNote ? XML_ENDNOTE_REF : XML_FOOTNOTE_REF);
		break;
	default:
		OSL_ENSURE( XML_NOTE==m_eTypeToken, "invalid note type" );
		break;
	}

	SetExportQName( GetTransformer().GetNamespaceMap().GetQNameByKey(
							XML_NAMESPACE_TEXT,
							::xmloff::token::GetXMLToken( eToken ) ) );
	if( m_bPersistent )
		XMLPersElemContentTContext::StartElement( xAttrList );
	else
		GetTransformer().GetDocHandler()->startElement( GetExportQName(),
														xAttrList );
}

void XMLNotesTransformerContext::EndElement()
{
	if( m_bPersistent )
	{
		XMLPersElemContentTContext::EndElement();
	}
	else
	{
		GetTransformer().GetDocHandler()->endElement( GetExportQName() );
	}
}

XMLTransformerContext *XMLNotesTransformerContext::CreateChildContext(
		sal_uInt16 nPrefix,
		const OUString& rLocalName,
		const OUString& rQName,
		const Reference< XAttributeList >& rAttrList )
{
	XMLTransformerContext *pContext = 0;
	if( XML_NOTE == m_eTypeToken )
	{
		if( XML_NAMESPACE_TEXT == nPrefix )
		{
			XMLTokenEnum eToken ( XML_TOKEN_INVALID );
			if( IsXMLToken( rLocalName, XML_NOTE_CITATION ) )
			{
				eToken = m_bEndNote ? XML_ENDNOTE_CITATION
								  : XML_FOOTNOTE_CITATION;
			}
			else if( IsXMLToken( rLocalName, XML_NOTE_BODY ) )
			{
				eToken = m_bEndNote ? XML_ENDNOTE_BODY
								  : XML_FOOTNOTE_BODY;
			}

			if( XML_TOKEN_INVALID != eToken )
			{
				if( m_bPersistent  )
				{
					pContext = new XMLPersTextContentTContext(
									GetTransformer(), rQName,
									XML_NAMESPACE_TEXT,
									eToken );
					AddContent( pContext );

				}
				else
				{
					pContext = new XMLRenameElemTransformerContext(
									GetTransformer(), rQName,
									XML_NAMESPACE_TEXT,
									eToken );
				}
			}
		}
	}

	if( !pContext )
	{
		pContext = m_bPersistent
						? XMLPersElemContentTContext::CreateChildContext(
								nPrefix, rLocalName, rQName, rAttrList )
						: XMLTransformerContext::CreateChildContext(
								nPrefix, rLocalName, rQName, rAttrList );
	}

	return pContext;
}

sal_Bool XMLNotesTransformerContext::IsPersistent() const
{
	return m_bPersistent;
}
