/**************************************************************
 *
 * 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 "XMLImageMapExport.hxx"
#include <rtl/ustring.hxx>
#include <rtl/ustrbuf.hxx>
#include <tools/debug.hxx>
#include <com/sun/star/uno/Reference.h>
#include <com/sun/star/uno/Sequence.h>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/container/XIndexContainer.hpp>
#include <com/sun/star/document/XEventsSupplier.hpp>
#include <com/sun/star/awt/Rectangle.hpp>
#include <com/sun/star/awt/Point.hpp>
#include <com/sun/star/awt/Size.hpp>
#include <com/sun/star/drawing/PointSequence.hpp>
#include <xmloff/xmlexp.hxx>
#include "xmloff/xmlnmspe.hxx"
#include <xmloff/xmltoken.hxx>
#include <xmloff/XMLEventExport.hxx>
#include <xmloff/xmluconv.hxx>
#include "xexptran.hxx"
#include <basegfx/polygon/b2dpolygon.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>

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

using ::rtl::OUString;
using ::rtl::OUStringBuffer;
using ::com::sun::star::uno::Any;
using ::com::sun::star::uno::UNO_QUERY;
using ::com::sun::star::uno::Sequence;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::beans::XPropertySet;
using ::com::sun::star::container::XIndexContainer;
using ::com::sun::star::document::XEventsSupplier;
using ::com::sun::star::lang::XServiceInfo;
using ::com::sun::star::drawing::PointSequence;


const sal_Char sAPI_ImageMapRectangleObject[] = "com.sun.star.image.ImageMapRectangleObject";
const sal_Char sAPI_ImageMapCircleObject[] = "com.sun.star.image.ImageMapCircleObject";
const sal_Char sAPI_ImageMapPolygonObject[] = "com.sun.star.image.ImageMapPolygonObject";

XMLImageMapExport::XMLImageMapExport(SvXMLExport& rExp) :
	msBoundary(RTL_CONSTASCII_USTRINGPARAM("Boundary")),
	msCenter(RTL_CONSTASCII_USTRINGPARAM("Center")),
	msDescription(RTL_CONSTASCII_USTRINGPARAM("Description")),
	msImageMap(RTL_CONSTASCII_USTRINGPARAM("ImageMap")),
	msIsActive(RTL_CONSTASCII_USTRINGPARAM("IsActive")),
	msName(RTL_CONSTASCII_USTRINGPARAM("Name")),
	msPolygon(RTL_CONSTASCII_USTRINGPARAM("Polygon")),
	msRadius(RTL_CONSTASCII_USTRINGPARAM("Radius")),
	msTarget(RTL_CONSTASCII_USTRINGPARAM("Target")),
	msURL(RTL_CONSTASCII_USTRINGPARAM("URL")),
	msTitle(RTL_CONSTASCII_USTRINGPARAM("Title")),
	mrExport(rExp),
	mbWhiteSpace(sal_True)
{
}

XMLImageMapExport::~XMLImageMapExport()
{

}

void XMLImageMapExport::Export(
	const Reference<XPropertySet> & rPropertySet)
{
	if (rPropertySet->getPropertySetInfo()->hasPropertyByName(msImageMap))
	{
		Any aAny = rPropertySet->getPropertyValue(msImageMap);
		Reference<XIndexContainer> aContainer;
		aAny >>= aContainer;

		Export(aContainer);
	}
	// else: no ImageMap property -> nothing to do
}

void XMLImageMapExport::Export(
	const Reference<XIndexContainer> & rContainer)
{
	if (rContainer.is())
	{
		if (rContainer->hasElements())
		{
			// image map container element
			SvXMLElementExport aImageMapElement(
				mrExport, XML_NAMESPACE_DRAW, XML_IMAGE_MAP,
				mbWhiteSpace, mbWhiteSpace);

			// iterate over image map elements and call ExportMapEntry(...)
			// for each
			sal_Int32 nLength = rContainer->getCount();
			for(sal_Int32 i = 0; i < nLength; i++)
			{
				Any aAny = rContainer->getByIndex(i);
				Reference<XPropertySet> rElement;
				aAny >>= rElement;

				DBG_ASSERT(rElement.is(), "Image map element is empty!");
				if (rElement.is())
				{
					ExportMapEntry(rElement);
				}
			}
		}
		// else: container is empty -> nothing to do
	}
	// else: no container -> nothing to do
}


void XMLImageMapExport::ExportMapEntry(
	const Reference<XPropertySet> & rPropertySet)
{
	Reference<XServiceInfo> xServiceInfo(rPropertySet, UNO_QUERY);
	if (xServiceInfo.is())
	{
		enum XMLTokenEnum eType = XML_TOKEN_INVALID;

		// distinguish map entries by their service name
		Sequence<OUString> sServiceNames =
			xServiceInfo->getSupportedServiceNames();
		sal_Int32 nLength = sServiceNames.getLength();
		for( sal_Int32 i=0; i<nLength; i++ )
		{
			OUString& rName = sServiceNames[i];

			if ( rName.equalsAsciiL(sAPI_ImageMapRectangleObject,
									sizeof(sAPI_ImageMapRectangleObject)-1) )
			{
				eType = XML_AREA_RECTANGLE;
				break;
			}
			else if ( rName.equalsAsciiL(sAPI_ImageMapCircleObject,
										 sizeof(sAPI_ImageMapCircleObject)-1) )
			{
				eType = XML_AREA_CIRCLE;
				break;
			}
			else if ( rName.equalsAsciiL(sAPI_ImageMapPolygonObject,
										 sizeof(sAPI_ImageMapPolygonObject)-1))
			{
				eType = XML_AREA_POLYGON;
				break;
			}
		}

		// return from method if no proper service is found!
		DBG_ASSERT(XML_TOKEN_INVALID != eType,
				   "Image map element doesn't support appropriate service!");
		if (XML_TOKEN_INVALID == eType)
			return;

		// now: handle ImageMapObject properties (those for all types)

		// XLINK (URL property)
		Any aAny = rPropertySet->getPropertyValue(msURL);
		OUString sHref;
		aAny >>= sHref;
		if (sHref.getLength() > 0)
		{
			mrExport.AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, mrExport.GetRelativeReference(sHref));
		}
		mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );

		// Target property (and xlink:show)
		aAny = rPropertySet->getPropertyValue(msTarget);
		OUString sTargt;
		aAny >>= sTargt;
		if (sTargt.getLength() > 0)
		{
			mrExport.AddAttribute(
				XML_NAMESPACE_OFFICE, XML_TARGET_FRAME_NAME, sTargt);

			mrExport.AddAttribute(
				XML_NAMESPACE_XLINK, XML_SHOW,
				sTargt.equalsAsciiL( "_blank", sizeof("_blank")-1 )
										? XML_NEW : XML_REPLACE );
		}

		// name
		aAny = rPropertySet->getPropertyValue(msName);
		OUString sItemName;
		aAny >>= sItemName;
		if (sItemName.getLength() > 0)
		{
			mrExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_NAME, sItemName);
		}

		// is-active
		aAny = rPropertySet->getPropertyValue(msIsActive);
		if (! *(sal_Bool*)aAny.getValue())
		{
			mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_NOHREF, XML_NOHREF);
		}

		// call specific rectangle/circle/... method
		// also prepare element name
		switch (eType)
		{
			case XML_AREA_RECTANGLE:
				ExportRectangle(rPropertySet);
				break;
			case XML_AREA_CIRCLE:
				ExportCircle(rPropertySet);
				break;
			case XML_AREA_POLYGON:
				ExportPolygon(rPropertySet);
				break;
			default:
				break;
		}

		// write element
		DBG_ASSERT(XML_TOKEN_INVALID != eType,
                   "No name?! How did this happen?");
		SvXMLElementExport aAreaElement(mrExport, XML_NAMESPACE_DRAW, eType,
										mbWhiteSpace, mbWhiteSpace);

		// title property (as <svg:title> element)
		OUString sTitle;
		rPropertySet->getPropertyValue(msTitle) >>= sTitle;
		if(sTitle.getLength())
		{
			SvXMLElementExport aEventElemt(mrExport, XML_NAMESPACE_SVG, XML_TITLE, mbWhiteSpace, sal_False);
			mrExport.Characters(sTitle);
		}

		// description property (as <svg:desc> element)
		OUString sDescription;
		rPropertySet->getPropertyValue(msDescription) >>= sDescription;
		if (sDescription.getLength() > 0)
		{
			SvXMLElementExport aDesc(mrExport, XML_NAMESPACE_SVG, XML_DESC, mbWhiteSpace, sal_False);
			mrExport.Characters(sDescription);
		}

		// export events attached to this
		Reference<XEventsSupplier> xSupplier(rPropertySet, UNO_QUERY);
		mrExport.GetEventExport().Export(xSupplier, mbWhiteSpace);
	}
	// else: no service info -> can't determine type -> ignore entry
}

void XMLImageMapExport::ExportRectangle(
	const Reference<XPropertySet> & rPropertySet)
{
	// get boundary rectangle
	Any aAny = rPropertySet->getPropertyValue(msBoundary);
	awt::Rectangle aRectangle;
	aAny >>= aRectangle;

	// parameters svg:x, svg:y, svg:width, svg:height
	OUStringBuffer aBuffer;
	mrExport.GetMM100UnitConverter().convertMeasure(aBuffer, aRectangle.X);
	mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_X,
						  aBuffer.makeStringAndClear() );
	mrExport.GetMM100UnitConverter().convertMeasure(aBuffer, aRectangle.Y);
	mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_Y,
						  aBuffer.makeStringAndClear() );
	mrExport.GetMM100UnitConverter().convertMeasure(aBuffer, aRectangle.Width);
	mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_WIDTH,
						  aBuffer.makeStringAndClear() );
	mrExport.GetMM100UnitConverter().convertMeasure(aBuffer, aRectangle.Height);
	mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_HEIGHT,
						  aBuffer.makeStringAndClear() );
}

void XMLImageMapExport::ExportCircle(
	const Reference<XPropertySet> & rPropertySet)
{
	// get boundary rectangle
	Any aAny = rPropertySet->getPropertyValue(msCenter);
	awt::Point aCenter;
	aAny >>= aCenter;

	// parameters svg:cx, svg:cy
	OUStringBuffer aBuffer;
	mrExport.GetMM100UnitConverter().convertMeasure(aBuffer, aCenter.X);
	mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_CX,
						  aBuffer.makeStringAndClear() );
	mrExport.GetMM100UnitConverter().convertMeasure(aBuffer, aCenter.Y);
	mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_CY,
						  aBuffer.makeStringAndClear() );

	// radius
	aAny = rPropertySet->getPropertyValue(msRadius);
	sal_Int32 nRadius = 0;
	aAny >>= nRadius;
	mrExport.GetMM100UnitConverter().convertMeasure(aBuffer, nRadius);
	mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_R,
						  aBuffer.makeStringAndClear() );
}

void XMLImageMapExport::ExportPolygon(const Reference<XPropertySet> & rPropertySet)
{
    // polygons get exported as bounding box, viewbox, and coordinate
    // pair sequence. The bounding box is always the entire image.

    // get polygon point sequence
    Any aAny = rPropertySet->getPropertyValue(msPolygon);
    PointSequence aPoly;
    aAny >>= aPoly;

    const basegfx::B2DPolygon aPolygon(
        basegfx::tools::UnoPointSequenceToB2DPolygon(
            aPoly));
    const basegfx::B2DRange aPolygonRange(aPolygon.getB2DRange());

    // parameters svg:x, svg:y, svg:width, svg:height
    OUStringBuffer aBuffer;

    mrExport.GetMM100UnitConverter().convertMeasure(aBuffer, 0);
    mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_X, aBuffer.makeStringAndClear() );
    mrExport.GetMM100UnitConverter().convertMeasure(aBuffer, 0);
    mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_Y, aBuffer.makeStringAndClear() );
    mrExport.GetMM100UnitConverter().convertMeasure(aBuffer, basegfx::fround(aPolygonRange.getWidth()));
    mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_WIDTH, aBuffer.makeStringAndClear() );
    mrExport.GetMM100UnitConverter().convertMeasure(aBuffer, basegfx::fround(aPolygonRange.getHeight()));
    mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_HEIGHT, aBuffer.makeStringAndClear() );

    // svg:viewbox
    SdXMLImExViewBox aViewBox(0.0, 0.0, aPolygonRange.getWidth(), aPolygonRange.getHeight());
    mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_VIEWBOX, aViewBox.GetExportString());

    // export point sequence
    const ::rtl::OUString aPointString(
        basegfx::tools::exportToSvgPoints(
            aPolygon));

    mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_POINTS, aPointString);
}

// eof
