/*
 * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.java.accessibility.util;

import java.util.*;
import java.beans.*;
import java.awt.*;
import java.awt.event.*;
import javax.accessibility.*;

/**
 * <P>{@code AccessibilityEventMonitor} implements a PropertyChange listener
 * on every UI object that implements interface {@code Accessible} in the Java
 * Virtual Machine.  The events captured by these listeners are made available
 * through listeners supported by {@code AccessibilityEventMonitor}.
 * With this, all the individual events on each of the UI object
 * instances are funneled into one set of PropertyChange listeners.
 * <p>This class depends upon {@link EventQueueMonitor}, which provides the base
 * level support for capturing the top-level containers as they are created.
 *
 */

public class AccessibilityEventMonitor {

    // listeners
    /**
     * The current list of registered {@link java.beans.PropertyChangeListener
     * PropertyChangeListener} classes.
     *
     * @see #addPropertyChangeListener
     * @see #removePropertyChangeListener
     */
    static protected final AccessibilityListenerList listenerList =
        new AccessibilityListenerList();


    /**
     * The actual listener that is installed on the component instances.
     * This listener calls the other registered listeners when an event
     * occurs.  By doing things this way, the actual number of listeners
     * installed on a component instance is drastically reduced.
     */
    static protected final AccessibilityEventListener accessibilityListener =
        new AccessibilityEventListener();

    /**
     * Adds the specified listener to receive all PropertyChange events on
     * each UI object instance in the Java Virtual Machine as they occur.
     * <P>Note: This listener is automatically added to all component
     * instances created after this method is called.  In addition, it
     * is only added to UI object instances that support this listener type.
     *
     * @param l the listener to add
     *
     * @see #removePropertyChangeListener
     */
    static public void addPropertyChangeListener(PropertyChangeListener l) {
        if (listenerList.getListenerCount(PropertyChangeListener.class) == 0) {
            accessibilityListener.installListeners();
        }
        listenerList.add(PropertyChangeListener.class, l);
    }

    /**
     * Removes the specified listener so it no longer receives PropertyChange
     * events when they occur.
     * @see #addPropertyChangeListener
     * @param l the listener to remove
     */
    static public void removePropertyChangeListener(PropertyChangeListener l) {
        listenerList.remove(PropertyChangeListener.class, l);
        if (listenerList.getListenerCount(PropertyChangeListener.class) == 0) {
            accessibilityListener.removeListeners();
        }
    }


    /**
     * AccessibilityEventListener is the class that does all the work for
     * AccessibilityEventMonitor.  It is not intended for use by any other
     * class except AccessibilityEventMonitor.
     *
     */

