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

#include <com/sun/star/uno/Any.hxx>
#include <com/sun/star/uno/Reference.hxx>
#include <comphelper/accessiblekeybindinghelper.hxx>

#include "AccessibleHyperlink.hxx"
#include "editeng/unoedprx.hxx"
#include <editeng/flditem.hxx>
#include <vcl/keycodes.hxx>

using namespace ::com::sun::star;


//------------------------------------------------------------------------
//
// AccessibleHyperlink implementation
//
//------------------------------------------------------------------------

namespace accessibility
{

    AccessibleHyperlink::AccessibleHyperlink( SvxAccessibleTextAdapter& r, SvxFieldItem* p, sal_uInt16 nP, sal_uInt16 nR, sal_Int32 nStt, sal_Int32 nEnd, const ::rtl::OUString& rD ) 
    : rTA( r )
    { 
        pFld = p; 
        nPara = nP; 
        nRealIdx = nR; 
        nStartIdx = nStt; 
        nEndIdx = nEnd; 
        aDescription = rD;
    }
    
    AccessibleHyperlink::~AccessibleHyperlink()
    {
        delete pFld;
    }

    // XAccessibleAction
    sal_Int32 SAL_CALL AccessibleHyperlink::getAccessibleActionCount() throw (uno::RuntimeException)
    {
    	 return isValid() ? 1 : 0;
    }
    
