/**************************************************************
 *
 * 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_svx.hxx"
#include "EnhancedCustomShapeEngine.hxx"
#include "svx/EnhancedCustomShape2d.hxx"
#include "EnhancedCustomShape3d.hxx"
#include "EnhancedCustomShapeFontWork.hxx"
#include "EnhancedCustomShapeHandle.hxx"
#include "svx/EnhancedCustomShapeGeometry.hxx"
#include <svx/unoshape.hxx>
#ifndef _SVX_UNOPAGE_HXX
#include "svx/unopage.hxx"
#endif
#include "svx/unoapi.hxx"
#include <svx/svdobj.hxx>
#include <svx/svdoashp.hxx>
#include <svx/svdogrp.hxx>
#include <svx/svdorect.hxx>
#include <editeng/outlobj.hxx>
#include <editeng/outliner.hxx>
#include <svx/svdoutl.hxx>
#include <svl/itemset.hxx>
#include <svx/svdopath.hxx>
#include <svx/svdpage.hxx>
#include <svx/svdmodel.hxx>
#include "svx/svditer.hxx"
#include "unopolyhelper.hxx"
#include <uno/mapping.hxx>
#include <basegfx/polygon/b2dpolypolygontools.hxx>
#include <com/sun/star/document/XActionLockable.hpp>

// ---------------------------
// - EnhancedCustomShapeEngine -
// ---------------------------

rtl::OUString EnhancedCustomShapeEngine_getImplementationName()
	throw( NMSP_UNO::RuntimeException )
{
	return B2UCONST( "com.sun.star.drawing.EnhancedCustomShapeEngine" );
}
sal_Bool SAL_CALL EnhancedCustomShapeEngine_supportsService( const rtl::OUString& ServiceName )
	throw( NMSP_UNO::RuntimeException )
{
    return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "com.sun.star.drawing.CustomShapeEngine" ) );
}
SEQ( rtl::OUString ) SAL_CALL EnhancedCustomShapeEngine_getSupportedServiceNames()
	throw( NMSP_UNO::RuntimeException )
{
	SEQ( rtl::OUString ) aRet(1);
    rtl::OUString* pArray = aRet.getArray();
    pArray[0] = B2UCONST( "com.sun.star.drawing.CustomShapeEngine" );
    return aRet;
}

// -----------------------------------------------------------------------------

EnhancedCustomShapeEngine::EnhancedCustomShapeEngine( const REF( NMSP_LANG::XMultiServiceFactory )& rxMgr ) :
	mxFact					( rxMgr ),
	mbForceGroupWithText	( sal_False )
{
}
EnhancedCustomShapeEngine::~EnhancedCustomShapeEngine()
{
}

// XInterface -----------------------------------------------------------------

void SAL_CALL EnhancedCustomShapeEngine::acquire() throw()
{
	OWeakObject::acquire();
}
void SAL_CALL EnhancedCustomShapeEngine::release() throw()
{
	OWeakObject::release();
}

// XInitialization ------------------------------------------------------------

void SAL_CALL EnhancedCustomShapeEngine::initialize( const SEQ( NMSP_UNO::Any )& aArguments )
	throw ( NMSP_UNO::Exception, NMSP_UNO::RuntimeException )
{
	sal_Int32 i;
	SEQ( NMSP_BEANS::PropertyValue ) aParameter;
	for ( i = 0; i < aArguments.getLength(); i++ )
	{
		if ( aArguments[ i ] >>= aParameter )
			break;
	}
	for ( i = 0; i < aParameter.getLength(); i++ )
	{
		const NMSP_BEANS::PropertyValue& rProp = aParameter[ i ];
		if ( rProp.Name.equalsAscii( "CustomShape" ) )
			rProp.Value >>= mxShape;
		else if ( rProp.Name.equalsAscii( "ForceGroupWithText" ) )
			rProp.Value >>= mbForceGroupWithText;
	}
}

// XServiceInfo ---------------------------------------------------------------

rtl::OUString SAL_CALL EnhancedCustomShapeEngine::getImplementationName()
	throw( NMSP_UNO::RuntimeException )
{
	return EnhancedCustomShapeEngine_getImplementationName();
}
sal_Bool SAL_CALL EnhancedCustomShapeEngine::supportsService( const rtl::OUString& rServiceName )
	throw( NMSP_UNO::RuntimeException )
{
    return EnhancedCustomShapeEngine_supportsService( rServiceName );
}
SEQ( rtl::OUString ) SAL_CALL EnhancedCustomShapeEngine::getSupportedServiceNames()
	throw ( NMSP_UNO::RuntimeException )
{
    return EnhancedCustomShapeEngine_getSupportedServiceNames();
}

// XCustomShapeEngine -----------------------------------------------------------

SdrObject* EnhancedCustomShapeEngine::ImplForceGroupWithText( const SdrObjCustomShape* pCustoObj, SdrObject* pRenderedShape )
{
	bool bHasText = pCustoObj->HasText();
	if ( pRenderedShape || bHasText )
	{
		// applying shadow
		const SdrObject* pShadowGeometry = pCustoObj->GetSdrObjectShadowFromCustomShape();
		if ( pShadowGeometry )
		{
			if ( pRenderedShape )
			{
				if ( !pRenderedShape->ISA( SdrObjGroup ) )
				{
					SdrObject* pTmp = pRenderedShape;
					pRenderedShape = new SdrObjGroup();
					((SdrObjGroup*)pRenderedShape)->GetSubList()->NbcInsertObject( pTmp );
				}
				((SdrObjGroup*)pRenderedShape)->GetSubList()->NbcInsertObject( pShadowGeometry->Clone(), 0 );
			}
			else
				pRenderedShape = pShadowGeometry->Clone();
		}

		// apply text
		if ( bHasText )
		{
			// #i37011# also create a text object and add at rPos + 1
			SdrTextObj* pTextObj = (SdrTextObj*)SdrObjFactory::MakeNewObject(
				pCustoObj->GetObjInventor(), OBJ_TEXT, 0L, pCustoObj->GetModel());

			// Copy text content
			OutlinerParaObject* pParaObj = pCustoObj->GetOutlinerParaObject();
			if( pParaObj )
				pTextObj->NbcSetOutlinerParaObject( new OutlinerParaObject(*pParaObj) );

			// copy all attributes
			SfxItemSet aTargetItemSet( pCustoObj->GetMergedItemSet() );

			// clear fill and line style
			aTargetItemSet.Put(XLineStyleItem(XLINE_NONE));
			aTargetItemSet.Put(XFillStyleItem(XFILL_NONE));

			// get the text bounds and set at text object
			Rectangle aTextBounds = pCustoObj->GetSnapRect();
			SdrObject* pSdrObjCustomShape( GetSdrObjectFromXShape( mxShape ) );
			if ( pSdrObjCustomShape )
			{
				EnhancedCustomShape2d aCustomShape2d( pSdrObjCustomShape );
				aTextBounds = aCustomShape2d.GetTextRect();
			}
			pTextObj->SetSnapRect( aTextBounds );

			// if rotated, copy GeoStat, too.
			const GeoStat& rSourceGeo = pCustoObj->GetGeoStat();
			if ( rSourceGeo.nDrehWink )
			{
				pTextObj->NbcRotate(
					pCustoObj->GetSnapRect().Center(), rSourceGeo.nDrehWink,
					rSourceGeo.nSin, rSourceGeo.nCos);
			}

			// set modified ItemSet at text object
			pTextObj->SetMergedItemSet(aTargetItemSet);

			if ( pRenderedShape )
			{
				if ( !pRenderedShape->ISA( SdrObjGroup ) )
				{
					SdrObject* pTmp = pRenderedShape;
					pRenderedShape = new SdrObjGroup();
					((SdrObjGroup*)pRenderedShape)->GetSubList()->NbcInsertObject( pTmp );
				}
				((SdrObjGroup*)pRenderedShape)->GetSubList()->NbcInsertObject( pTextObj, LIST_APPEND );
			}
			else
				pRenderedShape = pTextObj;
		}

		// force group
		if ( pRenderedShape )
		{
			if ( !pRenderedShape->ISA( SdrObjGroup ) )
			{
				SdrObject* pTmp = pRenderedShape;
				pRenderedShape = new SdrObjGroup();
				((SdrObjGroup*)pRenderedShape)->GetSubList()->NbcInsertObject( pTmp );
			}
			pRenderedShape->SetPage( pCustoObj->GetPage() );
			pRenderedShape->SetModel( pCustoObj->GetModel() );
		}
	}
	return pRenderedShape;
}

void SetTemporary( ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& xShape )
{
	if ( xShape.is() )
	{
		SvxShape* pShape = SvxShape::getImplementation( xShape );
		if ( pShape )
			pShape->TakeSdrObjectOwnership();
/*
		::com::sun::star::uno::Reference<
			::com::sun::star::drawing::XShapes > xShapes( xShape, ::com::sun::star::uno::UNO_QUERY );
		if ( xShapes.is() )
		{
			sal_Int32 i;
			for ( i = 0; i < xShapes->getCount(); i++ )
			{
	            ::com::sun::star::uno::Any aAny( xShapes->getByIndex( i ) );
				::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > xShape;
				if ( aAny >>= xShape )
					SetTemporary( xShape );
			}
		}
*/
	}
}

