/**************************************************************
 *
 * 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 "XMLTextMarkImportContext.hxx"


#include <rtl/ustring.hxx>
#include <tools/debug.hxx>
#include <xmloff/xmluconv.hxx>
#include <xmloff/xmltoken.hxx>
#include <xmloff/xmlimp.hxx>
#include <xmloff/nmspmap.hxx>
#include "xmloff/xmlnmspe.hxx"
#include <xmloff/odffields.hxx>
#include <com/sun/star/xml/sax/XAttributeList.hpp>
#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/container/XNamed.hpp>
#include <com/sun/star/rdf/XMetadatable.hpp>

#include <com/sun/star/text/XFormField.hpp>

#include "RDFaImportHelper.hxx"


using ::rtl::OUString;
using ::rtl::OUStringBuffer;

using namespace ::com::sun::star;
using namespace ::com::sun::star::text;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::xml::sax;
using namespace ::xmloff::token;


XMLFieldParamImportContext::XMLFieldParamImportContext(
	SvXMLImport& rImport,
	XMLTextImportHelper& rHlp,
	sal_uInt16 nPrefix,
	const OUString& rLocalName ) :
		SvXMLImportContext(rImport, nPrefix, rLocalName),
		rHelper(rHlp)
{
}


void XMLFieldParamImportContext::StartElement(const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList> & xAttrList)
{
	SvXMLImport& rImport = GetImport();
	::rtl::OUString sName;
	::rtl::OUString sValue;

	sal_Int16 nLength = xAttrList->getLength();
	for(sal_Int16 nAttr = 0; nAttr < nLength; nAttr++)
	{
		OUString sLocalName;
		sal_uInt16 nPrefix = rImport.GetNamespaceMap().
			GetKeyByAttrName( xAttrList->getNameByIndex(nAttr),
							  &sLocalName );

		if ( (XML_NAMESPACE_FIELD == nPrefix) &&
			 IsXMLToken(sLocalName, XML_NAME)   )
		{
			sName = xAttrList->getValueByIndex(nAttr);
		}
		if ( (XML_NAMESPACE_FIELD == nPrefix) &&
			 IsXMLToken(sLocalName, XML_VALUE)   )
		{
			sValue = xAttrList->getValueByIndex(nAttr);
		}
	}
	if (rHelper.hasCurrentFieldCtx() && sName.getLength()>0) {
		rHelper.addFieldParam(sName, sValue);
	}
}


TYPEINIT1( XMLTextMarkImportContext, SvXMLImportContext);

XMLTextMarkImportContext::XMLTextMarkImportContext(
	SvXMLImport& rImport,
	XMLTextImportHelper& rHlp,
	sal_uInt16 nPrefix,
    const OUString& rLocalName )
    : SvXMLImportContext(rImport, nPrefix, rLocalName)
    , m_rHelper(rHlp)
    , m_bHaveAbout(false)
{
}

enum lcl_MarkType { TypeReference, TypeReferenceStart, TypeReferenceEnd,
					TypeBookmark, TypeBookmarkStart, TypeBookmarkEnd,
					TypeFieldmark, TypeFieldmarkStart, TypeFieldmarkEnd
				  };

static SvXMLEnumMapEntry __READONLY_DATA lcl_aMarkTypeMap[] =
{
	{ XML_REFERENCE_MARK,			TypeReference },
	{ XML_REFERENCE_MARK_START,	    TypeReferenceStart },
	{ XML_REFERENCE_MARK_END,		TypeReferenceEnd },
	{ XML_BOOKMARK,				    TypeBookmark },
	{ XML_BOOKMARK_START,			TypeBookmarkStart },
	{ XML_BOOKMARK_END,			    TypeBookmarkEnd },
	{ XML_FIELDMARK,				TypeFieldmark },
	{ XML_FIELDMARK_START,			TypeFieldmarkStart },
	{ XML_FIELDMARK_END,			TypeFieldmarkEnd },
	{ XML_TOKEN_INVALID,    		0 },
};


static const char *lcl_getFormFieldmarkName(rtl::OUString &name)
{
    static const char sCheckbox[]=ODF_FORMCHECKBOX;
    static const char sFormDropDown[]=ODF_FORMDROPDOWN;
    if (name.compareToAscii("msoffice.field.FORMCHECKBOX")==0)
        return sCheckbox;
    else if (name.compareToAscii(ODF_FORMCHECKBOX)==0)
        return sCheckbox;
    if (name.compareToAscii(ODF_FORMDROPDOWN)==0)
        return sFormDropDown;
    else
        return NULL;
}

static rtl::OUString lcl_getFieldmarkName(rtl::OUString &name)
{
    static const char sFormtext[]=ODF_FORMTEXT;
    if (name.compareToAscii("msoffice.field.FORMTEXT")==0)
        return rtl::OUString::createFromAscii(sFormtext);
    else if (name.compareToAscii(ODF_FORMTEXT)==0)
        return rtl::OUString::createFromAscii(sFormtext);
    else
        return name;
}


void XMLTextMarkImportContext::StartElement(
	const Reference<XAttributeList> & xAttrList)
{
    if (!FindName(GetImport(), xAttrList))
    {
        m_sBookmarkName = OUString();
    }

	if (IsXMLToken(GetLocalName(), XML_FIELDMARK_END))
    {
        m_sBookmarkName = m_rHelper.FindActiveBookmarkName();
    }

    if (IsXMLToken(GetLocalName(), XML_FIELDMARK_START) || IsXMLToken(GetLocalName(), XML_FIELDMARK))
    {
        if (m_sBookmarkName.getLength() == 0)
        {
            m_sBookmarkName = ::rtl::OUString::createFromAscii("Unknown");
        }
        m_rHelper.pushFieldCtx( m_sBookmarkName, m_sFieldName );
	}
}

void XMLTextMarkImportContext::EndElement()
{
	SvXMLImportContext::EndElement();

    static const OUString sAPI_reference_mark(
		RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.ReferenceMark"));
    static const OUString sAPI_bookmark(
		RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.Bookmark"));
    static const OUString sAPI_fieldmark(
		RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.Fieldmark"));
    static const OUString sAPI_formfieldmark(
		RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.FormFieldmark"));

    if (m_sBookmarkName.getLength() > 0)
	{
		sal_uInt16 nTmp;
		if (SvXMLUnitConverter::convertEnum(nTmp, GetLocalName(),
											lcl_aMarkTypeMap))
		{
			switch ((lcl_MarkType)nTmp)
			{
				case TypeReference:
					// export point reference mark
					CreateAndInsertMark(GetImport(),
                        sAPI_reference_mark,
                        m_sBookmarkName,
                        m_rHelper.GetCursorAsRange()->getStart(),
                        ::rtl::OUString());
					break;

				case TypeFieldmark:
				case TypeBookmark:
					{
                        const char *formFieldmarkName=lcl_getFormFieldmarkName(m_sFieldName);
                        bool bImportAsField=((lcl_MarkType)nTmp==TypeFieldmark && formFieldmarkName!=NULL); //@TODO handle abbreviation cases..
						// export point bookmark
                        const Reference<XInterface> xContent(
                            CreateAndInsertMark(GetImport(),
										(bImportAsField?sAPI_formfieldmark:sAPI_bookmark),
                                m_sBookmarkName,
                                m_rHelper.GetCursorAsRange()->getStart(),
                                m_sXmlId) );
						if ((lcl_MarkType)nTmp==TypeFieldmark) {
                            if (xContent.is() && bImportAsField) {
								// setup fieldmark...
                                Reference< ::com::sun::star::text::XFormField> xFormField(xContent, UNO_QUERY);
                                xFormField->setFieldType(rtl::OUString::createFromAscii(formFieldmarkName));
                                if (xFormField.is() && m_rHelper.hasCurrentFieldCtx()) {
                                    m_rHelper.setCurrentFieldParamsTo(xFormField);
								}
							}
                            m_rHelper.popFieldCtx();
						}
					}
					break;

				case TypeFieldmarkStart:
				case TypeBookmarkStart:
					// save XTextRange for later construction of bookmark
                    {
                        ::boost::shared_ptr< ::xmloff::ParsedRDFaAttributes >
                            pRDFaAttributes;
                        if (m_bHaveAbout && (TypeBookmarkStart
                                == static_cast<lcl_MarkType>(nTmp)))
                        {
                            pRDFaAttributes =
                                GetImport().GetRDFaImportHelper().ParseRDFa(
                                    m_sAbout, m_sProperty,
                                    m_sContent, m_sDatatype);
                        }
                        m_rHelper.InsertBookmarkStartRange(
                            m_sBookmarkName,
                            m_rHelper.GetCursorAsRange()->getStart(),
                            m_sXmlId, pRDFaAttributes);
                    }
					break;

				case TypeFieldmarkEnd:
				case TypeBookmarkEnd:
				{
					// get old range, and construct
					Reference<XTextRange> xStartRange;
                    ::boost::shared_ptr< ::xmloff::ParsedRDFaAttributes >
                        pRDFaAttributes;
                    if (m_rHelper.FindAndRemoveBookmarkStartRange(
                            m_sBookmarkName, xStartRange,
                            m_sXmlId, pRDFaAttributes))
					{
						Reference<XTextRange> xEndRange(
                            m_rHelper.GetCursorAsRange()->getStart());

						// check if beginning and end are in same XText
						if (xStartRange->getText() == xEndRange->getText())
						{
							// create range for insertion
							Reference<XTextCursor> xInsertionCursor =
                                m_rHelper.GetText()->createTextCursorByRange(
									xEndRange);
                            try {
							xInsertionCursor->gotoRange(xStartRange, sal_True);
                            } catch (uno::Exception&) {
                                OSL_ENSURE(false,
                                    "cannot go to end position of bookmark");
                            }

							//DBG_ASSERT(! xInsertionCursor->isCollapsed(),
							// 				"we want no point mark");
							// can't assert, because someone could
							// create a file with subsequence
							// start/end elements

							Reference<XTextRange> xInsertionRange(
								xInsertionCursor, UNO_QUERY);

                            bool bImportAsField=((lcl_MarkType)nTmp==TypeFieldmarkEnd && m_rHelper.hasCurrentFieldCtx());

							// insert reference
                            const Reference<XInterface> xContent(
                                CreateAndInsertMark(GetImport(),
												(bImportAsField?sAPI_fieldmark:sAPI_bookmark),
                                    m_sBookmarkName,
                                    xInsertionRange,
                                    m_sXmlId) );
                            if (pRDFaAttributes)
                            {
                                const Reference<rdf::XMetadatable>
                                    xMeta(xContent, UNO_QUERY);
                                GetImport().GetRDFaImportHelper().AddRDFa(
                                    xMeta, pRDFaAttributes);
                            }

							if ((lcl_MarkType)nTmp==TypeFieldmarkEnd) {
                                if (xContent.is() && bImportAsField) {
									// setup fieldmark...
                                    Reference< ::com::sun::star::text::XFormField> xFormField(xContent, UNO_QUERY);
                                    if (xFormField.is() && m_rHelper.hasCurrentFieldCtx()) {
                                        rtl::OUString givenTypeName=m_rHelper.getCurrentFieldType();
                                        rtl::OUString fieldmarkTypeName=lcl_getFieldmarkName(givenTypeName);

                                        xFormField->setFieldType(fieldmarkTypeName);
                                        m_rHelper.setCurrentFieldParamsTo(xFormField);
									}
								}
								m_rHelper.popFieldCtx();
							}
						}
						// else: beginning/end in different XText -> ignore!
					}
					// else: no start found -> ignore!
					break;
				}

				case TypeReferenceStart:
				case TypeReferenceEnd:
					DBG_ERROR("reference start/end are handled in txtparai !");
					break;

				default:
					DBG_ERROR("unknown mark type");
					break;
			}
		}
	}
}

SvXMLImportContext *XMLTextMarkImportContext::CreateChildContext( sal_uInt16 nPrefix,
                                        const ::rtl::OUString& rLocalName,
                                        const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >&  )
{
    return new XMLFieldParamImportContext(GetImport(), m_rHelper,
                nPrefix, rLocalName);
}


Reference<XTextContent> XMLTextMarkImportContext::CreateAndInsertMark(
    SvXMLImport& rImport,
    const OUString& sServiceName,
    const OUString& sMarkName,
    const Reference<XTextRange> & rRange,
    const OUString& i_rXmlId)
{
    // create mark
    const Reference<XMultiServiceFactory> xFactory(rImport.GetModel(),
        UNO_QUERY);
    Reference<XInterface> xIfc;

    if (xFactory.is())
    {
        xIfc = xFactory->createInstance(sServiceName);

        if (!xIfc.is())
        {
            OSL_ENSURE(false, "CreateAndInsertMark: cannot create service?");
            return 0;
        }

        // set name (unless there is no name (text:meta))
        const Reference<XNamed> xNamed(xIfc, UNO_QUERY);
        if (xNamed.is())
        {
            xNamed->setName(sMarkName);
        }
        else
        {
            if (sMarkName.getLength())
            {
                OSL_ENSURE(false, "name given, but XNamed not supported?");
                return 0;
            }
        }

        // cast to XTextContent and attach to document
        const Reference<XTextContent> xTextContent(xIfc, UNO_QUERY);
        if (xTextContent.is())
        {
            try
            {
                // if inserting marks, bAbsorb==sal_False will cause
                // collapsing of the given XTextRange.
                rImport.GetTextImport()->GetText()->insertTextContent(rRange,
                    xTextContent, sal_True);

                // xml:id for RDF metadata -- after insertion!
                rImport.SetXmlId(xIfc, i_rXmlId);

                return xTextContent;
            }
            catch (com::sun::star::lang::IllegalArgumentException &)
            {
                OSL_ENSURE(false, "CreateAndInsertMark: cannot insert?");
                return 0;
            }
        }
    }
    return 0;
}

sal_Bool XMLTextMarkImportContext::FindName(
	SvXMLImport& rImport,
    const Reference<XAttributeList> & xAttrList)
{
	sal_Bool bNameOK = sal_False;

	// find name attribute first
    const sal_Int16 nLength = xAttrList->getLength();
	for(sal_Int16 nAttr = 0; nAttr < nLength; nAttr++)
	{
		OUString sLocalName;
        const sal_uInt16 nPrefix = rImport.GetNamespaceMap().
			GetKeyByAttrName( xAttrList->getNameByIndex(nAttr),
							  &sLocalName );

		if ( (XML_NAMESPACE_TEXT == nPrefix) &&
			 IsXMLToken(sLocalName, XML_NAME)   )
		{
            m_sBookmarkName = xAttrList->getValueByIndex(nAttr);
			bNameOK = sal_True;
		}
		else if ( (XML_NAMESPACE_XML == nPrefix) &&
			 IsXMLToken(sLocalName, XML_ID)   )
		{
            m_sXmlId = xAttrList->getValueByIndex(nAttr);
		}
        else if ( XML_NAMESPACE_XHTML == nPrefix )
        {
            // RDFa
            if ( IsXMLToken( sLocalName, XML_ABOUT) )
            {
                m_sAbout = xAttrList->getValueByIndex(nAttr);
                m_bHaveAbout = true;
            }
            else if ( IsXMLToken( sLocalName, XML_PROPERTY) )
            {
                m_sProperty = xAttrList->getValueByIndex(nAttr);
            }
            else if ( IsXMLToken( sLocalName, XML_CONTENT) )
            {
                m_sContent = xAttrList->getValueByIndex(nAttr);
            }
            else if ( IsXMLToken( sLocalName, XML_DATATYPE) )
            {
                m_sDatatype = xAttrList->getValueByIndex(nAttr);
            }
        }
        else if ( (XML_NAMESPACE_FIELD == nPrefix) &&
			 IsXMLToken(sLocalName, XML_TYPE)   )
		{
            m_sFieldName = xAttrList->getValueByIndex(nAttr);
		}
	}

	return bNameOK;
}
