YUI.add('aui-overlay-manager-deprecated', function (A, NAME) {

/**
 * The OverlayManager Utility
 *
 * @module aui-overlay
 * @submodule aui-overlay-manager
 */

var Lang = A.Lang,
    isArray = Lang.isArray,
    isBoolean = Lang.isBoolean,
    isNumber = Lang.isNumber,
    isString = Lang.isString,

    BOUNDING_BOX = 'boundingBox',
    DEFAULT = 'default',
    HOST = 'host',
    OVERLAY_MANAGER = 'OverlayManager',
    GROUP = 'group',
    Z_INDEX = 'zIndex',
    Z_INDEX_BASE = 'zIndexBase';

/**
 * <p><img src="assets/images/aui-overlay-manager/main.png"/></p>
 *
 * A base class for OverlayManager, providing:
 * <ul>
 *    <li>Grouping overlays</li>
 *    <li>Show or hide the entire group of registered overlays</li>
 *    <li>Basic Overlay Stackability (zIndex support)</li>
 * </ul>
 *
 * Quick Example:<br/>
 *
 * <pre><code>var groupOverlayManager = new A.OverlayManager();
 * groupOverlayManager.register([overlay1, overlay2, overlay3]);
 * groupOverlayManager.hideAll();
 * </code></pre>
 *
 * Check the list of <a href="OverlayManager.html#configattributes">Configuration Attributes</a> available for
 * OverlayManager.
 *
 * @param config {Object} Object literal specifying widget configuration properties.
 *
 * @class OverlayManager
 * @constructor
 * @extends Base
 */
var OverlayManager = A.Component.create({
    /**
     * Static property provides a string to identify the class.
     *
     * @property OverlayManager.NAME
     * @type String
     * @static
     */
    NAME: OVERLAY_MANAGER.toLowerCase(),

    /**
     * Static property used to define the default attribute
     * configuration for the OverlayManager.
     *
     * @property OverlayManager.ATTRS
     * @type Object
     * @static
     */
    ATTRS: {
        /**
         * The zIndex base to be used on the stacking for all overlays
         * registered on the OverlayManager.
         *
         * @attribute zIndexBase
         * @default 1000
         * @type Number
         */
        zIndexBase: {
            value: 1000,
            validator: isNumber,
            setter: Lang.toInt
        }
    },

    EXTENDS: A.Base,

    prototype: {
        /**
         * Construction logic executed during OverlayManager instantiation. Lifecycle.
         *
         * @method initializer
         * @protected
         */
        initializer: function() {
            var instance = this;

            instance._overlays = [];
        },

        /**
         * Set the passed overlay zIndex to the highest value.
         *
         * @method bringToTop
         * @param {Overlay} overlay Instance of
         * <a href="Overlay.html">Overlay</a>.
         */
        bringToTop: function(overlay) {
            var instance = this;

            var overlays = instance._overlays.sort(instance.sortByZIndexDesc);

            var highest = overlays[0];

            if (highest !== overlay) {
                var overlayZ = overlay.get(Z_INDEX);
                var highestZ = highest.get(Z_INDEX);

                overlay.set(Z_INDEX, highestZ + 1);

                overlay.set('focused', true);
            }
        },

        /**
         * Destructor lifecycle implementation for the OverlayManager class.
         * Purges events attached to the node (and all child nodes).
         *
         * @method destructor
         * @protected
         */
        destructor: function() {
            var instance = this;

            instance._overlays = [];
        },

        /**
         * Register the passed <a href="Overlay.html">Overlay</a> to this
         * OverlayManager.
         *
         * @method register
         * @param {Overlay} overlay <a href="Overlay.html">Overlay</a> instance to be registered
         * @return {Array} Registered overlays
         */
        register: function(overlay) {
            var instance = this;

            var overlays = instance._overlays;

            if (isArray(overlay)) {
                A.Array.each(overlay, function(o) {
                    instance.register(o);
                });
            }
            else {
                var zIndexBase = instance.get(Z_INDEX_BASE);
                var registered = instance._registered(overlay);

                if (!registered && overlay &&
                    ((overlay instanceof A.Overlay) ||
                        (A.Component && overlay instanceof A.Component))
                ) {
                    var boundingBox = overlay.get(BOUNDING_BOX);

                    overlays.push(overlay);

                    var zIndex = overlay.get(Z_INDEX) || 0;
                    var newZIndex = overlays.length + zIndex + zIndexBase;

                    overlay.set(Z_INDEX, newZIndex);

                    overlay.on('focusedChange', instance._onFocusedChange, instance);
                    boundingBox.on('mousedown', instance._onMouseDown, instance);
                }
            }

            return overlays;
        },

        /**
         * Remove the passed <a href="Overlay.html">Overlay</a> from this
         * OverlayManager.
         *
         * @method remove
         * @param {Overlay} overlay <a href="Overlay.html">Overlay</a> instance to be removed
         * @return {null}
         */
        remove: function(overlay) {
            var instance = this;

            var overlays = instance._overlays;

            if (overlays.length) {
                return A.Array.removeItem(overlays, overlay);
            }

            return null;
        },

        /**
         * Loop through all registered <a href="Overlay.html">Overlay</a> and
         * execute a callback.
         *
         * @method each
         * @param {function} fn Callback to be executed on the
         * <a href="Array.html#method_each">Array.each</a>
         * @return {null}
         */
        each: function(fn) {
            var instance = this;

            var overlays = instance._overlays;

            A.Array.each(overlays, fn);
        },

        /**
         * Invoke the <a href="Overlay.html#method_show">show</a> method from
         * all registered Overlays.
         *
         * @method showAll
         */
        showAll: function() {
            this.each(
                function(overlay) {
                    overlay.show();
                }
            );
        },

        /**
         * Invoke the <a href="Overlay.html#method_hide">hide</a> method from
         * all registered Overlays.
         *
         * @method hideAll
         */
        hideAll: function() {
            this.each(
                function(overlay) {
                    overlay.hide();
                }
            );
        },

        /**
         * zIndex comparator. Used on Array.sort.
         *
         * @method sortByZIndexDesc
         * @param {Overlay} a Overlay
         * @param {Overlay} b Overlay
         * @return {Number}
         */
        sortByZIndexDesc: function(a, b) {
            if (!a || !b || !a.hasImpl(A.WidgetStack) || !b.hasImpl(A.WidgetStack)) {
                return 0;
            }
            else {
                var aZ = a.get(Z_INDEX);
                var bZ = b.get(Z_INDEX);

                if (aZ > bZ) {
                    return -1;
                }
                else if (aZ < bZ) {
                    return 1;
                }
                else {
                    return 0;
                }
            }
        },

        /**
         * Check if the overlay is registered.
         *
         * @method _registered
         * @param {Overlay} overlay Overlay
         * @protected
         * @return {boolean}
         */
        _registered: function(overlay) {
            var instance = this;

            return A.Array.indexOf(instance._overlays, overlay) != -1;
        },

        /**
         * Mousedown event handler, used to invoke
         * <a href="OverlayManager.html#method_bringToTop">bringToTop</a>.
         *
         * @method _onMouseDown
         * @param {EventFacade} event
         * @protected
         */
        _onMouseDown: function(event) {
            var instance = this;
            var overlay = A.Widget.getByNode(event.currentTarget || event.target);
            var registered = instance._registered(overlay);

            if (overlay && registered) {
                instance.bringToTop(overlay);
            }
        },

        /**
         * Fires when the <a href="Widget.html#config_focused">focused</a>
         * attribute change. Used to invoke
         * <a href="OverlayManager.html#method_bringToTop">bringToTop</a>.
         *
         * @method _onFocusedChange
         * @param {EventFacade} event
         * @protected
         */
        _onFocusedChange: function(event) {
            var instance = this;

            if (event.newVal) {
                var overlay = event.currentTarget || event.target;
                var registered = instance._registered(overlay);

                if (overlay && registered) {
                    instance.bringToTop(overlay);
                }
            }
        }
    }
});

A.OverlayManager = OverlayManager;


}, '3.1.0-deprecated.112', {"requires": ["overlay", "plugin", "aui-base-deprecated", "aui-overlay-base-deprecated"]});
