/**************************************************************
 * 
 * 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 <editeng/AccessibleContextBase.hxx>

#include <com/sun/star/accessibility/AccessibleRole.hpp>
#include <com/sun/star/beans/PropertyChangeEvent.hpp>
#include <com/sun/star/accessibility/XAccessibleEventListener.hpp>
#include <com/sun/star/accessibility/AccessibleStateType.hpp>
#include <com/sun/star/accessibility/AccessibleRelationType.hpp>

#include <unotools/accessiblestatesethelper.hxx>
#include <unotools/accessiblerelationsethelper.hxx>
#include <comphelper/accessibleeventnotifier.hxx>
#include <rtl/uuid.h>
#include <vos/mutex.hxx>
//#include <vcl/svapp.hxx>

#include <utility>

using namespace	::rtl;
using namespace	::com::sun::star;
using namespace	::com::sun::star::accessibility;
using ::com::sun::star::uno::Reference;

namespace accessibility {

//=====  internal  ============================================================

// Define a shortcut for the somewhot longish base class name.
typedef ::cppu::WeakComponentImplHelper4<
    ::com::sun::star::accessibility::XAccessible,
    ::com::sun::star::accessibility::XAccessibleContext,
    ::com::sun::star::accessibility::XAccessibleEventBroadcaster,
    ::com::sun::star::lang::XServiceInfo> BaseClass;

AccessibleContextBase::AccessibleContextBase (
        const uno::Reference<XAccessible>& rxParent,
		const sal_Int16 aRole)
	:   BaseClass (MutexOwner::maMutex),
        mxStateSet (NULL),
        mxRelationSet (NULL),
        mxParent(rxParent),
        msDescription(),
        meDescriptionOrigin(NotSet),
        msName(),
        meNameOrigin(NotSet),
        mnClientId(0),
        maRole(aRole)
{
    // Create the state set.
    ::utl::AccessibleStateSetHelper* pStateSet  = new ::utl::AccessibleStateSetHelper ();
    mxStateSet = pStateSet;

    // Set some states.  Don't use the SetState method because no events
    // shall be broadcastet (that is not yet initialized anyway).
    if (pStateSet != NULL)
    {
        pStateSet->AddState (AccessibleStateType::ENABLED);
        pStateSet->AddState (AccessibleStateType::SENSITIVE);
        pStateSet->AddState (AccessibleStateType::SHOWING);
        pStateSet->AddState (AccessibleStateType::VISIBLE);
        pStateSet->AddState (AccessibleStateType::FOCUSABLE);
        pStateSet->AddState (AccessibleStateType::SELECTABLE);
    }

    // Create the relation set.
    ::utl::AccessibleRelationSetHelper* pRelationSet = new ::utl::AccessibleRelationSetHelper ();
    mxRelationSet = pRelationSet;
}




AccessibleContextBase::~AccessibleContextBase(void)
{
}




sal_Bool AccessibleContextBase::SetState (sal_Int16 aState)
{
    ::osl::ClearableMutexGuard aGuard (maMutex);
    ::utl::AccessibleStateSetHelper* pStateSet =
        static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get());
    if ((pStateSet != NULL) && !pStateSet->contains(aState))
    {
        pStateSet->AddState (aState);
        // Clear the mutex guard so that it is not locked during calls to
        // listeners.
        aGuard.clear();

        // Send event for all states except the DEFUNC state.
        if (aState != AccessibleStateType::DEFUNC)
        {
            uno::Any aNewValue;
            aNewValue <<= aState;
            CommitChange(
                AccessibleEventId::STATE_CHANGED,
                aNewValue,
                uno::Any());
        }
        return sal_True;
    }
    else
        return sal_False;
}




sal_Bool AccessibleContextBase::ResetState (sal_Int16 aState)
{
    ::osl::ClearableMutexGuard aGuard (maMutex);
    ::utl::AccessibleStateSetHelper* pStateSet =
        static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get());
    if ((pStateSet != NULL) && pStateSet->contains(aState))
    {
        pStateSet->RemoveState (aState);
        // Clear the mutex guard so that it is not locked during calls to listeners.
        aGuard.clear();

        uno::Any aOldValue;
        aOldValue <<= aState;
        CommitChange(
            AccessibleEventId::STATE_CHANGED,
            uno::Any(),
            aOldValue);
        return sal_True;
    }
    else
        return sal_False;
}




sal_Bool AccessibleContextBase::GetState (sal_Int16 aState)
{
    ::osl::MutexGuard aGuard (maMutex);
    ::utl::AccessibleStateSetHelper* pStateSet =
        static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get());
    if (pStateSet != NULL)
        return pStateSet->contains(aState);
    else
        // If there is no state set then return false as a default value.
        return sal_False;
}




void AccessibleContextBase::SetRelationSet (
    const uno::Reference<XAccessibleRelationSet>& rxNewRelationSet)
    throw (::com::sun::star::uno::RuntimeException)
{
    OSL_TRACE ("setting relation set");

    // Try to emit some meaningfull events indicating differing relations in
    // both sets.
    typedef std::pair<short int,short int> RD;
    const RD aRelationDescriptors[] = {
        RD(AccessibleRelationType::CONTROLLED_BY, AccessibleEventId::CONTROLLED_BY_RELATION_CHANGED),
        RD(AccessibleRelationType::CONTROLLER_FOR, AccessibleEventId::CONTROLLER_FOR_RELATION_CHANGED),
        RD(AccessibleRelationType::LABELED_BY, AccessibleEventId::LABELED_BY_RELATION_CHANGED),
        RD(AccessibleRelationType::LABEL_FOR, AccessibleEventId::LABEL_FOR_RELATION_CHANGED),
        RD(AccessibleRelationType::MEMBER_OF, AccessibleEventId::MEMBER_OF_RELATION_CHANGED),
        RD(AccessibleRelationType::INVALID, -1),
    };
    for (int i=0; aRelationDescriptors[i].first!=AccessibleRelationType::INVALID; i++)
        if (mxRelationSet->containsRelation(aRelationDescriptors[i].first)
        != rxNewRelationSet->containsRelation(aRelationDescriptors[i].first))
        CommitChange (aRelationDescriptors[i].second, uno::Any(), uno::Any());

    mxRelationSet = rxNewRelationSet;
}




//=====  XAccessible  =========================================================

uno::Reference< XAccessibleContext> SAL_CALL
    AccessibleContextBase::getAccessibleContext (void)
    throw (uno::RuntimeException)
{
    ThrowIfDisposed ();
	return this;
}




//=====  XAccessibleContext  ==================================================

/** No children.
*/
sal_Int32 SAL_CALL
   	AccessibleContextBase::getAccessibleChildCount (void)
    throw (uno::RuntimeException)
{
    ThrowIfDisposed ();
    return 0;
}




