/**************************************************************
 * 
 * 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 "XMLIndexBibliographyConfigurationContext.hxx"
#include "XMLIndexBibliographyEntryContext.hxx"
#include <xmloff/xmlictxt.hxx>
#include <xmloff/xmlimp.hxx>
#include <xmloff/txtimp.hxx>
#include <xmloff/nmspmap.hxx>
#include "xmloff/xmlnmspe.hxx"
#include <xmloff/xmltoken.hxx>
#include <xmloff/xmluconv.hxx>
#include <tools/debug.hxx>
#include <rtl/ustring.hxx>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>

using namespace ::com::sun::star::text;
using namespace ::com::sun::star::uno;
using namespace ::xmloff::token;

using ::rtl::OUString;
using ::com::sun::star::xml::sax::XAttributeList;
using ::com::sun::star::beans::PropertyValue;
using ::com::sun::star::beans::XPropertySet;
using ::com::sun::star::lang::XMultiServiceFactory;

const sal_Char sAPI_FieldMaster_Bibliography[] = 
								"com.sun.star.text.FieldMaster.Bibliography";


TYPEINIT1( XMLIndexBibliographyConfigurationContext, SvXMLStyleContext );

XMLIndexBibliographyConfigurationContext::XMLIndexBibliographyConfigurationContext(
	SvXMLImport& rImport, 
	sal_uInt16 nPrfx,
	const OUString& rLocalName,
	const Reference<XAttributeList> & xAttrList) :
		SvXMLStyleContext(rImport, nPrfx, rLocalName, xAttrList, XML_STYLE_FAMILY_TEXT_BIBLIOGRAPHYCONFIG),
		sFieldMaster_Bibliography(
			RTL_CONSTASCII_USTRINGPARAM(sAPI_FieldMaster_Bibliography)),
		sBracketBefore(RTL_CONSTASCII_USTRINGPARAM("BracketBefore")),
		sBracketAfter(RTL_CONSTASCII_USTRINGPARAM("BracketAfter")),
		sIsNumberEntries(RTL_CONSTASCII_USTRINGPARAM("IsNumberEntries")),
		sIsSortByPosition(RTL_CONSTASCII_USTRINGPARAM("IsSortByPosition")),
		sSortKeys(RTL_CONSTASCII_USTRINGPARAM("SortKeys")),
		sSortKey(RTL_CONSTASCII_USTRINGPARAM("SortKey")),
		sIsSortAscending(RTL_CONSTASCII_USTRINGPARAM("IsSortAscending")),
        sSortAlgorithm(RTL_CONSTASCII_USTRINGPARAM("SortAlgorithm")),
        sLocale(RTL_CONSTASCII_USTRINGPARAM("Locale")),
		sSuffix(),
		sPrefix(),
        sAlgorithm(),
        aLocale(),
		bNumberedEntries(sal_False),
		bSortByPosition(sal_True)
{
}

XMLIndexBibliographyConfigurationContext::~XMLIndexBibliographyConfigurationContext()
{
}

void XMLIndexBibliographyConfigurationContext::StartElement(
	const Reference<XAttributeList> & xAttrList)
{
	sal_Int16 nLength = xAttrList->getLength();
	for(sal_Int16 nAttr = 0; nAttr < nLength; nAttr++)
	{
		OUString sLocalName;
		sal_uInt16 nPrefix = GetImport().GetNamespaceMap().
			GetKeyByAttrName( xAttrList->getNameByIndex(nAttr), 
							  &sLocalName );

        ProcessAttribute(nPrefix, sLocalName, 
                         xAttrList->getValueByIndex(nAttr));
		// else: ignore
	}
}

void XMLIndexBibliographyConfigurationContext::ProcessAttribute(
    sal_uInt16 nPrefix,
	OUString sLocalName,
	OUString sValue)
{
    if( XML_NAMESPACE_TEXT == nPrefix )
    {
        if( IsXMLToken(sLocalName, XML_PREFIX) )
        {
            sPrefix = sValue;
        } 
        else if( IsXMLToken(sLocalName, XML_SUFFIX) )
        {
            sSuffix = sValue;
        }
        else if( IsXMLToken(sLocalName, XML_NUMBERED_ENTRIES) )
        {
            sal_Bool bTmp;
            if( SvXMLUnitConverter::convertBool(bTmp, sValue) )
            {
                bNumberedEntries = bTmp;
            }
        }
        else if( IsXMLToken(sLocalName, XML_SORT_BY_POSITION) )
        {
            sal_Bool bTmp;
            if (SvXMLUnitConverter::convertBool(bTmp, sValue))
            {
                bSortByPosition = bTmp;
            }
        }
        else if( IsXMLToken(sLocalName, XML_SORT_ALGORITHM) )
        {
            sAlgorithm = sValue;
        }
	}
    else if( XML_NAMESPACE_FO == nPrefix )
    {
        if( IsXMLToken(sLocalName, XML_LANGUAGE) )
        {
            aLocale.Language = sValue;
        }
        else if( IsXMLToken(sLocalName, XML_COUNTRY) )
        {
            aLocale.Country = sValue;
        }
    }
}


SvXMLImportContext *XMLIndexBibliographyConfigurationContext::CreateChildContext( 
	sal_uInt16 nPrefix,
	const OUString& rLocalName,
	const Reference<XAttributeList> & xAttrList )
{
	OUString sKey;
	sal_Bool bSort(sal_True);

	// process children here and use default context!
	if ( ( nPrefix == XML_NAMESPACE_TEXT ) && 
         IsXMLToken( rLocalName, XML_SORT_KEY ) )
	{
		sal_Int16 nLength = xAttrList->getLength();
		for(sal_Int16 nAttr = 0; nAttr < nLength; nAttr++)
		{
			OUString sLocalName;
			sal_uInt16 nPrfx = GetImport().GetNamespaceMap().
				GetKeyByAttrName( xAttrList->getNameByIndex(nAttr), 
								  &sLocalName );

			if (nPrfx == XML_NAMESPACE_TEXT) 
			{
				if ( IsXMLToken( sLocalName, XML_KEY ) )
				{
					sKey = xAttrList->getValueByIndex(nAttr);
				}
				else if ( IsXMLToken( sLocalName, XML_SORT_ASCENDING ) )
				{
					sal_Bool bTmp;
					if (SvXMLUnitConverter::convertBool(
						bTmp, xAttrList->getValueByIndex(nAttr)))
					{
						bSort = bTmp;
					}
				}
			}
		}

		// valid data?
		sal_uInt16 nKey;
		if (SvXMLUnitConverter::convertEnum(nKey, sKey, 
											aBibliographyDataFieldMap))
		{

			Any aAny;
			Sequence<PropertyValue> aKey(2);
		
			PropertyValue aNameValue;
			aNameValue.Name = sSortKey;
			aAny <<= (sal_Int16)nKey;
			aNameValue.Value = aAny;
			aKey[0] = aNameValue;

			PropertyValue aSortValue;
			aSortValue.Name = sIsSortAscending;
			aAny.setValue(&bSort, ::getBooleanCppuType());
			aSortValue.Value = aAny;
			aKey[1] = aSortValue;
			
			aSortKeys.push_back(aKey);
		}
	}

	return SvXMLImportContext::CreateChildContext(nPrefix, rLocalName, 
												  xAttrList);
}

void XMLIndexBibliographyConfigurationContext::CreateAndInsert(sal_Bool)
{
	// (code almost the same as export...)

	// insert and block mode is handled in insertStyleFamily

	// first: get field master
	// (we'll create one, and get the only master for this type)
	Reference<XMultiServiceFactory> xFactory(GetImport().GetModel(),UNO_QUERY);
	if( xFactory.is() )
	{
		Sequence<rtl::OUString> aServices = xFactory->getAvailableServiceNames();
		sal_Bool bFound(sal_False);
		sal_Int32 i(0);
		sal_Int32 nServiceCount(aServices.getLength());
		while (i < nServiceCount && !bFound)
		{
			if (aServices[i].equals(sFieldMaster_Bibliography))
			// here we should use a methode which compares in reverse order if available
			// #85282#
				bFound = sal_True;
			else
				i++;
		}
		if (bFound)
		{
			Reference<XInterface> xIfc = 
				xFactory->createInstance(sFieldMaster_Bibliography);
			if( xIfc.is() )
			{
				Reference<XPropertySet> xPropSet( xIfc, UNO_QUERY );
				Any aAny;

                aAny <<= sSuffix;
                xPropSet->setPropertyValue(sBracketAfter, aAny);

                aAny <<= sPrefix;
                xPropSet->setPropertyValue(sBracketBefore, aAny);
		
				aAny.setValue(&bNumberedEntries, ::getBooleanCppuType());
				xPropSet->setPropertyValue(sIsNumberEntries, aAny);

				aAny.setValue(&bSortByPosition, ::getBooleanCppuType());
				xPropSet->setPropertyValue(sIsSortByPosition, aAny);

                if( (aLocale.Language.getLength() > 0) &&
                    (aLocale.Country.getLength() > 0)     )
                {
                    aAny <<= aLocale;
                    xPropSet->setPropertyValue(sLocale, aAny);
                }

                if( sAlgorithm.getLength() > 0 )
                {
                    aAny <<= sAlgorithm;
                    xPropSet->setPropertyValue(sSortAlgorithm, aAny);
                }

				sal_Int32 nCount = aSortKeys.size();
				Sequence<Sequence<PropertyValue> > aKeysSeq(nCount);
				for(i = 0; i < nCount; i++)
				{
					aKeysSeq[i] = aSortKeys[i];
				}
				aAny <<= aKeysSeq;
				xPropSet->setPropertyValue(sSortKeys, aAny);
			}
			// else: can't get FieldMaster -> ignore
		}
	}
	// else: can't even get Factory -> ignore
}