/**************************************************************
 *
 * 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 javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.TreePath;


import java.util.Vector;
import java.util.HashMap;
import java.util.Enumeration;

import com.sun.star.accessibility.*;

import com.sun.star.uno.UnoRuntime;
import com.sun.star.uno.XInterface;
import com.sun.star.uno.Any;
import com.sun.star.lang.EventObject;
import com.sun.star.lang.XServiceInfo;
import com.sun.star.lang.XServiceName;

public class AccessibilityTreeModel
    extends AccessibilityTreeModelBase
{
    public boolean mbVerbose = false;

    public AccessibilityTreeModel (AccessibleTreeNode aRoot)
    {
        // create default node (unless we have a 'proper' node)
        if( ! (aRoot instanceof AccessibleTreeNode) )
            aRoot = new StringNode ("Root", null);
        setRoot (aRoot);

        maNodeMap = new NodeMap();

        maEventListener = new EventListener (this);
        mxListener = new QueuedListener (maEventListener);
    }

    public void clear ()
    {
        maNodeMap.Clear();
    }

    /** Lock the tree.  While the tree is locked, events from the outside are
        not processed.  Lock the tree when you change its internal structure.
    */
    public void lock ()
    {
        mnLockCount += 1;
    }

    /** Unlock the tree.  After unlocking the tree as many times as locking
        it, a treeStructureChange event is sent to the event listeners.
        @param aNodeHint
            If not null and treeStructureChange events are thrown then this
            node is used as root of the modified subtree.
    */
    public void unlock (AccessibleTreeNode aNodeHint)
    {
        mnLockCount -= 1;
        if (mnLockCount == 0)
            fireTreeStructureChanged (
                new TreeModelEvent (this,
                    new TreePath (aNodeHint.createPath())));
    }




    /** Inform all listeners (especially the renderer) of a change of the
        tree's structure.
        @param aNode This node specifies the sub tree in which all changes
        take place.
    */
    public void FireTreeStructureChanged (AccessibleTreeNode aNode)
    {
    }





    public synchronized void setRoot (AccessibleTreeNode aRoot)
    {
        if (getRoot() == null)
            super.setRoot (aRoot);
        else
        {
            lock ();
            maNodeMap.ForEach (new NodeMapCallback () {
                    public void Apply (AccTreeNode aNode)
                    {
                        if (maCanvas != null)
                            maCanvas.removeNode (aNode);
                        removeAccListener ((AccTreeNode)aNode);
                    }
                });
            maNodeMap.Clear ();

            setRoot (aRoot);
            unlock (aRoot);
        }
    }


    //
    // child management:
    //



    /** Delegate the request to the parent and then register listeners at
        the child and add the child to the canvas.
    */
    public Object getChild (Object aParent, int nIndex)
    {
        AccessibleTreeNode aChild = (AccessibleTreeNode)super.getChild (aParent, nIndex);

        if (aChild == null)
            System.out.println ("getChild: child not found");
        else
            // Keep translation table up-to-date.
            addNode (aChild);

        return aChild;
    }

    public Object getChildNoCreate (Object aParent, int nIndex)
    {
        AccessibleTreeNode aChild = (AccessibleTreeNode)super.getChildNoCreate (aParent, nIndex);

        return aChild;
    }




    /** Remove a node (and all children) from the tree model.
    */
    protected boolean removeChild (AccessibleTreeNode aNode)
    {
        try
        {
            if( aNode == null )
            {
                System.out.println ("can't remove null node");
                return false;
            }
            else
            {
                // depth-first removal of children
                while (aNode.getChildCount() > 0)
                    if ( ! removeChild (aNode.getChildNoCreate (0)))
                        break;

                // Remove node from its parent.
                AccessibleTreeNode aParent = aNode.getParent();
                if (aParent != null)
                {
                    int nIndex = aParent.indexOf(aNode);
                    aParent.removeChild (nIndex);
                }

                maNodeMap.RemoveNode (aNode);
            }
        }
        catch (Exception e)
        {
            System.out.println ("caught exception while removing child "
                + aNode + " : " + e);
            e.printStackTrace ();
            return false;
        }
        return true;
    }

    public void removeNode (XAccessibleContext xNode)
    {
        if (xNode != null)
        {
            AccessibleTreeNode aNode = maNodeMap.GetNode (xNode);
            AccessibleTreeNode aRootNode = (AccessibleTreeNode)getRoot();
            TreeModelEvent aEvent = createEvent (aRootNode, aNode);
            removeChild (aNode);
            if (mbVerbose)
                System.out.println (aNode);
            fireTreeNodesRemoved (aEvent);
            maCanvas.repaint ();
        }
    }


    /** Add add a new child to a parent.
        @return
            Returns the new or existing representation of the specified
            accessible object.
    */
    protected AccessibleTreeNode addChild (AccTreeNode aParentNode, XAccessible xNewChild)
    {
        AccessibleTreeNode aChildNode = null;
        try
        {
            boolean bRet = false;

            // First make sure that the accessible object does not already have
            // a representation.
            aChildNode = maNodeMap.GetNode(xNewChild);
            if (aChildNode == null)
                aChildNode = aParentNode.addAccessibleChild (xNewChild);
            else
                System.out.println ("node already present");
        }
        catch (Exception e)
        {
            System.out.println ("caught exception while adding child "
                + xNewChild + " to parent " + aParentNode + ": " + e);
            e.printStackTrace ();
        }
        return aChildNode;
    }

    public void addChild (XAccessibleContext xParent, XAccessible xChild)
    {
        AccessibleTreeNode aParentNode = maNodeMap.GetNode (xParent);
        if (aParentNode instanceof AccTreeNode)
        {
            AccessibleTreeNode aChild = addChild ((AccTreeNode)aParentNode, xChild);
            if (addNode (aChild))
            {
                if (maCanvas != null)
                    maCanvas.updateNode ((AccTreeNode)aParentNode);

                // A call to fireTreeNodesInserted for xNew
                // should be sufficient but at least the
                // StringNode object that contains the number of
                // children also changes and we do not know its
                // index relative to its parent.  Therefore the
                // more expensive fireTreeStructureChanged is
                // necessary.
                fireTreeNodesInserted (createEvent (xParent, xChild));
                updateNode (xParent, AccessibleTreeHandler.class);
            }
            maCanvas.repaint ();
        }
    }


    /** Add the child node to the internal tree structure.
        @param aNode
            The node to insert into the internal tree structure.
    */
    protected boolean addNode (AccessibleTreeNode aNode)
    {
        boolean bRet = false;
        try
        {
            if ( ! maNodeMap.ValueIsMember (aNode))
            {
                if (aNode instanceof AccTreeNode)
                {
                    AccTreeNode aChild = (AccTreeNode)aNode;
                    XAccessibleContext xChild = aChild.getContext();
                    registerAccListener (aChild);
                    if (maCanvas != null)
                        maCanvas.addNode (aChild);
                    maNodeMap.InsertNode (xChild, aChild);
                }
                bRet = true;
            }

        }
        catch (Exception e)
        {
            System.out.println ("caught exception while adding node "
                + aNode + ": " + e);
            e.printStackTrace ();
        }
        return bRet;
    }




    /** create path to node, suitable for TreeModelEvent constructor
     * @see javax.swing.event.TreeModelEvent#TreeModelEvent
     */
    protected Object[] createPath (AccessibleTreeNode aNode)
    {
        Vector aPath = new Vector();
        aNode.createPath (aPath);
        return aPath.toArray();
    }

    //
    // listeners (and helper methods)
    //
    // We are registered with listeners as soon as objects are in the
    // tree cache, and we should get removed as soon as they are out.
    //

    protected void fireTreeNodesChanged(TreeModelEvent e)
    {
        for(int i = 0; i < maTMListeners.size(); i++)
        {
            ((TreeModelListener)maTMListeners.get(i)).treeNodesChanged(e);
        }
    }

    protected void fireTreeNodesInserted(final TreeModelEvent e)
    {
        for(int i = 0; i < maTMListeners.size(); i++)
        {
            ((TreeModelListener)maTMListeners.get(i)).treeNodesInserted(e);
        }
    }

    protected void fireTreeNodesRemoved(final TreeModelEvent e)
    {
        for(int i = 0; i < maTMListeners.size(); i++)
        {
            ((TreeModelListener)maTMListeners.get(i)).treeNodesRemoved(e);
        }
    }

    protected void fireTreeStructureChanged(final TreeModelEvent e)
    {
        for(int i = 0; i < maTMListeners.size(); i++)
        {
            ((TreeModelListener)maTMListeners.get(i)).treeStructureChanged(e);
        }
    }

    protected TreeModelEvent createEvent (XAccessibleContext xParent)
    {
        AccessibleTreeNode aParentNode = maNodeMap.GetNode (xParent);
        return new TreeModelEvent (this, createPath (aParentNode));
    }

    /** Create a TreeModelEvent object that informs listeners that one child
        has been removed from or inserted into its parent.
    */
    public TreeModelEvent createEvent (XAccessibleContext xParent, XAccessible xChild)
    {
        AccessibleTreeNode aParentNode = maNodeMap.GetNode (xParent);
        return createEvent (aParentNode, xParent);
    }

    public TreeModelEvent createEvent (AccessibleTreeNode aParentNode, XAccessibleContext xChild)
    {
        AccessibleTreeNode aChildNode = null;
        if (xChild != null)
            aChildNode = maNodeMap.GetNode (xChild);
        return createEvent (aParentNode, aChildNode);
    }



    protected TreeModelEvent createEvent (
        AccessibleTreeNode aParentNode,
        AccessibleTreeNode aChildNode)
    {
        Object[] aPathToParent = createPath (aParentNode);

        int nIndexInParent = -1;
        if (aChildNode != null)
            nIndexInParent = aParentNode.indexOf (aChildNode);
        if (mbVerbose)
            System.out.println (aChildNode + " " + nIndexInParent);

        if (nIndexInParent == -1)
            // This event may be passed only to treeStructureChanged of the listeners.
            return new TreeModelEvent (this,
                aPathToParent);
        else
            // General purpose event for removing or inserting known nodes.
            return new TreeModelEvent (this,
                aPathToParent,
                new int[] {nIndexInParent},
                new Object[] {aChildNode} );
    }




    /** Create a TreeModelEvent that indicates changes at those children of
        the specified node with the specified indices.
    */
    protected TreeModelEvent createChangeEvent (AccTreeNode aNode, Vector aChildIndices)
    {
        // Build a list of child objects that are indicated by the given indices.
        int nCount = aChildIndices.size();
        Object aChildObjects[] = new Object[nCount];
        int nChildIndices[] = new int[nCount];
        for (int i=0; i<nCount; i++)
        {
            int nIndex = ((Integer)aChildIndices.elementAt(i)).intValue();
            aChildObjects[i] = aNode.getChild (nIndex);
            nChildIndices[i] = nIndex;
        }

        return new TreeModelEvent (this,
            createPath(aNode),
            nChildIndices,
            aChildObjects);
    }



    /**
     * broadcast a tree event in a separate Thread
     * must override fire method
     */
    class EventRunner implements Runnable
    {
        public void run()
        {
            for(int i = 0; i < maTMListeners.size(); i++)
            {
                fire( (TreeModelListener)maTMListeners.get(i) );
            }
        }

        protected void fire( TreeModelListener l) { }
    }



    protected XAccessibleEventBroadcaster getBroadcaster (Object aObject)
    {
        if (aObject instanceof AccTreeNode)
            return (XAccessibleEventBroadcaster) UnoRuntime.queryInterface (
                XAccessibleEventBroadcaster.class, ((AccTreeNode)aObject).getContext());
        else
            return null;
    }

    protected void registerAccListener( Object aObject )
    {
        // register this as listener for XAccessibleEventBroadcaster
        // implementations
        XAccessibleEventBroadcaster xBroadcaster = getBroadcaster( aObject );
        if (xBroadcaster != null)
        {
            xBroadcaster.addEventListener( mxListener );
        }
    }

    protected void removeAccListener( Object aObject )
    {
        XAccessibleEventBroadcaster xBroadcaster = getBroadcaster( aObject );
        if (xBroadcaster != null)
        {
            xBroadcaster.removeEventListener( mxListener );
        }
    }



    public void setCanvas (Canvas aCanvas)
    {
        maCanvas = aCanvas;
    }

    public Canvas getCanvas ()
    {
        return maCanvas;
    }

    public void updateNode (XAccessibleContext xSource, java.lang.Class class1)
    {
        updateNode (xSource, class1,null);
    }

    /** Get a list of children of the node associated with xSource that are
        affected by the given handlers.  Fire events that these children may
        have changed in the tree view.  Update the canvas representation of
        xSource.
    */
    public AccTreeNode updateNode (XAccessibleContext xSource,
        java.lang.Class class1, java.lang.Class class2)
    {
        AccessibleTreeNode aTreeNode = maNodeMap.GetNode (xSource);
        AccTreeNode aNode = null;
        if (mbVerbose)
            System.out.println ("updating node " + xSource + "  " + aTreeNode);
        if (aTreeNode instanceof AccTreeNode)
        {
            aNode = (AccTreeNode) aTreeNode;
            // Get list of affected children.
            Vector aChildIndices = (aNode).updateChildren (
                class1, class2);
            // Fire events that these children may have changed.
            fireTreeNodesChanged (
                createChangeEvent (aNode, aChildIndices));
        }
        return aNode;
    }

    /** The listener to be registered with the accessible objects.
     * Could be set to 'this' for same-thread event delivery, or to an
     * instance of QueuedListener for multi-threaded delivery.  May
     * not be changed, since this would trip the
     * register/removeAccListener logic. */
    private final XAccessibleEventListener mxListener;

    // Map to translate from accessible object to corresponding tree node.
    private NodeMap maNodeMap;

    // If the lock count is higher then zero, then no events are processed.
    private int mnLockCount;

    private Canvas maCanvas;

    private EventListener maEventListener;
}