/** Forward the request to the shape.  Return the requested shape or throw
    an exception for a wrong index.
*/
uno::Reference<XAccessible> SAL_CALL
    AccessibleContextBase::getAccessibleChild (sal_Int32 nIndex)
    throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException)
{
    ThrowIfDisposed ();
    throw lang::IndexOutOfBoundsException (
        ::rtl::OUString::createFromAscii ("no child with index " + nIndex),
		NULL);
}




uno::Reference<XAccessible> SAL_CALL
   	AccessibleContextBase::getAccessibleParent (void)
    throw (::com::sun::star::uno::RuntimeException)
{
    ThrowIfDisposed ();
	return mxParent;
}




sal_Int32 SAL_CALL
   	AccessibleContextBase::getAccessibleIndexInParent (void)
    throw (::com::sun::star::uno::RuntimeException)
{
    ThrowIfDisposed ();
	//	Use a simple but slow solution for now.  Optimize later.

    //	Iterate over all the parent's children and search for this object.
    if (mxParent.is())
    {
    	uno::Reference<XAccessibleContext> xParentContext (
        	mxParent->getAccessibleContext());
        if (xParentContext.is())
        {
        	sal_Int32 nChildCount = xParentContext->getAccessibleChildCount();
            for (sal_Int32 i=0; i<nChildCount; i++)
            {
            	uno::Reference<XAccessible> xChild (xParentContext->getAccessibleChild (i));
                if (xChild.is())
                {
                	uno::Reference<XAccessibleContext> xChildContext = xChild->getAccessibleContext();
	            	if (xChildContext == (XAccessibleContext*)this)
                    	return i;
                }
            }
        }
   }

   //	Return -1 to indicate that this object's parent does not know about the
   //	object.
   return -1;
}




