/**************************************************************
 * 
 * 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.
 * 
 *************************************************************/



import java.util.Vector;

import com.sun.star.uno.AnyConverter;
import com.sun.star.uno.UnoRuntime;
import com.sun.star.uno.Type;
import com.sun.star.accessibility.*;

/** Handle all the events send from accessibility objects.  The events
    denoting new or removed top windows are handled as well.

    It does not implement any listener interface as does the
    EventListenerProxy class because it is interested only in a sub set of
    the event types.
*/
public class EventHandler
{
    public EventHandler ()
    {
        mnTopWindowCount = 0;
        maListenerProxy = new EventListenerProxy (this);
        maConnectionTask = new ConnectionTask (maListenerProxy);
        maObjectDisplays = new Vector ();
    }

    public synchronized void addObjectDisplay (IAccessibleObjectDisplay aDisplay)
    {
        maObjectDisplays.add (aDisplay);
    }


    public void finalize ()
    {
        // When it is running then cancel the timer that tries to connect to
        // the Office.
        if (maConnectionTask != null)
            maConnectionTask.cancel();
    }



    public void disposing (com.sun.star.lang.EventObject aEvent)
    {
        // Ignored: We are not holding references to accessibility objects.
    }




    /**  This method is called back when a new top level window has been opened.
    */
    public void windowOpened (XAccessible xAccessible)
    {
        if (xAccessible != null)
        {
            // Update the counter of currently open top level windows
            // observed by this object.
            mnTopWindowCount += 1;

            XAccessibleContext xContext = xAccessible.getAccessibleContext();
            if (xContext != null)
            {
                MessageArea.println ("new top level window has accessible name " 
                    + xContext.getAccessibleName());

                // Register at all accessible objects of the new window.
                new RegistrationThread (
                    maListenerProxy,
                    xContext,
                    true,
                    true);
            }
            else
                MessageArea.println ("new top level window is not accessible.");
        }
        else
            MessageArea.println ("new top level window is not accessible.");
    }




    public void windowClosed (XAccessible xAccessible)
    {
        mnTopWindowCount -= 1;
        MessageArea.println ("window closed, " + mnTopWindowCount + " still open");
        if (mnTopWindowCount == 0)
        {
            // This was the last window.  Wait for a new connection.
            MessageArea.println ("lost connection to office");
            new ConnectionTask (maListenerProxy);
        }
        if (xAccessible != null)
            new RegistrationThread (
                maListenerProxy,
                xAccessible.getAccessibleContext(),
                false,
                true);
    }




    /** Print a message that the given object just received the focus.  Call
        all accessible object diplays and tell them to update.
    */
	private synchronized void focusGained (XAccessibleContext xContext)
    {
        if (xContext != null)
        {
            MessageArea.println ("focusGained: " + xContext.getAccessibleName() 
                + " with role "
                + NameProvider.getRoleName (xContext.getAccessibleRole()));

            // Tell the object displays to update their views.
            for (int i=0; i<maObjectDisplays.size(); i++)
            {
                IAccessibleObjectDisplay aDisplay = 
                    (IAccessibleObjectDisplay)maObjectDisplays.get(i);
                if (aDisplay != null)
                    aDisplay.setAccessibleObject (xContext);
            }

            // Remember the currently focused object.
            mxFocusedObject = xContext;
        }
        else
            MessageArea.println ("focusGained: null");
    }



 
    /** Print a message that the given object just lost the focus.  Call
        all accessible object diplays and tell them to update.
    */
	private synchronized void focusLost (XAccessibleContext xContext)
    {
        if (xContext != null)
        {
            MessageArea.println ("focusLost: " 
                + xContext.getAccessibleName() 
                + " with role "
                + NameProvider.getRoleName (xContext.getAccessibleRole()));

            // Tell the object displays to update their views.
            for (int i=0; i<maObjectDisplays.size(); i++)
            {
                IAccessibleObjectDisplay aDisplay = 
                    (IAccessibleObjectDisplay)maObjectDisplays.get(i);
                if (aDisplay != null)
                    aDisplay.setAccessibleObject (null);
            }
            mxFocusedObject = null;
        }
        else
            MessageArea.println ("focusLost: null");
    }




    /** Handle a change of the caret position.  Ignore this on all objects
        but the one currently focused.
    */
    private void handleCaretEvent (XAccessibleContext xContext, 
        long nOldPosition, long nNewPosition)
    {
        if (xContext == mxFocusedObject)
            MessageArea.println ("caret moved from " + nOldPosition + " to " + nNewPosition);
    }




    /** Print a message that a state has been changed.
        @param xContext
            The accessible context of the object whose state has changed.
        @param nOldState
            When not zero then this value describes a state that has been reset.
        @param nNewValue
            When not zero then this value describes a state that has been set.
    */
    private void handleStateChange (XAccessibleContext xContext, short nOldState, short nNewState)
    {
        // Determine which state has changed and what is its new value.
        short nState;
        boolean aNewValue;
        if (nOldState >= 0)
        {
            nState = nOldState;
            aNewValue = false;
        }
        else
        {
            nState = nNewState;
            aNewValue = true;
        }

        // Print a message about the changed state.
        MessageArea.print ("setting state " + NameProvider.getStateName(nState) 
            + " to " + aNewValue);
        if (xContext != null)
        {
            MessageArea.println (" at " + xContext.getAccessibleName() + " with role "
                + NameProvider.getRoleName(xContext.getAccessibleRole()));
        }
        else
            MessageArea.println (" at null");

        // Further handling of some states 
        switch (nState)
        {
            case AccessibleStateType.FOCUSED:
                if (aNewValue)
                    focusGained (xContext);
                else
                    focusLost (xContext);
        }
    }




