/**************************************************************
 * 
 * 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 "XMLIndexTOCContext.hxx"
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/lang/IllegalArgumentException.hpp>
#include <com/sun/star/uno/XInterface.hpp>
#include <com/sun/star/text/XTextContent.hpp>
#include <com/sun/star/text/XTextSection.hpp>
#include <com/sun/star/text/XRelativeTextContentInsert.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include "XMLIndexTOCSourceContext.hxx"
#include "XMLIndexObjectSourceContext.hxx"
#include "XMLIndexAlphabeticalSourceContext.hxx"
#include "XMLIndexUserSourceContext.hxx"
#include "XMLIndexBibliographySourceContext.hxx"
#include "XMLIndexTableSourceContext.hxx"
#include "XMLIndexIllustrationSourceContext.hxx"
#include "XMLIndexBodyContext.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/prstylei.hxx>
#include "xmloff/xmlerror.hxx"
#include <xmloff/xmluconv.hxx>
#include <rtl/ustring.hxx>


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

using ::rtl::OUString;
using ::com::sun::star::beans::XPropertySet;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::xml::sax::XAttributeList;
using ::com::sun::star::lang::XMultiServiceFactory;
using ::com::sun::star::lang::IllegalArgumentException;


TYPEINIT1(XMLIndexTOCContext, SvXMLImportContext);

static const sal_Char* aIndexServiceMap[] =
{ 
	"com.sun.star.text.ContentIndex",
	"com.sun.star.text.DocumentIndex",
	"com.sun.star.text.TableIndex",
	"com.sun.star.text.ObjectIndex",
	"com.sun.star.text.Bibliography",
	"com.sun.star.text.UserIndex",
	"com.sun.star.text.IllustrationsIndex"
};

static const XMLTokenEnum aIndexSourceElementMap[] =
{ 
	XML_TABLE_OF_CONTENT_SOURCE,
	XML_ALPHABETICAL_INDEX_SOURCE,
	XML_TABLE_INDEX_SOURCE,
	XML_OBJECT_INDEX_SOURCE,
	XML_BIBLIOGRAPHY_SOURCE,
	XML_USER_INDEX_SOURCE,
	XML_ILLUSTRATION_INDEX_SOURCE
};

SvXMLEnumMapEntry __READONLY_DATA aIndexTypeMap[] =
{
	{ XML_TABLE_OF_CONTENT,	    TEXT_INDEX_TOC },
	{ XML_ALPHABETICAL_INDEX,	TEXT_INDEX_ALPHABETICAL },
	{ XML_TABLE_INDEX, 		    TEXT_INDEX_TABLE },
	{ XML_OBJECT_INDEX,		    TEXT_INDEX_OBJECT },
	{ XML_BIBLIOGRAPHY,		    TEXT_INDEX_BIBLIOGRAPHY },
	{ XML_USER_INDEX,			TEXT_INDEX_USER },
	{ XML_ILLUSTRATION_INDEX,	TEXT_INDEX_ILLUSTRATION },
	{ XML_TOKEN_INVALID,        0 }
};


XMLIndexTOCContext::XMLIndexTOCContext(
	SvXMLImport& rImport, 
	sal_uInt16 nPrfx,
	const OUString& rLocalName )
:	SvXMLImportContext(rImport, nPrfx, rLocalName)
,	sTitle(RTL_CONSTASCII_USTRINGPARAM("Title"))
,	sIsProtected(RTL_CONSTASCII_USTRINGPARAM("IsProtected"))
,	sName(RTL_CONSTASCII_USTRINGPARAM("Name"))
,	bValid(sal_False)
{
	if (XML_NAMESPACE_TEXT == nPrfx)
	{
		sal_uInt16 nTmp;
		if (SvXMLUnitConverter::convertEnum(nTmp, rLocalName, aIndexTypeMap))
		{
			// check for array index: 
			OSL_ENSURE(nTmp < (sizeof(aIndexServiceMap)/sizeof(sal_Char*)), "index out of range");
			OSL_ENSURE(sizeof(aIndexServiceMap) == 
					   sizeof(aIndexSourceElementMap), 
					   "service and source element maps must be same size");

			eIndexType = static_cast<IndexTypeEnum>(nTmp);
			bValid = sal_True;
		}
	}
}

XMLIndexTOCContext::~XMLIndexTOCContext()
{
}

void XMLIndexTOCContext::StartElement(
	const Reference<XAttributeList> & xAttrList)
{
	if (bValid)
    {
        // find text:style-name attribute and set section style
        // find text:protected and set value
        // find text:name and set value (if not empty)
        sal_Int16 nCount = xAttrList->getLength();
        sal_Bool bProtected = sal_False;
        OUString sIndexName;
        OUString sXmlId;
        XMLPropStyleContext* pStyle(NULL);
        for(sal_Int16 nAttr = 0; nAttr < nCount; nAttr++)
        {
            OUString sLocalName;
            sal_uInt16 nPrefix = GetImport().GetNamespaceMap().
                GetKeyByAttrName( xAttrList->getNameByIndex(nAttr),
                                  &sLocalName );
            if ( XML_NAMESPACE_TEXT == nPrefix)
            {
                if ( IsXMLToken( sLocalName, XML_STYLE_NAME ) )
                {
                    pStyle = GetImport().GetTextImport()->FindSectionStyle(
                                xAttrList->getValueByIndex(nAttr));
                }
                else if ( IsXMLToken( sLocalName, XML_PROTECTED ) )
                {
                    sal_Bool bTmp;
                    if ( SvXMLUnitConverter::convertBool(
                         bTmp, xAttrList->getValueByIndex(nAttr) ) )
                    {
                        bProtected = bTmp;
                    }
                }
                else if ( IsXMLToken( sLocalName, XML_NAME ) )
                {
                    sIndexName = xAttrList->getValueByIndex(nAttr);
                }
            }
            else if ( XML_NAMESPACE_XML == nPrefix)
            {
                if ( IsXMLToken( sLocalName, XML_ID ) )
                {
                    sXmlId = xAttrList->getValueByIndex(nAttr);
                }
            }
        }

		// create table of content (via MultiServiceFactory)
		Reference<XMultiServiceFactory> xFactory(GetImport().GetModel(),
												 UNO_QUERY);
        if( xFactory.is() )
        {
            Reference<XInterface> xIfc =
				xFactory->createInstance(
					OUString::createFromAscii(aIndexServiceMap[eIndexType]));
			if( xIfc.is() )
			{
				// get Property set
				Reference<XPropertySet> xPropSet(xIfc, UNO_QUERY);
				xTOCPropertySet = xPropSet;

				// insert section
				// a) insert section
				//    The inserted index consists of an empty paragraph 
				//    only, as well as an empty paragraph *after* the index
				// b) insert marker after index, and put Cursor inside of the 
				//    index

				// preliminaries
#ifndef DBG_UTIL
				OUString sMarker(RTL_CONSTASCII_USTRINGPARAM(" "));
#else
				OUString sMarker(RTL_CONSTASCII_USTRINGPARAM("Y"));
#endif
				UniReference<XMLTextImportHelper> rImport = 
					GetImport().GetTextImport();

				// a) insert index
				Reference<XTextContent> xTextContent(xIfc, UNO_QUERY);
                try
                {
                    GetImport().GetTextImport()->InsertTextContent(
                        xTextContent);
                }
                catch( IllegalArgumentException e )
                {
                    // illegal argument? Then we can't accept indices here!
                    Sequence<OUString> aSeq(1);
                    aSeq[0] = GetLocalName();
                    GetImport().SetError( 
                        XMLERROR_FLAG_ERROR | XMLERROR_NO_INDEX_ALLOWED_HERE,
                        aSeq, e.Message, NULL );

                    // set bValid to false, and return prematurely
                    bValid = false;
                    return;
                }

                // xml:id for RDF metadata
                GetImport().SetXmlId(xIfc, sXmlId);

				// b) insert marker and move cursor
				rImport->InsertString(sMarker);
				rImport->GetCursor()->goLeft(2, sal_False);
			}
		}

        // finally, check for redlines that should start at
        // the section start node
        if( bValid )
            GetImport().GetTextImport()->
                RedlineAdjustStartNodeCursor(sal_True);

        if (pStyle != NULL)
        {
            pStyle->FillPropertySet( xTOCPropertySet );
        }

        Any aAny;
        aAny.setValue( &bProtected, ::getBooleanCppuType() );
        xTOCPropertySet->setPropertyValue( sIsProtected, aAny );

        if (sIndexName.getLength() > 0)
        {
            aAny <<= sIndexName;
            xTOCPropertySet->setPropertyValue( sName, aAny );
        }
    }
}

void XMLIndexTOCContext::EndElement()
{
    // complete import of index by removing the markers (if the index
    // was actually inserted, that is)
    if( bValid )
    {
        // preliminaries
        OUString sEmpty;
        UniReference<XMLTextImportHelper> rHelper= GetImport().GetTextImport();

        // get rid of last paragraph (unless it's the only paragraph)
        rHelper->GetCursor()->goRight(1, sal_False);
        if( xBodyContextRef.Is() &&
            ((XMLIndexBodyContext*)&xBodyContextRef)->HasContent() )
        {
            rHelper->GetCursor()->goLeft(1, sal_True);
            rHelper->GetText()->insertString(rHelper->GetCursorAsRange(), 
                                             sEmpty, sal_True);
        }

        // and delete second marker
        rHelper->GetCursor()->goRight(1, sal_True);
        rHelper->GetText()->insertString(rHelper->GetCursorAsRange(), 
                                         sEmpty, sal_True);	

        // check for Redlines on our end node
        GetImport().GetTextImport()->RedlineAdjustStartNodeCursor(sal_False);
    }
}

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

	if (bValid)
	{
		if (XML_NAMESPACE_TEXT == nPrefix)
		{
			if ( IsXMLToken( rLocalName, XML_INDEX_BODY ) )
			{
				pContext = new XMLIndexBodyContext(GetImport(), nPrefix,
												   rLocalName);
                if ( !xBodyContextRef.Is() || 
                     !((XMLIndexBodyContext*)&xBodyContextRef)->HasContent() )
                {
                    xBodyContextRef = pContext;
                }
			}
			else if (IsXMLToken(rLocalName, aIndexSourceElementMap[eIndexType]))
			{
				// instantiate source context for the appropriate index type
				switch (eIndexType)
				{
					case TEXT_INDEX_TOC:
						pContext = new XMLIndexTOCSourceContext(
							GetImport(), nPrefix, rLocalName, xTOCPropertySet);
						break;

					case TEXT_INDEX_OBJECT:
						pContext = new XMLIndexObjectSourceContext(
							GetImport(), nPrefix, rLocalName, xTOCPropertySet);
						break;

					case TEXT_INDEX_ALPHABETICAL:
						pContext = new XMLIndexAlphabeticalSourceContext(
							GetImport(), nPrefix, rLocalName, xTOCPropertySet);
						break;

					case TEXT_INDEX_USER:
						pContext = new XMLIndexUserSourceContext(
							GetImport(), nPrefix, rLocalName, xTOCPropertySet);
						break;

					case TEXT_INDEX_BIBLIOGRAPHY:
						pContext = new XMLIndexBibliographySourceContext(
							GetImport(), nPrefix, rLocalName, xTOCPropertySet);
						break;

					case TEXT_INDEX_TABLE:
						pContext = new XMLIndexTableSourceContext(
							GetImport(), nPrefix, rLocalName, xTOCPropertySet);
						break;

					case TEXT_INDEX_ILLUSTRATION:
						pContext = new XMLIndexIllustrationSourceContext(
							GetImport(), nPrefix, rLocalName, xTOCPropertySet);
						break;

					default:
						OSL_ENSURE(false, "index type not implemented");
						break;
				}
			}
			// else: ignore
		}
		// else: no text: namespace -> ignore
	}
	// else: not valid -> ignore

	// default: ignore
	if (pContext == NULL)
	{
		pContext = SvXMLImportContext::CreateChildContext(nPrefix, rLocalName,
														  xAttrList);
	}

	return pContext;
}