sal_Int16 SAL_CALL
	AccessibleContextBase::getAccessibleRole (void)
    throw (::com::sun::star::uno::RuntimeException)
{
    ThrowIfDisposed ();
	return maRole;
}




::rtl::OUString SAL_CALL
   	AccessibleContextBase::getAccessibleDescription (void)
    throw (::com::sun::star::uno::RuntimeException)
{
    ThrowIfDisposed ();
        
    return msDescription;
}




OUString SAL_CALL
   	AccessibleContextBase::getAccessibleName (void)
    throw (::com::sun::star::uno::RuntimeException)
{
    ThrowIfDisposed ();

    if (meNameOrigin == NotSet)
    {
        // Do not send an event because this is the first time it has been
        // requested.
        msName = CreateAccessibleName();
        meNameOrigin = AutomaticallyCreated;
    }
    
    return msName;
}




/**	Return a copy of the relation set.
*/
uno::Reference<XAccessibleRelationSet> SAL_CALL
   	AccessibleContextBase::getAccessibleRelationSet (void)
    throw (::com::sun::star::uno::RuntimeException)
{
    ThrowIfDisposed ();

    // Create a copy of the relation set and return it.
    ::utl::AccessibleRelationSetHelper* pRelationSet =
        static_cast< ::utl::AccessibleRelationSetHelper*>(mxRelationSet.get());
    if (pRelationSet != NULL)
    {
        return uno::Reference<XAccessibleRelationSet> (
            new ::utl::AccessibleRelationSetHelper (*pRelationSet));
    }
    else
        return uno::Reference<XAccessibleRelationSet>(NULL);
}




/**	Return a copy of the state set.
    Possible states are:
		ENABLED
		SHOWING
		VISIBLE
*/
uno::Reference<XAccessibleStateSet> SAL_CALL
    AccessibleContextBase::getAccessibleStateSet (void)
    throw (::com::sun::star::uno::RuntimeException)
{
    ::utl::AccessibleStateSetHelper* pStateSet = NULL;

	if (rBHelper.bDisposed)
    {
        // We are already disposed!
        // Create a new state set that has only set the DEFUNC state.
        pStateSet = new ::utl::AccessibleStateSetHelper ();
        if (pStateSet != NULL)
            pStateSet->AddState (AccessibleStateType::DEFUNC);
    }
    else
    {
        // Create a copy of the state set and return it.
        pStateSet = static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get());

        // Merge current focused state from edit engine.
#if 0
        if (aState == AccessibleStateType::FOCUSED
            && pStateSet != NULL
            && mpText != NULL)
        {
            if (mpText->GetFocusedState ())
                pStateSet->AddState (aState);
            else
                pStateSet->RemoveState (aState);
        }
#endif
        if (pStateSet != NULL)
            pStateSet = new ::utl::AccessibleStateSetHelper (*pStateSet);
    }

    return uno::Reference<XAccessibleStateSet>(pStateSet);
}




