/**************************************************************
 *
 * 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 "XMLRedlineExport.hxx"
#include <tools/debug.hxx>
#include <rtl/ustring.hxx>
#include <rtl/ustrbuf.hxx>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/beans/UnknownPropertyException.hpp>
#include <com/sun/star/container/XEnumerationAccess.hpp>

#include <com/sun/star/container/XEnumeration.hpp>
#include <com/sun/star/document/XRedlinesSupplier.hpp>
#include <com/sun/star/text/XText.hpp>
#include <com/sun/star/text/XTextContent.hpp>
#include <com/sun/star/text/XTextSection.hpp>
#include <com/sun/star/util/DateTime.hpp>
#include <xmloff/xmltoken.hxx>
#include "xmloff/xmlnmspe.hxx"
#include <xmloff/xmlexp.hxx>
#include <xmloff/xmluconv.hxx>


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

using ::com::sun::star::beans::PropertyValue;
using ::com::sun::star::beans::XPropertySet;
using ::com::sun::star::beans::UnknownPropertyException;
using ::com::sun::star::document::XRedlinesSupplier;
using ::com::sun::star::container::XEnumerationAccess;
using ::com::sun::star::container::XEnumeration;
using ::com::sun::star::text::XText;
using ::com::sun::star::text::XTextContent;
using ::com::sun::star::text::XTextSection;
using ::com::sun::star::uno::Any;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::Sequence;
using ::com::sun::star::util::DateTime;
using ::rtl::OUString;
using ::rtl::OUStringBuffer;
using ::std::list;


XMLRedlineExport::XMLRedlineExport(SvXMLExport& rExp)
:	sDelete(RTL_CONSTASCII_USTRINGPARAM("Delete"))
,	sDeletion(GetXMLToken(XML_DELETION))
,	sFormat(RTL_CONSTASCII_USTRINGPARAM("Format"))
,	sFormatChange(GetXMLToken(XML_FORMAT_CHANGE))
,	sInsert(RTL_CONSTASCII_USTRINGPARAM("Insert"))
,	sInsertion(GetXMLToken(XML_INSERTION))
,	sIsCollapsed(RTL_CONSTASCII_USTRINGPARAM("IsCollapsed"))
,	sIsStart(RTL_CONSTASCII_USTRINGPARAM("IsStart"))
,	sRedlineAuthor(RTL_CONSTASCII_USTRINGPARAM("RedlineAuthor"))
,	sRedlineComment(RTL_CONSTASCII_USTRINGPARAM("RedlineComment"))
,	sRedlineDateTime(RTL_CONSTASCII_USTRINGPARAM("RedlineDateTime"))
,	sRedlineSuccessorData(RTL_CONSTASCII_USTRINGPARAM("RedlineSuccessorData"))
,	sRedlineText(RTL_CONSTASCII_USTRINGPARAM("RedlineText"))
,	sRedlineType(RTL_CONSTASCII_USTRINGPARAM("RedlineType"))
,	sStyle(RTL_CONSTASCII_USTRINGPARAM("Style"))
,	sTextTable(RTL_CONSTASCII_USTRINGPARAM("TextTable"))
,	sUnknownChange(RTL_CONSTASCII_USTRINGPARAM("UnknownChange"))
,	sStartRedline(RTL_CONSTASCII_USTRINGPARAM("StartRedline"))
,	sEndRedline(RTL_CONSTASCII_USTRINGPARAM("EndRedline"))
,	sRedlineIdentifier(RTL_CONSTASCII_USTRINGPARAM("RedlineIdentifier"))
,	sIsInHeaderFooter(RTL_CONSTASCII_USTRINGPARAM("IsInHeaderFooter"))
,	sRedlineProtectionKey(RTL_CONSTASCII_USTRINGPARAM("RedlineProtectionKey"))
,	sRecordChanges(RTL_CONSTASCII_USTRINGPARAM("RecordChanges"))
,	sMergeLastPara(RTL_CONSTASCII_USTRINGPARAM("MergeLastPara"))
,	sChangePrefix(RTL_CONSTASCII_USTRINGPARAM("ct"))
,	rExport(rExp)
,	pCurrentChangesList(NULL)
{
}


XMLRedlineExport::~XMLRedlineExport()
{
	// delete changes lists
	for( ChangesMapType::iterator aIter = aChangeMap.begin();
		 aIter != aChangeMap.end();
		 aIter++ )
	{
		delete aIter->second;
	}
	aChangeMap.clear();
}


void XMLRedlineExport::ExportChange(
	const Reference<XPropertySet> & rPropSet,
	sal_Bool bAutoStyle)
{
	if (bAutoStyle)
	{
        // For the headers/footers, we have to collect the autostyles
        // here.  For the general case, however, it's better to collet
        // the autostyles by iterating over the global redline
        // list. So that's what we do: Here, we collect autostyles
        // only if we have no current list of changes. For the
        // main-document case, the autostyles are collected in
        // ExportChangesListAutoStyles().
        if (pCurrentChangesList != NULL)
            ExportChangeAutoStyle(rPropSet);
	}
	else
	{
		ExportChangeInline(rPropSet);
	}
}


void XMLRedlineExport::ExportChangesList(sal_Bool bAutoStyles)
{
	if (bAutoStyles)
	{
		ExportChangesListAutoStyles();
	}
	else
	{
		ExportChangesListElements();
	}
}


void XMLRedlineExport::ExportChangesList(
	const Reference<XText> & rText,
	sal_Bool bAutoStyles)
{
    // in the header/footer case, auto styles are collected from the
    // inline change elements.
    if (bAutoStyles)
        return;

	// look for changes list for this XText
	ChangesMapType::iterator aFind = aChangeMap.find(rText);
	if (aFind != aChangeMap.end())
	{
		ChangesListType* pChangesList = aFind->second;

		// export only if changes are found
		if (pChangesList->size() > 0)
		{
			// changes container element
			SvXMLElementExport aChanges(rExport, XML_NAMESPACE_TEXT,
										XML_TRACKED_CHANGES,
										sal_True, sal_True);

			// iterate over changes list
			for( ChangesListType::iterator aIter = pChangesList->begin();
				 aIter != pChangesList->end();
				 aIter++ )
			{
                ExportChangedRegion( *aIter );
			}
		}
		// else: changes list empty -> ignore
	}
	// else: no changes list found -> empty
}

void XMLRedlineExport::SetCurrentXText(
	const Reference<XText> & rText)
{
	if (rText.is())
	{
		// look for appropriate list in map; use the found one, or create new
		ChangesMapType::iterator aIter = aChangeMap.find(rText);
		if (aIter == aChangeMap.end())
		{
			ChangesListType* pList = new ChangesListType;
			aChangeMap[rText] = pList;
			pCurrentChangesList = pList;
		}
		else
			pCurrentChangesList = aIter->second;
	}
	else
	{
		// don't record changes
		SetCurrentXText();
	}
}

void XMLRedlineExport::SetCurrentXText()
{
	pCurrentChangesList = NULL;
}


void XMLRedlineExport::ExportChangesListElements()
{
	// get redlines (aka tracked changes) from the model
	Reference<XRedlinesSupplier> xSupplier(rExport.GetModel(), uno::UNO_QUERY);
	if (xSupplier.is())
	{
		Reference<XEnumerationAccess> aEnumAccess = xSupplier->getRedlines();

		// redline protection key
		Reference<XPropertySet> aDocPropertySet( rExport.GetModel(),
												 uno::UNO_QUERY );
		// redlining enabled?
		sal_Bool bEnabled = *(sal_Bool*)aDocPropertySet->getPropertyValue(
												sRecordChanges ).getValue();

		// only export if we have redlines or attributes
		if ( aEnumAccess->hasElements() || bEnabled )
		{

			// export only if we have changes, but tracking is not enabled
			if ( !bEnabled != !aEnumAccess->hasElements() )
			{
				rExport.AddAttribute(
					XML_NAMESPACE_TEXT, XML_TRACK_CHANGES,
					bEnabled ? XML_TRUE : XML_FALSE );
			}

			// changes container element
			SvXMLElementExport aChanges(rExport, XML_NAMESPACE_TEXT,
										XML_TRACKED_CHANGES,
										sal_True, sal_True);

			// get enumeration and iterate over elements
			Reference<XEnumeration> aEnum = aEnumAccess->createEnumeration();
			while (aEnum->hasMoreElements())
			{
				Any aAny = aEnum->nextElement();
				Reference<XPropertySet> xPropSet;
				aAny >>= xPropSet;

				DBG_ASSERT(xPropSet.is(),
						   "can't get XPropertySet; skipping Redline");
				if (xPropSet.is())
				{
					// export only if not in header or footer
					// (those must be exported with their XText)
					aAny = xPropSet->getPropertyValue(sIsInHeaderFooter);
					if (! *(sal_Bool*)aAny.getValue())
					{
						// and finally, export change
						ExportChangedRegion(xPropSet);
					}
				}
				// else: no XPropertySet -> no export
			}
		}
		// else: no redlines -> no export
	}
	// else: no XRedlineSupplier -> no export
}

void XMLRedlineExport::ExportChangeAutoStyle(
	const Reference<XPropertySet> & rPropSet)
{
	// record change (if changes should be recorded)
	if (NULL != pCurrentChangesList)
	{
		// put redline in list if it's collapsed or the redline start
		Any aIsStart = rPropSet->getPropertyValue(sIsStart);
		Any aIsCollapsed = rPropSet->getPropertyValue(sIsCollapsed);

		if ( *(sal_Bool*)aIsStart.getValue() ||
			 *(sal_Bool*)aIsCollapsed.getValue() )
			pCurrentChangesList->push_back(rPropSet);
	}

	// get XText for export of redline auto styles
	Any aAny = rPropSet->getPropertyValue(sRedlineText);
	Reference<XText> xText;
	aAny >>= xText;
	if (xText.is())
	{
		// export the auto styles
		rExport.GetTextParagraphExport()->collectTextAutoStyles(xText);
	}
}

void XMLRedlineExport::ExportChangesListAutoStyles()
{
	// get redlines (aka tracked changes) from the model
	Reference<XRedlinesSupplier> xSupplier(rExport.GetModel(), uno::UNO_QUERY);
	if (xSupplier.is())
	{
		Reference<XEnumerationAccess> aEnumAccess = xSupplier->getRedlines();

		// only export if we actually have redlines
		if (aEnumAccess->hasElements())
		{
			// get enumeration and iterate over elements
			Reference<XEnumeration> aEnum = aEnumAccess->createEnumeration();
			while (aEnum->hasMoreElements())
			{
				Any aAny = aEnum->nextElement();
				Reference<XPropertySet> xPropSet;
				aAny >>= xPropSet;

				DBG_ASSERT(xPropSet.is(),
						   "can't get XPropertySet; skipping Redline");
				if (xPropSet.is())
				{

                    // export only if not in header or footer
                    // (those must be exported with their XText)
                    aAny = xPropSet->getPropertyValue(sIsInHeaderFooter);
                    if (! *(sal_Bool*)aAny.getValue())
					{
                        ExportChangeAutoStyle(xPropSet);
                    }
				}
			}
		}
	}
}

void XMLRedlineExport::ExportChangeInline(
	const Reference<XPropertySet> & rPropSet)
{
	// determine element name (depending on collapsed, start/end)
	enum XMLTokenEnum eElement = XML_TOKEN_INVALID;
	Any aAny = rPropSet->getPropertyValue(sIsCollapsed);
	sal_Bool bCollapsed = *(sal_Bool *)aAny.getValue();
	sal_Bool bStart = sal_True;	// ignored if bCollapsed = sal_True
	if (bCollapsed)
	{
		eElement = XML_CHANGE;
	}
	else
	{
		aAny = rPropSet->getPropertyValue(sIsStart);
		bStart = *(sal_Bool *)aAny.getValue();
		eElement = bStart ? XML_CHANGE_START : XML_CHANGE_END;
	}

	if (XML_TOKEN_INVALID != eElement)
	{
		// we always need the ID
		rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_CHANGE_ID,
							 GetRedlineID(rPropSet));

		// export the element (no whitespace because we're in the text body)
		SvXMLElementExport aChangeElem(rExport, XML_NAMESPACE_TEXT,
									   eElement, sal_False, sal_False);
	}
}


void XMLRedlineExport::ExportChangedRegion(
	const Reference<XPropertySet> & rPropSet)
{
	// Redline-ID
    rExport.AddAttributeIdLegacy(XML_NAMESPACE_TEXT, GetRedlineID(rPropSet));

    // merge-last-paragraph
    Any aAny = rPropSet->getPropertyValue(sMergeLastPara);
    if( ! *(sal_Bool*)aAny.getValue() )
        rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_MERGE_LAST_PARAGRAPH,
                             XML_FALSE);

    // export change region element
	SvXMLElementExport aChangedRegion(rExport, XML_NAMESPACE_TEXT,
									  XML_CHANGED_REGION, sal_True, sal_True);


	// scope for (first) change element
	{
		aAny = rPropSet->getPropertyValue(sRedlineType);
		OUString sType;
		aAny >>= sType;
		SvXMLElementExport aChange(rExport, XML_NAMESPACE_TEXT,
								   ConvertTypeName(sType), sal_True, sal_True);

		ExportChangeInfo(rPropSet);

		// get XText from the redline and export (if the XText exists)
		aAny = rPropSet->getPropertyValue(sRedlineText);
		Reference<XText> xText;
		aAny >>= xText;
		if (xText.is())
		{
			rExport.GetTextParagraphExport()->exportText(xText);
			// default parameters: bProgress, bExportParagraph ???
		}
		// else: no text interface -> content is inline and will
		//       be exported there
	}

	// changed change? Hierarchical changes can onl be two levels
	// deep. Here we check for the second level.
	aAny = rPropSet->getPropertyValue(sRedlineSuccessorData);
	Sequence<PropertyValue> aSuccessorData;
	aAny >>= aSuccessorData;

	// if we actually got a hierarchical change, make element and
	// process change info
	if (aSuccessorData.getLength() > 0)
	{
		// The only change that can be "undone" is an insertion -
		// after all, you can't re-insert an deletion, but you can
		// delete an insertion. This assumption is asserted in
		// ExportChangeInfo(Sequence<PropertyValue>&).
		SvXMLElementExport aSecondChangeElem(
			rExport, XML_NAMESPACE_TEXT, XML_INSERTION,
			sal_True, sal_True);

		ExportChangeInfo(aSuccessorData);
	}
	// else: no hierarchical change
}


const OUString XMLRedlineExport::ConvertTypeName(
	const OUString& sApiName)
{
	if (sApiName == sDelete)
	{
		return sDeletion;
	}
	else if (sApiName == sInsert)
	{
		return sInsertion;
	}
	else if (sApiName == sFormat)
	{
		return sFormatChange;
	}
	else
	{
		DBG_ERROR("unknown redline type");
		return sUnknownChange;
	}
}


/** Create a Redline-ID */
const OUString XMLRedlineExport::GetRedlineID(
	const Reference<XPropertySet> & rPropSet)
{
	Any aAny = rPropSet->getPropertyValue(sRedlineIdentifier);
	OUString sTmp;
	aAny >>= sTmp;

	OUStringBuffer sBuf(sChangePrefix);
	sBuf.append(sTmp);
	return sBuf.makeStringAndClear();
}


