/**************************************************************
 * 
 * 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 "XMLSectionImportContext.hxx"
#include "XMLSectionSourceImportContext.hxx"
#include "XMLSectionSourceDDEImportContext.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 <xmloff/prstylei.hxx>
#include <com/sun/star/container/XNamed.hpp>
#include <com/sun/star/uno/Reference.h>
#include <com/sun/star/text/XTextContent.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/text/ControlCharacter.hpp>


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::container::XNamed;

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


TYPEINIT1( XMLSectionImportContext, SvXMLImportContext );

const sal_Char sAPI_TextSection[] = "com.sun.star.text.TextSection";
const sal_Char sAPI_IndexHeaderSection[] = "com.sun.star.text.IndexHeaderSection";
const sal_Char sAPI_IsProtected[] = "IsProtected";
const sal_Char sAPI_Condition[] = "Condition";
const sal_Char sAPI_IsVisible[] = "IsVisible";
const sal_Char sAPI_IsCurrentlyVisible[] = "IsCurrentlyVisible";
const sal_Char sAPI_ProtectionKey[] = "ProtectionKey";

enum XMLSectionToken
{
    XML_TOK_SECTION_XMLID,
	XML_TOK_SECTION_STYLE_NAME,
	XML_TOK_SECTION_NAME,
	XML_TOK_SECTION_CONDITION,
	XML_TOK_SECTION_DISPLAY,
	XML_TOK_SECTION_PROTECT,
	XML_TOK_SECTION_PROTECTION_KEY,
    XML_TOK_SECTION_IS_HIDDEN
};

static __FAR_DATA SvXMLTokenMapEntry aSectionTokenMap[] =
{
	{ XML_NAMESPACE_XML , XML_ID, XML_TOK_SECTION_XMLID },
	{ XML_NAMESPACE_TEXT, XML_STYLE_NAME, XML_TOK_SECTION_STYLE_NAME },
	{ XML_NAMESPACE_TEXT, XML_NAME, XML_TOK_SECTION_NAME },
	{ XML_NAMESPACE_TEXT, XML_CONDITION, XML_TOK_SECTION_CONDITION },
	{ XML_NAMESPACE_TEXT, XML_DISPLAY, XML_TOK_SECTION_DISPLAY },
	{ XML_NAMESPACE_TEXT, XML_PROTECTED, XML_TOK_SECTION_PROTECT },
	{ XML_NAMESPACE_TEXT, XML_PROTECTION_KEY, XML_TOK_SECTION_PROTECTION_KEY},
    { XML_NAMESPACE_TEXT, XML_IS_HIDDEN, XML_TOK_SECTION_IS_HIDDEN },
	// compatibility with SRC629 (or earlier) versions
	{ XML_NAMESPACE_TEXT, XML_PROTECT, XML_TOK_SECTION_PROTECT },
	XML_TOKEN_MAP_END
};


// section import: This one is fairly tricky due to a variety of
// limits of the core or the API. The main problem is that if you
// insert a section within another section, you can't move the cursor
// between the ends of the inner and the enclosing section. To avoid
// these problems, additional markers are first inserted and later deleted.
XMLSectionImportContext::XMLSectionImportContext(
	SvXMLImport& rImport, 
	sal_uInt16 nPrfx,
	const OUString& rLocalName )
:	SvXMLImportContext(rImport, nPrfx, rLocalName)
,	sTextSection(RTL_CONSTASCII_USTRINGPARAM(sAPI_TextSection))
,	sIndexHeaderSection(RTL_CONSTASCII_USTRINGPARAM(sAPI_IndexHeaderSection))
,	sCondition(RTL_CONSTASCII_USTRINGPARAM(sAPI_Condition))
,	sIsVisible(RTL_CONSTASCII_USTRINGPARAM(sAPI_IsVisible))
,	sProtectionKey(RTL_CONSTASCII_USTRINGPARAM(sAPI_ProtectionKey))
,	sIsProtected(RTL_CONSTASCII_USTRINGPARAM(sAPI_IsProtected))
,	sIsCurrentlyVisible(RTL_CONSTASCII_USTRINGPARAM(sAPI_IsCurrentlyVisible))
,	bProtect(sal_False)
,	bCondOK(sal_False)
,	bIsVisible(sal_True)
,	bValid(sal_False)
,	bSequenceOK(sal_False)
,	bIsCurrentlyVisible(sal_True)
,	bIsCurrentlyVisibleOK(sal_False)
,	bHasContent(sal_False)
{
}

XMLSectionImportContext::~XMLSectionImportContext()
{
}

void XMLSectionImportContext::StartElement(
	const Reference<XAttributeList> & xAttrList)
{
	// process attributes
	ProcessAttributes(xAttrList);

	// process index headers:
	sal_Bool bIsIndexHeader = IsXMLToken( GetLocalName(), XML_INDEX_TITLE );
	if (bIsIndexHeader)
	{
		bValid = sal_True;
	}

	UniReference<XMLTextImportHelper> rHelper = GetImport().GetTextImport();

	// valid?
	if (bValid)
	{
		// create text section (as XPropertySet)
		Reference<XMultiServiceFactory> xFactory(
			GetImport().GetModel(),UNO_QUERY);
		if (xFactory.is())
		{
			Reference<XInterface> xIfc = 
				xFactory->createInstance( bIsIndexHeader ? sIndexHeaderSection 
														: sTextSection );
			if (xIfc.is()) 
			{
				Reference<XPropertySet> xPropSet(xIfc, UNO_QUERY);

				// save PropertySet (for CreateChildContext)
				xSectionPropertySet = xPropSet;

				// name
				Reference<XNamed> xNamed(xPropSet, UNO_QUERY);
				xNamed->setName(sName);

				// stylename?
				if (sStyleName.getLength() > 0)
				{
					XMLPropStyleContext* pStyle = rHelper->
						FindSectionStyle(sStyleName);

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

				// IsVisible and condition (not for index headers)
				if (! bIsIndexHeader)
				{
					Any aAny;
					aAny.setValue( &bIsVisible, ::getBooleanCppuType() );
					xPropSet->setPropertyValue( sIsVisible, aAny );

                    // #97450# hidden sections must be hidden on reload
                    // For backwards compatibilty, set flag only if it is 
                    // present
                    if( bIsCurrentlyVisibleOK )
                    {
                        aAny.setValue( &bIsCurrentlyVisible, 
                                       ::getBooleanCppuType() );
                        xPropSet->setPropertyValue( sIsCurrentlyVisible, aAny);
                    }

					if (bCondOK)
					{
						aAny <<= sCond;
						xPropSet->setPropertyValue( sCondition, aAny );
					}
				}

				// password (only for regular sections)
				if ( bSequenceOK &&
                     IsXMLToken(GetLocalName(), XML_SECTION) )
				{
					Any aAny;
					aAny <<= aSequence;
					xPropSet->setPropertyValue(sProtectionKey, aAny);
				}

				// protection
				Any aAny;
				aAny.setValue( &bProtect, ::getBooleanCppuType() );
				xPropSet->setPropertyValue( sIsProtected, aAny );

				// insert marker, <paragraph>, marker; then insert
				// section over the first marker character, and delete the
				// last paragraph (and marker) when closing a section.
				Reference<XTextRange> xStart = 
					rHelper->GetCursor()->getStart();
#ifndef DBG_UTIL
				static const sal_Char sMarker[] = " ";
#else
				static const sal_Char sMarker[] = "X";
#endif
				OUString sMarkerString(RTL_CONSTASCII_USTRINGPARAM(sMarker));
				rHelper->InsertString(sMarkerString);
				rHelper->InsertControlCharacter( 
					ControlCharacter::APPEND_PARAGRAPH );
				rHelper->InsertString(sMarkerString);
				
				// select first marker
				rHelper->GetCursor()->gotoRange(xStart, sal_False);
				rHelper->GetCursor()->goRight(1, sal_True);

				// convert section to XTextContent
				Reference<XTextContent> xTextContent(xSectionPropertySet, 
													 UNO_QUERY);

				// and insert (over marker)
				rHelper->GetText()->insertTextContent( 
					rHelper->GetCursorAsRange(), xTextContent, sal_True );

				// and delete first marker (in section)
				rHelper->GetText()->insertString( 
					rHelper->GetCursorAsRange(), sEmpty, sal_True);

				// finally, check for redlines that should start at
				// the section start node
				rHelper->RedlineAdjustStartNodeCursor(sal_True); // start ???

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

void XMLSectionImportContext::ProcessAttributes(
	const Reference<XAttributeList> & xAttrList )
{
	SvXMLTokenMap aTokenMap(aSectionTokenMap);
	
	sal_Int16 nLength = xAttrList->getLength();
	for(sal_Int16 nAttr = 0; nAttr < nLength; nAttr++)
	{
		OUString sLocalName;
		sal_uInt16 nNamePrefix = GetImport().GetNamespaceMap().
			GetKeyByAttrName( xAttrList->getNameByIndex(nAttr), 
							  &sLocalName );
		OUString sAttr = xAttrList->getValueByIndex(nAttr);

		switch (aTokenMap.Get(nNamePrefix, sLocalName))
		{
			case XML_TOK_SECTION_XMLID:
                sXmlId = sAttr;
				break;
			case XML_TOK_SECTION_STYLE_NAME:
				sStyleName = sAttr;
				break;
			case XML_TOK_SECTION_NAME:
				sName = sAttr;
				bValid = sal_True;
				break;
			case XML_TOK_SECTION_CONDITION:
				{
					OUString sTmp;
					sal_uInt16 nPrefix = GetImport().GetNamespaceMap().
									_GetKeyByAttrName( sAttr, &sTmp, sal_False );
					if( XML_NAMESPACE_OOOW == nPrefix )
					{
						sCond = sTmp;
						bCondOK = sal_True;
					}
					else
						sCond = sAttr;
				}
				break;
			case XML_TOK_SECTION_DISPLAY:
				if (IsXMLToken(sAttr, XML_TRUE))
				{
					bIsVisible = sal_True;
				}
				else if ( IsXMLToken(sAttr, XML_NONE) ||
						  IsXMLToken(sAttr, XML_CONDITION) )
				{
					bIsVisible = sal_False;
				}
				// else: ignore
				break;
			case XML_TOK_SECTION_IS_HIDDEN:
                {
                    sal_Bool bTmp;
                    if (SvXMLUnitConverter::convertBool(bTmp, sAttr))
                    {
                        bIsCurrentlyVisible = !bTmp;
                        bIsCurrentlyVisibleOK = sal_True;
                    }
                }
                break;
			case XML_TOK_SECTION_PROTECTION_KEY:
				SvXMLUnitConverter::decodeBase64(aSequence, sAttr);
				bSequenceOK = sal_True;
				break;
			case XML_TOK_SECTION_PROTECT:
			{
				sal_Bool bTmp;
				if (SvXMLUnitConverter::convertBool(bTmp, sAttr))
				{
					bProtect = bTmp;
				}
				break;
			}
			default:
				; // ignore
				break;
		}
	}
}

void XMLSectionImportContext::EndElement()
{
	// get rid of last paragraph 
	// (unless it's the only paragraph in the section)
	UniReference<XMLTextImportHelper> rHelper = GetImport().GetTextImport();
	rHelper->GetCursor()->goRight(1, sal_False);
	if (bHasContent)
	{
		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 to our endnode
    rHelper->RedlineAdjustStartNodeCursor(sal_False);
}

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

	// section-source (-dde) elements
	if ( (XML_NAMESPACE_TEXT == nPrefix) &&
         IsXMLToken(rLocalName, XML_SECTION_SOURCE) )
	{
		pContext = new XMLSectionSourceImportContext(GetImport(),
													 nPrefix, rLocalName, 
													 xSectionPropertySet);
	} 
	else if ( (XML_NAMESPACE_OFFICE == nPrefix) &&
              IsXMLToken(rLocalName, XML_DDE_SOURCE) )
	{
		pContext = new XMLSectionSourceDDEImportContext(GetImport(),
														nPrefix, rLocalName,
														xSectionPropertySet);
	}
	else
	{
		// otherwise: text context
		pContext = GetImport().GetTextImport()->CreateTextChildContext(
			GetImport(), nPrefix, rLocalName, xAttrList,
			XML_TEXT_TYPE_SECTION );

		// if that fails, default context
		if (NULL == pContext)
		{
			pContext = new SvXMLImportContext( GetImport(), 
											   nPrefix, rLocalName );
		}
		else
			bHasContent = sal_True;
	}

	return pContext;
}