lang::Locale SAL_CALL
   	AccessibleContextBase::getLocale (void)
	throw (IllegalAccessibleComponentStateException,
        ::com::sun::star::uno::RuntimeException)
{
    ThrowIfDisposed ();
    // Delegate request to parent.
	if (mxParent.is())
    {
    	uno::Reference<XAccessibleContext> xParentContext (
        	mxParent->getAccessibleContext());
        if (xParentContext.is())
	    	return xParentContext->getLocale ();
    }

    //	No locale and no parent.  Therefore throw exception to indicate this
    //	cluelessness.
    throw IllegalAccessibleComponentStateException ();
}




//=====  XAccessibleEventListener  ============================================

void SAL_CALL
    AccessibleContextBase::addEventListener (
        const uno::Reference<XAccessibleEventListener >& rxListener)
    throw (uno::RuntimeException)
{
	if (rxListener.is())
    {
	    if (rBHelper.bDisposed || rBHelper.bInDispose)
	    {
            uno::Reference<uno::XInterface> x ((lang::XComponent *)this, uno::UNO_QUERY);
		    rxListener->disposing (lang::EventObject (x));
	    }
	    else
	    {
		    if (!mnClientId)
                mnClientId = comphelper::AccessibleEventNotifier::registerClient( );
		    comphelper::AccessibleEventNotifier::addEventListener( mnClientId, rxListener );
	    }
    }
}




void SAL_CALL
    AccessibleContextBase::removeEventListener (
        const uno::Reference<XAccessibleEventListener >& rxListener )
    throw (uno::RuntimeException)
{
    ThrowIfDisposed ();
	if (rxListener.is())
	{
        sal_Int32 nListenerCount = comphelper::AccessibleEventNotifier::removeEventListener( mnClientId, rxListener );
		if ( !nListenerCount )
		{
			// no listeners anymore
			// -> revoke ourself. This may lead to the notifier thread dying (if we were the last client),
			// and at least to us not firing any events anymore, in case somebody calls
			// NotifyAccessibleEvent, again
			comphelper::AccessibleEventNotifier::revokeClient( mnClientId );
			mnClientId = 0;
		}
	}
}




//=====  XServiceInfo  ========================================================

::rtl::OUString SAL_CALL
   	AccessibleContextBase::getImplementationName (void)
    throw (::com::sun::star::uno::RuntimeException)
{
    ThrowIfDisposed ();
	return OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleContextBase"));
}




sal_Bool SAL_CALL
 	AccessibleContextBase::supportsService (const OUString& sServiceName)
    throw (::com::sun::star::uno::RuntimeException)
{
    ThrowIfDisposed ();
    //  Iterate over all supported service names and return true if on of them
    //  matches the given name.
    uno::Sequence< ::rtl::OUString> aSupportedServices (
        getSupportedServiceNames ());
    for (int i=0; i<aSupportedServices.getLength(); i++)
        if (sServiceName == aSupportedServices[i])
            return sal_True;
    return sal_False;
}




uno::Sequence< ::rtl::OUString> SAL_CALL
   	AccessibleContextBase::getSupportedServiceNames (void)
    throw (::com::sun::star::uno::RuntimeException)
{
    ThrowIfDisposed ();
	static const OUString sServiceNames[2] = {
        OUString(RTL_CONSTASCII_USTRINGPARAM(
            "com.sun.star.accessibility.Accessible")),
        OUString(RTL_CONSTASCII_USTRINGPARAM(
            "com.sun.star.accessibility.AccessibleContext"))
    };
	return uno::Sequence<OUString> (sServiceNames, 2);
}




//=====  XTypeProvider  =======================================================

uno::Sequence< ::com::sun::star::uno::Type>
	AccessibleContextBase::getTypes (void)
    throw (::com::sun::star::uno::RuntimeException)
{
    ThrowIfDisposed ();

    // This class supports no interfaces on its own.  Just return those
    // supported by the base class.
	return BaseClass::getTypes();
}