    static class AccessibilityEventListener implements TopLevelWindowListener,
                PropertyChangeListener {

        /**
         * Create a new instance of this class and install it on each component
         * instance in the virtual machine that supports any of the currently
         * registered listeners in AccessibilityEventMonitor.  Also registers
         * itself as a TopLevelWindowListener with EventQueueMonitor so it can
         * automatically add new listeners to new components.
         * @see EventQueueMonitor
         * @see AccessibilityEventMonitor
         */
        public AccessibilityEventListener() {
            EventQueueMonitor.addTopLevelWindowListener(this);
        }

        /**
         * Installs PropertyChange listeners on all Accessible objects based
         * upon the current topLevelWindows cached by EventQueueMonitor.
         * @see EventQueueMonitor
         * @see AWTEventMonitor
         */
        protected void installListeners() {
            Window topLevelWindows[] = EventQueueMonitor.getTopLevelWindows();
            if (topLevelWindows != null) {
                for (int i = 0; i < topLevelWindows.length; i++) {
                    if (topLevelWindows[i] instanceof Accessible) {
                        installListeners((Accessible) topLevelWindows[i]);
                    }
                }
            }
        }

        /**
         * Installs PropertyChange listeners to the Accessible object, and it's
         * children (so long as the object isn't of TRANSIENT state).
         * @param a the Accessible object to add listeners to
         */
        protected void installListeners(Accessible a) {
            installListeners(a.getAccessibleContext());
        }

        /**
         * Installs PropertyChange listeners to the AccessibleContext object,
         * and it's * children (so long as the object isn't of TRANSIENT state).
         * @param a the Accessible object to add listeners to
         */
        private void installListeners(AccessibleContext ac) {

            if (ac != null) {
                AccessibleStateSet states = ac.getAccessibleStateSet();
                if (!states.contains(AccessibleState.TRANSIENT)) {
                    ac.addPropertyChangeListener(this);
                    /*
                     * Don't add listeners to transient children. Components
                     * with transient children should return an AccessibleStateSet
                     * containing AccessibleState.MANAGES_DESCENDANTS. Components
                     * may not explicitly return the MANAGES_DESCENDANTS state.
                     * In this case, don't add listeners to the children of
                     * lists, tables and trees.
                     */
                    AccessibleStateSet set = ac.getAccessibleStateSet();
                    if (set.contains(_AccessibleState.MANAGES_DESCENDANTS)) {
                        return;
                    }
                    AccessibleRole role = ac.getAccessibleRole();
                    if (role == AccessibleRole.LIST ||
                        role == AccessibleRole.TREE) {
                        return;
                    }
                    if (role == AccessibleRole.TABLE) {
                        // handle Oracle tables containing tables
                        Accessible child = ac.getAccessibleChild(0);
                        if (child != null) {
                            AccessibleContext ac2 = child.getAccessibleContext();
                            if (ac2 != null) {
                                role = ac2.getAccessibleRole();
                                if (role != null && role != AccessibleRole.TABLE) {
                                    return;
                                }
                            }
                        }
                    }
                    int count = ac.getAccessibleChildrenCount();
                    for (int i = 0; i < count; i++) {
                        Accessible child = ac.getAccessibleChild(i);
                        if (child != null) {
                            installListeners(child);
                        }
                    }
                }
            }
        }

        /**
         * Removes PropertyChange listeners on all Accessible objects based
         * upon the topLevelWindows cached by EventQueueMonitor.
         * @param eventID the event ID
         * @see EventID
         */
        protected void removeListeners() {
            Window topLevelWindows[] = EventQueueMonitor.getTopLevelWindows();
            if (topLevelWindows != null) {
                for (int i = 0; i < topLevelWindows.length; i++) {
                    if (topLevelWindows[i] instanceof Accessible) {
                        removeListeners((Accessible) topLevelWindows[i]);
                    }
                }
            }
        }

        /**
         * Removes PropertyChange listeners for the given Accessible object,
         * it's children (so long as the object isn't of TRANSIENT state).
         * @param a the Accessible object to remove listeners from
         */
        protected void removeListeners(Accessible a) {
            removeListeners(a.getAccessibleContext());
        }

        /**
         * Removes PropertyChange listeners for the given AccessibleContext
         * object, it's children (so long as the object isn't of TRANSIENT
         * state).
         * @param a the Accessible object to remove listeners from
         */
        private void removeListeners(AccessibleContext ac) {


            if (ac != null) {
                // Listeners are not added to transient components.
                AccessibleStateSet states = ac.getAccessibleStateSet();
                if (!states.contains(AccessibleState.TRANSIENT)) {
                    ac.removePropertyChangeListener(this);
                    /*
                     * Listeners are not added to transient children. Components
                     * with transient children should return an AccessibleStateSet
                     * containing AccessibleState.MANAGES_DESCENDANTS. Components
                     * may not explicitly return the MANAGES_DESCENDANTS state.
                     * In this case, don't remove listeners from the children of
                     * lists, tables and trees.
                     */
                    if (states.contains(_AccessibleState.MANAGES_DESCENDANTS)) {
                        return;
                    }
                    AccessibleRole role = ac.getAccessibleRole();
                    if (role == AccessibleRole.LIST ||
                        role == AccessibleRole.TABLE ||
                        role == AccessibleRole.TREE) {
                        return;
                    }
                    int count = ac.getAccessibleChildrenCount();
                    for (int i = 0; i < count; i++) {
                        Accessible child = ac.getAccessibleChild(i);
                        if (child != null) {
                            removeListeners(child);
                        }
                    }
                }
            }
        }

        /********************************************************************/
        /*                                                                  */
        /* Listener Interface Methods                                       */
        /*                                                                  */
        /********************************************************************/

        /* TopLevelWindow Methods ***************************************/

        /**
         * Called when top level window is created.
         * @see EventQueueMonitor
         * @see EventQueueMonitor#addTopLevelWindowListener
         */
        public void topLevelWindowCreated(Window w) {
            if (w instanceof Accessible) {
                installListeners((Accessible) w);
            }
        }

        /**
         * Called when top level window is destroyed.
         * @see EventQueueMonitor
         * @see EventQueueMonitor#addTopLevelWindowListener
         */
        public void topLevelWindowDestroyed(Window w) {
            if (w instanceof Accessible) {
                removeListeners((Accessible) w);
            }
        }


        /* PropertyChangeListener Methods **************************************/

        public void propertyChange(PropertyChangeEvent e) {
            // propogate the event
            Object[] listeners =
                    AccessibilityEventMonitor.listenerList.getListenerList();
            for (int i = listeners.length-2; i>=0; i-=2) {
                if (listeners[i]==PropertyChangeListener.class) {
                    ((PropertyChangeListener)listeners[i+1]).propertyChange(e);
                }
            }

            // handle childbirth/death
            String name = e.getPropertyName();
            if (name.compareTo(AccessibleContext.ACCESSIBLE_CHILD_PROPERTY) == 0) {
                Object oldValue = e.getOldValue();
                Object newValue = e.getNewValue();

                if ((oldValue == null) ^ (newValue == null)) { // one null, not both
                    if (oldValue != null) {
                        // this Accessible is a child that's going away
                        if (oldValue instanceof Accessible) {
                            Accessible a = (Accessible) oldValue;
                            removeListeners(a.getAccessibleContext());
                        } else if (oldValue instanceof AccessibleContext) {
                            removeListeners((AccessibleContext) oldValue);
                        }
                    } else if (newValue != null) {
                        // this Accessible is a child was just born
                        if (newValue instanceof Accessible) {
                            Accessible a = (Accessible) newValue;
                            installListeners(a.getAccessibleContext());
                        } else if (newValue instanceof AccessibleContext) {
                            installListeners((AccessibleContext) newValue);
                        }
                    }
                } else {
                    System.out.println("ERROR in usage of PropertyChangeEvents for: " + e.toString());
                }
            }
        }
    }
}

/*
 * workaround for no public AccessibleState constructor
 */
class _AccessibleState extends AccessibleState {
    /**
     * Indicates this object is responsible for managing its
     * subcomponents.  This is typically used for trees and tables
     * that have a large number of subcomponents and where the
     * objects are created only when needed and otherwise remain virtual.
     * The application should not manage the subcomponents directly.
     */
    public static final _AccessibleState MANAGES_DESCENDANTS
        = new _AccessibleState ("managesDescendants");

    /**
     * Creates a new AccessibleState using the given locale independent key.
     * This should not be a public method.  Instead, it is used to create
     * the constants in this file to make it a strongly typed enumeration.
     * Subclasses of this class should enforce similar policy.
     * <p>
     * The key String should be a locale independent key for the state.
     * It is not intended to be used as the actual String to display
     * to the user.  To get the localized string, use toDisplayString.
     *
     * @param key the locale independent name of the state.
     * @see AccessibleBundle#toDisplayString
     */
    protected _AccessibleState(String key) {
        super(key);
    }
}