REF( com::sun::star::drawing::XShape ) SAL_CALL EnhancedCustomShapeEngine::render()
	throw ( NMSP_UNO::RuntimeException )
{
	REF( com::sun::star::drawing::XShape ) xShape;
	SdrObject* pSdrObjCustomShape( GetSdrObjectFromXShape( mxShape ) );
	if ( pSdrObjCustomShape )
	{
		// retrieving the TextPath property to check if feature is enabled
		SdrCustomShapeGeometryItem& rGeometryItem = (SdrCustomShapeGeometryItem&)
			pSdrObjCustomShape->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY );
		sal_Bool bTextPathOn = sal_False;
		const rtl::OUString	sTextPath( RTL_CONSTASCII_USTRINGPARAM ( "TextPath" ) );
		com::sun::star::uno::Any* pAny = rGeometryItem.GetPropertyValueByName( sTextPath, sTextPath );
		if ( pAny )
			*pAny >>= bTextPathOn;

		EnhancedCustomShape2d aCustomShape2d( pSdrObjCustomShape );
		sal_Int32 nRotateAngle = aCustomShape2d.GetRotateAngle();

		sal_Bool bFlipV = aCustomShape2d.IsFlipVert();
		sal_Bool bFlipH = aCustomShape2d.IsFlipHorz();
		sal_Bool bLineGeometryNeededOnly = bTextPathOn;

		SdrObject* pRenderedShape = aCustomShape2d.CreateObject( bLineGeometryNeededOnly );
		if ( pRenderedShape )
		{
			if ( bTextPathOn )
			{
				SdrObject* pRenderedFontWork = EnhancedCustomShapeFontWork::CreateFontWork( pRenderedShape, pSdrObjCustomShape );
				if ( pRenderedFontWork )
                {
                    SdrObject::Free( pRenderedShape );
                    pRenderedShape = pRenderedFontWork;
                }
			}
			SdrObject* pRenderedShape3d = EnhancedCustomShape3d::Create3DObject( pRenderedShape, pSdrObjCustomShape );
			if ( pRenderedShape3d )
			{
				bFlipV = bFlipH = sal_False;
				nRotateAngle = 0;
                SdrObject::Free( pRenderedShape );
				pRenderedShape = pRenderedShape3d;
			}
			Rectangle aRect( pSdrObjCustomShape->GetSnapRect() );

			const GeoStat& rGeoStat = ((SdrObjCustomShape*)pSdrObjCustomShape)->GetGeoStat();
			if ( rGeoStat.nShearWink )
			{
				long nShearWink = rGeoStat.nShearWink;
				double nTan = rGeoStat.nTan;
				if ((bFlipV&&!bFlipH )||(bFlipH&&!bFlipV))
				{
					nShearWink = -nShearWink;
					nTan = -nTan;
				}
				pRenderedShape->Shear( pSdrObjCustomShape->GetSnapRect().Center(), nShearWink, nTan, sal_False);
			}
			if( nRotateAngle )
			{
				double a = nRotateAngle * F_PI18000;
				pRenderedShape->NbcRotate( pSdrObjCustomShape->GetSnapRect().Center(), nRotateAngle, sin( a ), cos( a ) );
			}
			if ( bFlipV )
			{
				Point aLeft( aRect.Left(), ( aRect.Top() + aRect.Bottom() ) >> 1 );
				Point aRight( aLeft.X() + 1000, aLeft.Y() );
				pRenderedShape->NbcMirror( aLeft, aRight );
			}
			if ( bFlipH )
			{
				Point aTop( ( aRect.Left() + aRect.Right() ) >> 1, aRect.Top() );
				Point aBottom( aTop.X(), aTop.Y() + 1000 );
				pRenderedShape->NbcMirror( aTop, aBottom );
			}
			pRenderedShape->NbcSetStyleSheet( pSdrObjCustomShape->GetStyleSheet(), sal_True );
			pRenderedShape->RecalcSnapRect();
		}

		if ( mbForceGroupWithText )
			pRenderedShape = ImplForceGroupWithText( (SdrObjCustomShape*)pSdrObjCustomShape, pRenderedShape );

		if ( pRenderedShape )
		{
			aCustomShape2d.ApplyGluePoints( pRenderedShape );
			xShape = SvxDrawPage::CreateShapeByTypeAndInventor( pRenderedShape->GetObjIdentifier(),
				pRenderedShape->GetObjInventor(), pRenderedShape, NULL );
		}
		SetTemporary( xShape );
	}
	return xShape;
}