void XMLRedlineExport::ExportChangeInfo(
	const Reference<XPropertySet> & rPropSet)
{

	SvXMLElementExport aChangeInfo(rExport, XML_NAMESPACE_OFFICE,
								   XML_CHANGE_INFO, sal_True, sal_True);

	Any aAny = rPropSet->getPropertyValue(sRedlineAuthor);
	OUString sTmp;
	aAny >>= sTmp;
	if (sTmp.getLength() > 0)
	{
		SvXMLElementExport aCreatorElem( rExport, XML_NAMESPACE_DC,
										  XML_CREATOR, sal_True,
										  sal_False );
		rExport.Characters(sTmp);
	}

	aAny = rPropSet->getPropertyValue(sRedlineDateTime);
	util::DateTime aDateTime;
	aAny >>= aDateTime;
	{
		OUStringBuffer sBuf;
		rExport.GetMM100UnitConverter().convertDateTime(sBuf, aDateTime);
		SvXMLElementExport aDateElem( rExport, XML_NAMESPACE_DC,
										  XML_DATE, sal_True,
										  sal_False );
		rExport.Characters(sBuf.makeStringAndClear());
	}

	// comment as <text:p> sequence
	aAny = rPropSet->getPropertyValue(sRedlineComment);
	aAny >>= sTmp;
    WriteComment( sTmp );
}