uno::Sequence<sal_Int8> SAL_CALL
	AccessibleContextBase::getImplementationId (void)
    throw (::com::sun::star::uno::RuntimeException)
{
    ThrowIfDisposed ();
	static uno::Sequence<sal_Int8> aId;
	if (aId.getLength() == 0)
	{
        ::osl::MutexGuard aGuard (maMutex);
		aId.realloc (16);
		rtl_createUuid ((sal_uInt8 *)aId.getArray(), 0, sal_True);
	}
	return aId;
}




//=====  internal  ============================================================

void SAL_CALL AccessibleContextBase::disposing (void)
{
    SetState (AccessibleStateType::DEFUNC);

    ::osl::MutexGuard aGuard (maMutex);

    // Send a disposing to all listeners.
	if ( mnClientId )
	{
        comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( mnClientId, *this );
		mnClientId =  0;
	}
}




void AccessibleContextBase::SetAccessibleDescription (
    const ::rtl::OUString& rDescription,
    StringOrigin eDescriptionOrigin)
    throw (uno::RuntimeException)
{
    if (eDescriptionOrigin < meDescriptionOrigin
        || (eDescriptionOrigin == meDescriptionOrigin && msDescription != rDescription))
	{
		uno::Any aOldValue, aNewValue;
		aOldValue <<= msDescription;
		aNewValue <<= rDescription;

		msDescription = rDescription;
        meDescriptionOrigin = eDescriptionOrigin;

        CommitChange(
            AccessibleEventId::DESCRIPTION_CHANGED,
            aNewValue,
            aOldValue);
	}
}




void AccessibleContextBase::SetAccessibleName (
    const ::rtl::OUString& rName,
    StringOrigin eNameOrigin)
    throw (uno::RuntimeException)
{
    if (eNameOrigin < meNameOrigin
        || (eNameOrigin == meNameOrigin && msName != rName))
	{
		uno::Any aOldValue, aNewValue;
		aOldValue <<= msName;
		aNewValue <<= rName;

		msName = rName;
        meNameOrigin = eNameOrigin;

        CommitChange(
            AccessibleEventId::NAME_CHANGED,
            aNewValue,
            aOldValue);
	}
}




::rtl::OUString AccessibleContextBase::CreateAccessibleDescription (void)
    throw (::com::sun::star::uno::RuntimeException)
{
    return ::rtl::OUString::createFromAscii ("Empty Description");
}




::rtl::OUString AccessibleContextBase::CreateAccessibleName (void)
    throw (::com::sun::star::uno::RuntimeException)
{
    return ::rtl::OUString::createFromAscii ("Empty Name");
}




void AccessibleContextBase::CommitChange (
    sal_Int16 nEventId,
    const uno::Any& rNewValue,
    const uno::Any& rOldValue)
{
    // Do not call FireEvent and do not even create the event object when no
    // listener has been registered yet.  Creating the event object can
    // otherwise lead to a crash.  See issue 93419 for details.
	if (mnClientId != 0)
    {
        AccessibleEventObject aEvent (
            static_cast<XAccessibleContext*>(this),
            nEventId,
            rNewValue,
            rOldValue);

        FireEvent (aEvent);
    }
}




void AccessibleContextBase::FireEvent (const AccessibleEventObject& aEvent)
{
	if (mnClientId)
		comphelper::AccessibleEventNotifier::addEvent( mnClientId, aEvent );
}




void AccessibleContextBase::ThrowIfDisposed (void)
    throw (::com::sun::star::lang::DisposedException)
{
	if (rBHelper.bDisposed || rBHelper.bInDispose)
	{
        OSL_TRACE ("Calling disposed object. Throwing exception:");
        throw lang::DisposedException (
            OUString(RTL_CONSTASCII_USTRINGPARAM("object has been already disposed")),
            static_cast<uno::XWeak*>(this));
    }
}



sal_Bool AccessibleContextBase::IsDisposed (void)
{
	return (rBHelper.bDisposed || rBHelper.bInDispose);
}



void AccessibleContextBase::SetAccessibleRole( sal_Int16 _nRole )
{
	maRole = _nRole;
}


} // end of namespace accessibility