com::sun::star::awt::Rectangle SAL_CALL EnhancedCustomShapeEngine::getTextBounds()
	throw ( NMSP_UNO::RuntimeException )
{
	com::sun::star::awt::Rectangle aTextRect;
	SdrObject* pSdrObjCustomShape( GetSdrObjectFromXShape( mxShape ) );
	::com::sun::star::uno::Reference< ::com::sun::star::document::XActionLockable > xLockable( mxShape, ::com::sun::star::uno::UNO_QUERY );
	if ( pSdrObjCustomShape && pSdrObjCustomShape->GetModel() && xLockable.is() && !xLockable->isActionLocked() )
	{
		if ( pSdrObjCustomShape )
		{
			EnhancedCustomShape2d aCustomShape2d( pSdrObjCustomShape );
			Rectangle aRect( aCustomShape2d.GetTextRect() );
			aTextRect.X = aRect.Left();
			aTextRect.Y = aRect.Top();
			aTextRect.Width = aRect.GetWidth();
			aTextRect.Height = aRect.GetHeight();
		}
	}
	return aTextRect;
}

com::sun::star::drawing::PolyPolygonBezierCoords SAL_CALL EnhancedCustomShapeEngine::getLineGeometry()
	throw ( NMSP_UNO::RuntimeException )
{
	com::sun::star::drawing::PolyPolygonBezierCoords aPolyPolygonBezierCoords;
	SdrObject* pSdrObjCustomShape( GetSdrObjectFromXShape( mxShape ) );
	if ( pSdrObjCustomShape )
	{
		EnhancedCustomShape2d aCustomShape2d( pSdrObjCustomShape );
		SdrObject* pObj = aCustomShape2d.CreateLineGeometry();
		if ( pObj )
		{
			Rectangle aRect( pSdrObjCustomShape->GetSnapRect() );
			sal_Bool bFlipV = aCustomShape2d.IsFlipVert();
			sal_Bool bFlipH = aCustomShape2d.IsFlipHorz();

			const GeoStat& rGeoStat = ((SdrObjCustomShape*)pSdrObjCustomShape)->GetGeoStat();
			if ( rGeoStat.nShearWink )
			{
				long nShearWink = rGeoStat.nShearWink;
				double nTan = rGeoStat.nTan;
				if ((bFlipV&&!bFlipH )||(bFlipH&&!bFlipV))
				{
					nShearWink = -nShearWink;
					nTan = -nTan;
				}
				pObj->Shear( aRect.Center(), nShearWink, nTan, sal_False);
			}
			sal_Int32 nRotateAngle = aCustomShape2d.GetRotateAngle();
			if( nRotateAngle )
			{
				double a = nRotateAngle * F_PI18000;
				pObj->NbcRotate( aRect.Center(), nRotateAngle, sin( a ), cos( a ) );
			}
			if ( bFlipH )
			{
				Point aTop( ( aRect.Left() + aRect.Right() ) >> 1, aRect.Top() );
				Point aBottom( aTop.X(), aTop.Y() + 1000 );
				pObj->NbcMirror( aTop, aBottom );
			}
			if ( bFlipV )
			{
				Point aLeft( aRect.Left(), ( aRect.Top() + aRect.Bottom() ) >> 1 );
				Point aRight( aLeft.X() + 1000, aLeft.Y() );
				pObj->NbcMirror( aLeft, aRight );
			}

			basegfx::B2DPolyPolygon aPolyPolygon;
			SdrObjListIter aIter( *pObj, IM_DEEPWITHGROUPS );

			while ( aIter.IsMore() )
			{
				SdrObject* pNewObj = NULL;
				basegfx::B2DPolyPolygon aPP;
				const SdrObject* pNext = aIter.Next();

				if ( pNext->ISA( SdrPathObj ) )
				{
					aPP = ((SdrPathObj*)pNext)->GetPathPoly();
				}
				else
				{
					pNewObj = pNext->ConvertToPolyObj( sal_False, sal_False );
					SdrPathObj* pPath = PTR_CAST( SdrPathObj, pNewObj );
					if ( pPath )
						aPP = pPath->GetPathPoly();
				}

				if ( aPP.count() )
					aPolyPolygon.append(aPP);

				SdrObject::Free( pNewObj );
			}
            SdrObject::Free( pObj );
			SvxConvertB2DPolyPolygonToPolyPolygonBezier( aPolyPolygon, aPolyPolygonBezierCoords );
		}
	}

	return aPolyPolygonBezierCoords;
}

SEQ( REF( com::sun::star::drawing::XCustomShapeHandle ) ) SAL_CALL EnhancedCustomShapeEngine::getInteraction()
	throw ( NMSP_UNO::RuntimeException )
{
	sal_uInt32 i, nHdlCount = 0;
	SdrObject* pSdrObjCustomShape = GetSdrObjectFromXShape( mxShape );
	if ( pSdrObjCustomShape )
	{
		EnhancedCustomShape2d aCustomShape2d( pSdrObjCustomShape );
		nHdlCount = aCustomShape2d.GetHdlCount();
	}
	SEQ( REF( com::sun::star::drawing::XCustomShapeHandle ) ) aSeq( nHdlCount );
	for ( i = 0; i < nHdlCount; i++ )
		aSeq[ i ] = new EnhancedCustomShapeHandle( mxShape, i );
	return aSeq;
}