void XMLRedlineExport::ExportChangeInfo(
	const Sequence<PropertyValue> & rPropertyValues)
{
    OUString sComment;

	sal_Int32 nCount = rPropertyValues.getLength();
	for(sal_Int32 i = 0; i < nCount; i++)
	{
		const PropertyValue& rVal = rPropertyValues[i];

		if( rVal.Name.equals(sRedlineAuthor) )
		{
			OUString sTmp;
			rVal.Value >>= sTmp;
			if (sTmp.getLength() > 0)
			{
				rExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_CHG_AUTHOR, sTmp);
			}
		}
        else if( rVal.Name.equals(sRedlineComment) )
        {
            rVal.Value >>= sComment;
        }
		else if( rVal.Name.equals(sRedlineDateTime) )
		{
			util::DateTime aDateTime;
			rVal.Value >>= aDateTime;
			OUStringBuffer sBuf;
			rExport.GetMM100UnitConverter().convertDateTime(sBuf, aDateTime);
			rExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_CHG_DATE_TIME,
								 sBuf.makeStringAndClear());
		}
		else if( rVal.Name.equals(sRedlineType) )
		{
			// check if this is an insertion; cf. comment at calling location
			OUString sTmp;
			rVal.Value >>= sTmp;
			DBG_ASSERT(sTmp.equals(sInsert),
					   "hierarchical change must be insertion");
		}
		// else: unknown value -> ignore
	}

	// finally write element
	SvXMLElementExport aChangeInfo(rExport, XML_NAMESPACE_OFFICE,
								   XML_CHANGE_INFO, sal_True, sal_True);

    WriteComment( sComment );
}