    /** Handle a child event that describes the creation of removal of a
        single child.
    */
    private void handleChildEvent (
        XAccessibleContext aOldChild, 
        XAccessibleContext aNewChild)
    {
        if (aOldChild != null)
            // Remove event listener from the child and all of its descendants.
            new RegistrationThread (maListenerProxy, aOldChild, false, false);
        else if (aNewChild != null)
            // Add event listener to the new child and all of its descendants.
            new RegistrationThread (maListenerProxy, aNewChild, true, false);
    }




    /** Handle the change of some visible data of an object.
    */
    private void handleVisibleDataEvent (XAccessibleContext xContext)
    {
        // The given object may affect the visible appearance of the focused
        // object even when the two are not identical when the given object
        // is an ancestor of the focused object.
        // In order to not check this we simply call an update on the
        // focused object.
        if (mxFocusedObject != null)
            for (int i=0; i<maObjectDisplays.size(); i++)
            {
                IAccessibleObjectDisplay aDisplay = 
                    (IAccessibleObjectDisplay)maObjectDisplays.get(i);
                if (aDisplay != null)
                    aDisplay.updateAccessibleObject (mxFocusedObject);
            }
    }




    /** Print some information about an event that is not handled by any
        more specialized handler.
    */
    private void handleGenericEvent (
        int nEventId,
        Object aSource, 
        Object aOldValue, 
        Object aNewValue)
    {
        // Print event to message area.
        MessageArea.print ("received event " 
            + NameProvider.getEventName (nEventId) + " from ");
        XAccessibleContext xContext = objectToContext (aSource);
        if (xContext != null)
            MessageArea.print (xContext.getAccessibleName());
        else
            MessageArea.print ("null");
        MessageArea.println (" / " 
            + NameProvider.getRoleName(xContext.getAccessibleRole()));
    }



    /** This is the main method for handling accessibility events.  It is
        assumed that it is not called directly from the Office but from a
        listener proxy that runs in a separate thread so that calls back to
        the Office do not result in dead-locks.
    */
    public void notifyEvent (com.sun.star.accessibility.AccessibleEventObject aEvent)
    {
        try // Guard against disposed objects.
        {
            switch (aEvent.EventId)
            {
                case AccessibleEventId.CHILD:
                    handleChildEvent (
                        objectToContext (aEvent.OldValue),
                        objectToContext (aEvent.NewValue));
                    break;

                case AccessibleEventId.STATE_CHANGED:
                {
                    short nOldState = -1;
                    short nNewState = -1;
                    try 
                    {
                        if (AnyConverter.isShort (aEvent.NewValue))
                            nNewState = AnyConverter.toShort (aEvent.NewValue);
                        if (AnyConverter.isShort (aEvent.OldValue))
                            nOldState = AnyConverter.toShort (aEvent.OldValue);
                    }
                    catch (com.sun.star.lang.IllegalArgumentException e) 
                    {}
                    handleStateChange (
                        objectToContext (aEvent.Source),
                        nOldState,
                        nNewState);
                }
                break;

                case AccessibleEventId.VISIBLE_DATA_CHANGED:
                case AccessibleEventId.BOUNDRECT_CHANGED:
                    handleVisibleDataEvent (objectToContext (aEvent.Source));
                    break;
                
                case AccessibleEventId.CARET_CHANGED:
                    try
                    {
                        handleCaretEvent (
                            objectToContext (aEvent.Source),
                            AnyConverter.toLong(aEvent.OldValue),
                            AnyConverter.toLong(aEvent.NewValue));
                    }
                    catch (com.sun.star.lang.IllegalArgumentException e) 
                    {}
                    break;

                default:
                    handleGenericEvent (aEvent.EventId,
                        aEvent.Source, aEvent.OldValue, aEvent.NewValue);
                    break;
            }
        }
        catch (com.sun.star.lang.DisposedException e)
        {}
    }




    /** Convert the given object into an accessible context.  The object is
        interpreted as UNO Any and may contain either an XAccessible or
        XAccessibleContext reference.
        @return
            The returned value is null when the given object can not be
            converted to an XAccessibleContext reference.
    */
    private XAccessibleContext objectToContext (Object aObject)
    {
        XAccessibleContext xContext = null;
        XAccessible xAccessible = null;
        try
        {
            xAccessible = (XAccessible)AnyConverter.toObject(
                new Type(XAccessible.class), aObject);
        }
        catch (com.sun.star.lang.IllegalArgumentException e)
        {}
        if (xAccessible != null)
            xContext = xAccessible.getAccessibleContext();
        else
            try
            {
                xContext = (XAccessibleContext)AnyConverter.toObject(
                    new Type(XAccessibleContext.class), aObject);
            }
            catch (com.sun.star.lang.IllegalArgumentException e)
            {}
        return xContext;
    }




    /** The proxy that runs in a separate thread and allows to call back to
        the Office without running into dead-locks.
    */
    private EventListenerProxy maListenerProxy;

    /** The currently focused object.  A value of null means that no object
        has the focus.
    */
    private XAccessibleContext mxFocusedObject;

    /** Keep track of the currently open top windows to start a registration
        loop when the last window (and the Office) is closed.
    */
    private long mnTopWindowCount;

    /** A list of objects that can display accessible objects in specific
        ways such as showing a graphical representation or some textual
        descriptions.
    */
    private Vector maObjectDisplays;

    /** The timer task that attempts in regular intervals to connect to a
        running Office application.
    */
    private ConnectionTask maConnectionTask;
}
