/**************************************************************
 *
 * 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 "MutableAttrList.hxx"
#include "xmloff/xmlnmspe.hxx"
#include <xmloff/nmspmap.hxx>
#include "ActionMapTypesOASIS.hxx"
#include "AttrTransformerAction.hxx"
#include "TransformerActions.hxx"
#ifndef _XMLOFF_TRANSFORMERBASE_HXX
#include "TransformerBase.hxx"
#endif
#include "FormPropOASISTContext.hxx"

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

TYPEINIT1( XMLFormPropOASISTransformerContext,
				XMLRenameElemTransformerContext );

XMLTokenEnum XMLFormPropOASISTransformerContext::GetValueType(
				const OUString& rValue )
{
	XMLTokenEnum eRet = XML_DOUBLE;
    sal_Bool bNeg = sal_False;
    sal_uInt32 nVal = 0;

    sal_Int32 nPos = 0;
    sal_Int32 nLen = rValue.getLength();

    // skip white space
    while( nPos < nLen && sal_Unicode(' ') == rValue[nPos] )
        nPos++;

    if( nPos < nLen && sal_Unicode('-') == rValue[nPos] )
    {
        bNeg = sal_True;
        nPos++;
    }

    // get number
	sal_Bool bOverflow = sal_False;
    while( nPos < nLen &&
           sal_Unicode('0') <= rValue[nPos] &&
           sal_Unicode('9') >= rValue[nPos] )
    {
        nVal *= 10;
        nVal += (rValue[nPos] - sal_Unicode('0'));
		bOverflow |= (nVal > (bNeg ? 2147483648UL : 2147483647UL));
        nPos++;
    }

    // skip white space
    while( nPos < nLen && sal_Unicode(' ') == rValue[nPos] )
        nPos++;

	if( nPos == nLen )
	{
		// It's a integer number
		if( bOverflow )
			eRet = XML_LONG;
		else if( nVal > (bNeg ? 32768UL : 32767UL) )
			eRet = XML_INT;
		else
			eRet = XML_SHORT;
	}

	return eRet;
}

XMLFormPropOASISTransformerContext::XMLFormPropOASISTransformerContext(
		XMLTransformerBase& rImp,
		const OUString& rQName,
	    XMLTokenEnum eLocalName ) :
	XMLRenameElemTransformerContext( rImp, rQName, XML_NAMESPACE_FORM,
		  							 XML_PROPERTY ),
	m_bIsList( XML_LIST_PROPERTY == eLocalName),
	m_bIsListValue( XML_LIST_VALUE == eLocalName)
{
}

XMLFormPropOASISTransformerContext::~XMLFormPropOASISTransformerContext()
{
}

void XMLFormPropOASISTransformerContext::StartElement(
	const Reference< XAttributeList >& rAttrList )
{

	XMLTransformerActions *pActions =
		GetTransformer().GetUserDefinedActions( OASIS_FORM_PROP_ACTIONS );
	OSL_ENSURE( pActions, "go no actions" );

	XMLMutableAttributeList *pMutableAttrList =
		new XMLMutableAttributeList( rAttrList );
	Reference< XAttributeList > xAttrList( pMutableAttrList );

	sal_Int16 nValueTypeAttr = -1;
	OUString aValue;
	sal_Bool bIsVoid = sal_False;
	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 );
			switch( (*aIter).second.m_nActionType )
			{
			case XML_ATACTION_RENAME:
				if( IsXMLToken( aLocalName, XML_VALUE_TYPE ) )
				{
					if( IsXMLToken( rAttrValue, XML_FLOAT ) )
					{
						nValueTypeAttr = i;
					}
					else if( IsXMLToken( rAttrValue, XML_VOID ) )
					{
						pMutableAttrList->SetValueByIndex( i,
								GetXMLToken( XML_SHORT ) );
						bIsVoid = sal_True;
					}
				}
				{
					OUString aNewAttrQName(
						GetTransformer().GetNamespaceMap().GetQNameByKey(
								(*aIter).second.GetQNamePrefixFromParam1(),
								::xmloff::token::GetXMLToken(
									(*aIter).second.GetQNameTokenFromParam1()) ) );
					pMutableAttrList->RenameAttributeByIndex( i, aNewAttrQName );
				}
				break;
			case XML_ATACTION_REMOVE:
				if( !IsXMLToken( aLocalName, XML_CURRENCY ) )
					aValue = rAttrValue;
				pMutableAttrList->RemoveAttributeByIndex( i );
				--i;
				--nAttrCount;
				break;
			default:
				OSL_ENSURE( sal_False, "unknown action" );
				break;
			}
		}
	}
	if( m_bIsList )
	{
		OUString aNewAttrQName(
				GetTransformer().GetNamespaceMap().GetQNameByKey(
					XML_NAMESPACE_FORM,
					GetXMLToken( XML_PROPERTY_IS_LIST ) ) );
		pMutableAttrList->AddAttribute( aNewAttrQName,
										GetXMLToken( XML_TRUE ) );
	}

	if( nValueTypeAttr != -1 )
		pMutableAttrList->SetValueByIndex( nValueTypeAttr,
								GetXMLToken( GetValueType( aValue ) ) );

	if( !m_bIsListValue )
		XMLRenameElemTransformerContext::StartElement( xAttrList );
	if( !m_bIsList )
	{
		pMutableAttrList =
			new XMLMutableAttributeList;
		xAttrList = pMutableAttrList;
		if( bIsVoid )
		{
			OUString aNewAttrQName(
				GetTransformer().GetNamespaceMap().GetQNameByKey(
					XML_NAMESPACE_FORM, GetXMLToken( XML_PROPERTY_IS_VOID ) ) );
			pMutableAttrList->AddAttribute( aNewAttrQName,
										GetXMLToken( XML_TRUE ) );
		}

		OUString aValueElemQName(
			GetTransformer().GetNamespaceMap().GetQNameByKey(
					XML_NAMESPACE_FORM, GetXMLToken( XML_PROPERTY_VALUE ) ) );
		GetTransformer().GetDocHandler()->startElement( aValueElemQName,
														xAttrList );
		GetTransformer().GetDocHandler()->characters( aValue );
		GetTransformer().GetDocHandler()->endElement( aValueElemQName );
	}
}

void XMLFormPropOASISTransformerContext::EndElement()
{
	if( !m_bIsListValue )
		XMLRenameElemTransformerContext::EndElement();
}