void XMLRedlineExport::ExportStartOrEndRedline(
	const Reference<XPropertySet> & rPropSet,
	sal_Bool bStart)
{
    if( ! rPropSet.is() )
        return;

	// get appropriate (start or end) property
	Any aAny;
    try
    {
        aAny = rPropSet->getPropertyValue(bStart ? sStartRedline : sEndRedline);
    }
    catch( UnknownPropertyException e )
    {
        // If we don't have the property, there's nothing to do.
        return;
    }

	Sequence<PropertyValue> aValues;
	aAny >>= aValues;
    const PropertyValue* pValues = aValues.getConstArray();

	// seek for redline properties
    sal_Bool bIsCollapsed = sal_False;
    sal_Bool bIsStart = sal_True;
    OUString sId;
    sal_Bool bIdOK = sal_False; // have we seen an ID?
	sal_Int32 nLength = aValues.getLength();
	for(sal_Int32 i = 0; i < nLength; i++)
	{
		if (sRedlineIdentifier.equals(pValues[i].Name))
		{
			pValues[i].Value >>= sId;
            bIdOK = sal_True;
        }
        else if (sIsCollapsed.equals(pValues[i].Name))
        {
            bIsCollapsed = *(sal_Bool*)pValues[i].Value.getValue();
        }
        else if (sIsStart.equals(pValues[i].Name))
        {
            bIsStart = *(sal_Bool*)pValues[i].Value.getValue();
        }
    }

    if( bIdOK )
    {
        DBG_ASSERT( sId.getLength() > 0, "Redlines must have IDs" );

        // TODO: use GetRedlineID or elimiate that function
        OUStringBuffer sBuffer(sChangePrefix);
        sBuffer.append(sId);

        rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_CHANGE_ID,
                             sBuffer.makeStringAndClear());

        // export the element
        // (whitespace because we're not inside paragraphs)
        SvXMLElementExport aChangeElem(
            rExport, XML_NAMESPACE_TEXT,
            bIsCollapsed ? XML_CHANGE :
                ( bIsStart ? XML_CHANGE_START : XML_CHANGE_END ),
            sal_True, sal_True);
    }
}