    sal_Bool SAL_CALL AccessibleHyperlink::doAccessibleAction( sal_Int32 nIndex  ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
    {
    	sal_Bool bRet = sal_False;
    	if ( isValid() && ( nIndex == 0 ) )
    	{
    	    rTA.FieldClicked( *pFld, nPara, nRealIdx );
    	    bRet = sal_True;
    	}
    	return bRet;
    }
    
    ::rtl::OUString  SAL_CALL AccessibleHyperlink::getAccessibleActionDescription( sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
    {
    	::rtl::OUString aDesc;

    	if ( isValid() && ( nIndex == 0 ) )
    	    aDesc = aDescription;
    
    	return aDesc;
    }
    
    uno::Reference< ::com::sun::star::accessibility::XAccessibleKeyBinding > SAL_CALL AccessibleHyperlink::getAccessibleActionKeyBinding( sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
    {
    	uno::Reference< ::com::sun::star::accessibility::XAccessibleKeyBinding > xKeyBinding;
    
    	if( isValid() && ( nIndex == 0 ) )
    	{
    		::comphelper::OAccessibleKeyBindingHelper* pKeyBindingHelper = new ::comphelper::OAccessibleKeyBindingHelper();
    		xKeyBinding = pKeyBindingHelper;
    
            awt::KeyStroke aKeyStroke;
    		aKeyStroke.Modifiers = 0;
    		aKeyStroke.KeyCode = KEY_RETURN;
    		aKeyStroke.KeyChar = 0;
    		aKeyStroke.KeyFunc = 0;
    		pKeyBindingHelper->AddKeyBinding( aKeyStroke );
    	}
    
    	return xKeyBinding;
    }

    // XAccessibleHyperlink
    uno::Any SAL_CALL AccessibleHyperlink::getAccessibleActionAnchor( sal_Int32 /*nIndex*/ ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
    {
    	return uno::Any();
    }
    
    uno::Any SAL_CALL AccessibleHyperlink::getAccessibleActionObject( sal_Int32 /*nIndex*/ ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
    {
    	return uno::Any();
    }
    
    sal_Int32 SAL_CALL AccessibleHyperlink::getStartIndex() throw (uno::RuntimeException)
    {
    	return nStartIdx;
    }
    
    sal_Int32 SAL_CALL AccessibleHyperlink::getEndIndex() throw (uno::RuntimeException)
    {
    	return nEndIdx;
    }
    
    sal_Bool SAL_CALL AccessibleHyperlink::isValid(  ) throw (uno::RuntimeException)
    {
    	return rTA.IsValid();
    }

}  // end of namespace accessibility

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

// MT IA2: Accessiblehyperlink.hxx from IA2 CWS - meanwhile we also introduced one in DEV300 (above)
// Keeping this for reference - we probably should get support for image maps in our implementation...


/*

class SVX_DLLPUBLIC SvxAccessibleHyperlink : 
		public ::cppu::WeakImplHelper1<
		::com::sun::star::accessibility::XAccessibleHyperlink >
{
	SvxURLField* mpField;
	sal_Int32 nStartIdx;
	sal_Int32 nEndIdx;

	ImageMap* mpImageMap;
	SdrObject* m_pShape;
	::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >  shapeParent;

public:

	SvxAccessibleHyperlink(){};
	//SvxAccessibleHyperlink(::rtl::OUString name, const Imagemap* pImageMap);
	SvxAccessibleHyperlink(const SvxURLField* p, sal_Int32 nStt, sal_Int32 nEnd);
	SvxAccessibleHyperlink(SdrObject* p, ::accessibility::AccessibleShape* pAcc);
	virtual ~SvxAccessibleHyperlink();
	//void setImageMap(ImageMap* pMap);
	//void setXAccessibleImage(::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > parent);
	::rtl::OUString GetHyperlinkURL(sal_Int32 nIndex) throw (::com::sun::star::lang::IndexOutOfBoundsException);
	sal_Bool IsValidHyperlink();

	// XAccessibleAction
    virtual sal_Int32 SAL_CALL getAccessibleActionCount() 
		throw (::com::sun::star::uno::RuntimeException);
    virtual sal_Bool SAL_CALL doAccessibleAction( sal_Int32 nIndex ) 
		throw (::com::sun::star::lang::IndexOutOfBoundsException, 
				::com::sun::star::uno::RuntimeException);
    virtual ::rtl::OUString SAL_CALL getAccessibleActionDescription( 
				sal_Int32 nIndex ) 
		throw (::com::sun::star::lang::IndexOutOfBoundsException,
				::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::uno::Reference< 
			::com::sun::star::accessibility::XAccessibleKeyBinding > SAL_CALL
		   	getAccessibleActionKeyBinding( sal_Int32 nIndex ) 
		throw (::com::sun::star::lang::IndexOutOfBoundsException, 
				::com::sun::star::uno::RuntimeException);

	// XAccessibleHyperlink
    virtual ::com::sun::star::uno::Any SAL_CALL getAccessibleActionAnchor( 
				sal_Int32 nIndex ) 
		throw (::com::sun::star::lang::IndexOutOfBoundsException, 
				::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::uno::Any SAL_CALL getAccessibleActionObject( 
			sal_Int32 nIndex ) 
		throw (::com::sun::star::lang::IndexOutOfBoundsException, 
				::com::sun::star::uno::RuntimeException);
    virtual sal_Int32 SAL_CALL getStartIndex() 
		throw (::com::sun::star::uno::RuntimeException);
    virtual sal_Int32 SAL_CALL getEndIndex() 
		throw (::com::sun::star::uno::RuntimeException);
    virtual sal_Bool SAL_CALL isValid(  ) 
		throw (::com::sun::star::uno::RuntimeException);
};


SvxAccessibleHyperlink::SvxAccessibleHyperlink( const SvxURLField *p,
										  sal_Int32 nStt, sal_Int32 nEnd ) :
	nStartIdx( nStt ),
	nEndIdx( nEnd ),
	m_pShape(NULL),
	shapeParent(NULL)
{
	if(p)
		mpField = (SvxURLField*)p->Clone();
	else
		mpField = NULL;
}
	
SvxAccessibleHyperlink::SvxAccessibleHyperlink(SdrObject* p, 
											::accessibility::AccessibleShape* pAcc) :
	nStartIdx( -1 ),
	nEndIdx( -1 ),
	mpField(NULL),
	m_pShape(p)
{
	mpImageMap = m_pShape->GetModel()->GetImageMapForObject(m_pShape);
	shapeParent = dynamic_cast< XAccessible* >(pAcc);
}

SvxAccessibleHyperlink::~SvxAccessibleHyperlink()
{
	if(mpField)
		delete mpField;
}

::rtl::OUString SvxAccessibleHyperlink::GetHyperlinkURL(sal_Int32 nIndex) throw (::com::sun::star::lang::IndexOutOfBoundsException)
{
	if( mpField )
	{
		if (nIndex != 0)
	        throw ::com::sun::star::lang::IndexOutOfBoundsException();
		return ::rtl::OUString( mpField->GetURL() );
	}
	else if (mpImageMap)
	{
		if (nIndex < 0 || nIndex >=mpImageMap->GetIMapObjectCount())
			throw IndexOutOfBoundsException();
		
		IMapObject* pMapObj = mpImageMap->GetIMapObject(sal_uInt16(nIndex));
		if (pMapObj->GetURL().Len())
			return ::rtl::OUString( pMapObj->GetURL() );
	}
	else
	{
		if (nIndex != 0)
	        throw ::com::sun::star::lang::IndexOutOfBoundsException();
		
		SdrUnoObj* pUnoCtrl = dynamic_cast< SdrUnoObj* >( m_pShape );
	
		if(pUnoCtrl) 
		{
			try
			{
				uno::Reference< awt::XControlModel > xControlModel( pUnoCtrl->GetUnoControlModel(), uno::UNO_QUERY_THROW );
				uno::Reference< beans::XPropertySet > xPropSet( xControlModel, uno::UNO_QUERY_THROW );
				uno::Reference< beans::XPropertySetInfo > xPropInfo( xPropSet->getPropertySetInfo(), uno::UNO_QUERY_THROW );
		
				form::FormButtonType eButtonType = form::FormButtonType_URL;
				const ::rtl::OUString sButtonType( RTL_CONSTASCII_USTRINGPARAM( "ButtonType" ) );
				if(xPropInfo->hasPropertyByName( sButtonType ) && (xPropSet->getPropertyValue( sButtonType ) >>= eButtonType ) )
				{
					::rtl::OUString aString;

					// URL
					const ::rtl::OUString sTargetURL(RTL_CONSTASCII_USTRINGPARAM( "TargetURL" ));
					if(xPropInfo->hasPropertyByName(sTargetURL))
					{
						if( xPropSet->getPropertyValue(sTargetURL) >>= aString )
							return aString;
					}
				}
			}
			catch( uno::Exception& )
			{
			}
		}
		// If hyperlink can't be got from sdrobject, query the corresponding document to retrieve the link info
		uno::Reference< XAccessibleGroupPosition > xGroupPosition (shapeParent, uno::UNO_QUERY);
		if (xGroupPosition.is())
			return xGroupPosition->getObjectLink( uno::makeAny( shapeParent ) );
	}
	return ::rtl::OUString();
}

// Just check whether the first hyperlink is valid
sal_Bool SvxAccessibleHyperlink::IsValidHyperlink()
{
	::rtl::OUString url = GetHyperlinkURL(0);
	if (url.getLength() > 0)
		return sal_True;
	else
		return sal_False;
}
// XAccessibleAction
sal_Int32 SAL_CALL SvxAccessibleHyperlink::getAccessibleActionCount() 
		throw (RuntimeException)
{
	if (mpImageMap)
		return mpImageMap->GetIMapObjectCount();
	else
		return 1;	// only shape link or url field
		
	//return mpField ? 1 : (mpImageMap ? mpImageMap->GetIMapObjectCount() : 0);
}

sal_Bool SAL_CALL SvxAccessibleHyperlink::doAccessibleAction( sal_Int32 nIndex ) 
		throw (IndexOutOfBoundsException, RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());

	sal_Bool bRet = sal_False;

	OUString url = GetHyperlinkURL(nIndex);
	
	if( url.getLength() > 0 ) 
	{
		SfxStringItem aStrItem(SID_FILE_NAME, url);
		const SfxObjectShell* pDocSh = SfxObjectShell::Current();
		if( pDocSh )
		{
			SfxMedium* pSfxMedium = pDocSh->GetMedium();
			if( pSfxMedium)
			{
				SfxStringItem aReferer(SID_REFERER, pSfxMedium->GetName());
				SfxBoolItem aBrowseItem( SID_BROWSE, TRUE );
				SfxViewFrame* pFrame = SfxViewFrame::Current();
				if( pFrame )
				{
					pFrame->GetDispatcher()->Execute(SID_OPENDOC, SFX_CALLMODE_ASYNCHRON | SFX_CALLMODE_RECORD,
						    	&aStrItem, &aBrowseItem, &aReferer, 0L);
					bRet = sal_True;
				}
			}
		}
	}

	return bRet;
}
		
OUString SAL_CALL SvxAccessibleHyperlink::getAccessibleActionDescription(
		sal_Int32 nIndex ) 
		throw (IndexOutOfBoundsException, RuntimeException)
{
	return GetHyperlinkURL(nIndex);
}

::com::sun::star::uno::Reference< XAccessibleKeyBinding > SAL_CALL
	SvxAccessibleHyperlink::getAccessibleActionKeyBinding( sal_Int32 ) 
	throw (IndexOutOfBoundsException, RuntimeException)
{
	::com::sun::star::uno::Reference< XAccessibleKeyBinding > xKeyBinding;

	if( mpField || m_pShape)
	{
		::comphelper::OAccessibleKeyBindingHelper* pKeyBindingHelper =
		   	new ::comphelper::OAccessibleKeyBindingHelper();
		xKeyBinding = pKeyBindingHelper;

		::com::sun::star::awt::KeyStroke aKeyStroke;
		aKeyStroke.Modifiers = 0;
		aKeyStroke.KeyCode = KEY_RETURN;
		aKeyStroke.KeyChar = 0;
		aKeyStroke.KeyFunc = 0;
		pKeyBindingHelper->AddKeyBinding( aKeyStroke );
	}

	return xKeyBinding;
}

// XAccessibleHyperlink
Any SAL_CALL SvxAccessibleHyperlink::getAccessibleActionAnchor(
		sal_Int32 nIndex ) 
		throw (IndexOutOfBoundsException, RuntimeException)
{
	Any aRet;

	::rtl::OUString retText;
	if(mpField && nIndex == 0)
	{
		retText = mpField->GetRepresentation();		
		aRet <<= retText;
		return aRet;
	}
	else if(mpImageMap)
	{
		IMapObject* pMapObj = mpImageMap->GetIMapObject(sal_uInt16(nIndex));
		if(pMapObj && pMapObj->GetURL().Len())
			aRet <<= shapeParent;
			return aRet;
	}
	else if (nIndex == 0)
	{
		aRet <<= shapeParent;
		return aRet;
	}
	return aRet;
}

Any SAL_CALL SvxAccessibleHyperlink::getAccessibleActionObject( 
			sal_Int32 nIndex ) 
	throw (IndexOutOfBoundsException, RuntimeException)
{
	::rtl::OUString retText = GetHyperlinkURL(nIndex);
	Any aRet;
	aRet <<= retText;
	return aRet;
}

sal_Int32 SAL_CALL SvxAccessibleHyperlink::getStartIndex() 
		throw (RuntimeException)
{
	return nStartIdx;
}

sal_Int32 SAL_CALL SvxAccessibleHyperlink::getEndIndex() 
		throw (RuntimeException)
{
	return nEndIdx;
}

sal_Bool SAL_CALL SvxAccessibleHyperlink::isValid(  ) 
		throw (RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());
	//return mpField ? sal_True: ( mpImageMap ? sal_True : sal_False );
	if (mpField || m_pShape)
		return sal_True;
	else 
		return sal_False;
}

*/