void XMLRedlineExport::ExportStartOrEndRedline(
	const Reference<XTextContent> & rContent,
	sal_Bool bStart)
{
	Reference<XPropertySet> xPropSet(rContent, uno::UNO_QUERY);
	if (xPropSet.is())
	{
		ExportStartOrEndRedline(xPropSet, bStart);
	}
	else
	{
		DBG_ERROR("XPropertySet expected");
	}
}

void XMLRedlineExport::ExportStartOrEndRedline(
	const Reference<XTextSection> & rSection,
	sal_Bool bStart)
{
	Reference<XPropertySet> xPropSet(rSection, uno::UNO_QUERY);
	if (xPropSet.is())
	{
		ExportStartOrEndRedline(xPropSet, bStart);
	}
	else
	{
		DBG_ERROR("XPropertySet expected");
	}
}

void XMLRedlineExport::WriteComment(const OUString& rComment)
{
	if (rComment.getLength() > 0)
	{
		// iterate over all string-pieces separated by return (0x0a) and
		// put each inside a paragraph element.
		SvXMLTokenEnumerator aEnumerator(rComment, sal_Char(0x0a));
		OUString aSubString;
		while (aEnumerator.getNextToken(aSubString))
		{
			SvXMLElementExport aParagraph(
				rExport, XML_NAMESPACE_TEXT, XML_P, sal_True, sal_False);
			rExport.Characters(aSubString);
		}
	}
}
