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

/**
 * The OverlayContextPanel Utility
 *
 * @module aui-overlay
 * @submodule aui-overlay-context-panel
 */

var L = A.Lang,
    isBoolean = L.isBoolean,
    isString = L.isString,
    isObject = L.isObject,

    ALIGN = 'align',
    ANIM = 'anim',
    ARROW = 'arrow',
    BACKGROUND_COLOR = 'backgroundColor',
    BLANK = '',
    BOUNDING_BOX = 'boundingBox',
    CLICK = 'click',
    CONTENT_BOX = 'contentBox',
    CONTEXTPANEL = 'overlaycontextpanel',
    DEFAULT = 'default',
    DOT = '.',
    END = 'end',
    HIDDEN = 'hidden',
    INNER = 'inner',
    OPACITY = 'opacity',
    POINTER = 'pointer',
    SHOW_ARROW = 'showArrow',
    STATE = 'state',
    STYLE = 'style',
    VISIBLE = 'visible',

    BC = 'bc',
    BL = 'bl',
    BR = 'br',
    CC = 'cc',
    LB = 'lb',
    LC = 'lc',
    LT = 'lt',
    RB = 'rb',
    RC = 'rc',
    RL = 'rl',

    getCN = A.getClassName,

    CSS_CONTEXTPANEL = getCN(CONTEXTPANEL),
    CSS_CONTEXTPANEL_ARROW = getCN(CONTEXTPANEL, ARROW, BLANK),
    CSS_CONTEXTPANEL_HIDDEN = getCN(CONTEXTPANEL, HIDDEN),
    CSS_CONTEXTPANEL_POINTER = getCN(CONTEXTPANEL, POINTER),
    CSS_CONTEXTPANEL_POINTER_INNER = getCN(CONTEXTPANEL, POINTER, INNER),
    CSS_STATE_DEFAULT = getCN(STATE, DEFAULT),

    TPL_POINTER = '<div class="' + [CSS_STATE_DEFAULT, CSS_CONTEXTPANEL_POINTER].join(' ') + '"></div>',
    TPL_POINTER_INNER = '<div class="' + CSS_CONTEXTPANEL_POINTER_INNER + '"></div>';

/**
 * <p><img src="assets/images/aui-overlay-context-panel/main.png"/></p>
 *
 * A base class for OverlayContextPanel, providing:
 * <ul>
 *	<li>Widget Lifecycle (initializer, renderUI, bindUI, syncUI, destructor)</li>
 *	<li>Customizable arrow</li>
 *	<li>Optional animation when show or hide</li>
 * </ul>
 *
 * Quick Example:<br/>
 *
 * <pre><code>var instance = new A.OverlayContextPanel({
 *  bodyContent: 'Here s a sample OverlayContextPanel.',
 *  boundingBox: '#overlay-context-panel',
 *  trigger: '#triggerButton',
 *  cancellableHide: true,
 *  hideDelay: 200,
 *  hideOnDocumentClick: false,
 *  anim: true
 * }).render();
 * </code></pre>
 *
 * Check the list of <a href="OverlayContextPanel.html#configattributes">Configuration Attributes</a> available for
 * OverlayContextPanel.
 *
 * @param config {Object} Object literal specifying widget configuration properties.
 *
 * @class OverlayContextPanel
 * @constructor
 * @extends OverlayContext
 */
var OverlayContextPanel = A.Component.create({
    /**
     * Static property provides a string to identify the class.
     *
     * @property OverlayContextPanel.NAME
     * @type String
     * @static
     */
    NAME: CONTEXTPANEL,

    /**
     * Static property used to define the default attribute
     * configuration for the OverlayContextPanel.
     *
     * @property OverlayContextPanel.ATTRS
     * @type Object
     * @static
     */
    ATTRS: {
        /**
         * Enable or disable the animation for hide and show. Used as the
         * <a href="Anim.html">Anim</a> configuration attributes.
         *
         * <pre><code>anim: {
         *  show: {
         *  	duration: .9
         *  },
         *  hide: {
         *  	duration: .2
         *  }
         * }
         * </code></pre>
         *
         * @attribute anim
         * @default { show: false }
         * @type Object
         */
        anim: {
            lazyAdd: false,
            value: {
                show: false
            },
            setter: function(v) {
                return this._setAnim(v);
            }
        },

        /**
         * Position where the arrow will be placed. See
         * <a href="OverlayContextPanel.html#config_showArrow">showArrow</a>. If it's
         * not set, it will get the value set on the
         * <a href="OverlayContext.html#config_align">align</a> point. Here is a
         * list of valid arrows 'bc', 'bl', 'br', 'cc', 'lb', 'lc', 'lt', 'rb',
         * 'rc', 'rl'.
         *
         * @attribute arrow
         * @default null
         * @type String
         */
        arrow: {
            value: null,
            validator: isString
        },

        /**
         * See <a href="OverlayContext.html#config_hideOn">hideOn</a>.
         *
         * @attribute hideOn
         * @default click
         * @type String
         */
        hideOn: {
            value: CLICK
        },

        /**
         * See <a href="OverlayContext.html#config_showOn">showOn</a>.
         *
         * @attribute showOn
         * @default click
         * @type String
         */
        showOn: {
            value: CLICK
        },

        /**
         * If true the OverlayContextPanel will show an arrow positioned on the
         * <a href="OverlayContextPanel.html#config_arrow">arrow</a> point.
         *
         * @attribute showArrow
         * @default true
         * @type boolean
         */
        showArrow: {
            lazyAdd: false,
            value: true,
            validator: isBoolean
        },

        /**
         * Gives stacking habilities to the OverlayContextPanel.
         *
         * @attribute stack
         * @default true
         * @type boolean
         */
        stack: {
            lazyAdd: false,
            value: true,
            setter: function(v) {
                return this._setStack(v);
            },
            validator: isBoolean
        }
    },

    EXTENDS: A.OverlayContext,

    prototype: {
        /**
         * Bind the events on the OverlayContextPanel UI. Lifecycle.
         *
         * @method bindUI
         * @protected
         */
        bindUI: function() {
            var instance = this;

            instance.after('showArrowChange', instance._afterShowArrowChange);

            instance.before('show', instance._beforeShow);

            OverlayContextPanel.superclass.bindUI.apply(instance, arguments);
        },

        /**
         * Create the DOM structure for the OverlayContextPanel. Lifecycle.
         *
         * @method renderUI
         * @protected
         */
        renderUI: function() {
            var instance = this;

            instance._renderElements();
        },

        /**
         * Sync the OverlayContextPanel UI. Lifecycle.
         *
         * @method syncUI
         * @protected
         */
        syncUI: function() {
            var instance = this;

            OverlayContextPanel.superclass.syncUI.apply(instance, arguments);

            instance._syncElements();
        },

        /**
         * Aligns the OverlayContextPanel to the provided node (or viewport) using the
         * provided points. Inherited from
         * <a href="Overlay.html#method_align">Overlay</a>.
         *
         * @method align
         * @param {Node | String | null} node A reference (or selector string) for
         * the Node which with the OverlayContextPanel is to be aligned.
         * @param {Array[2]} points A two element array, specifying the points on
         * the OverlayContextPanel and node/viewport which need to be aligned.
         */
        align: function(node, points) {
            var instance = this;

            OverlayContextPanel.superclass.align.apply(this, arguments);

            instance._syncElements();
        },

        /**
         * OverlayContextPanel uses a imageless arrow, which involves some CSS technics.
         * This method is meant to fix the color of the borders of the arrow.
         *
         * @method fixPointerColor
         */
        fixPointerColor: function() {
            var instance = this;
            var contentBox = instance.get(CONTENT_BOX);
            var pointer = contentBox.one(DOT + CSS_CONTEXTPANEL_POINTER_INNER);

            pointer.removeAttribute(STYLE);

            var bColor = contentBox.getStyle(BACKGROUND_COLOR);
            var border = 'borderBottomColor';

            var right = [
     DOT + CSS_CONTEXTPANEL_ARROW + RB,
      DOT + CSS_CONTEXTPANEL_ARROW + RC,
       DOT + CSS_CONTEXTPANEL_ARROW + RL
    ]
                .join(',');

            var bottom = [
     DOT + CSS_CONTEXTPANEL_ARROW + BR,
      DOT + CSS_CONTEXTPANEL_ARROW + BC,
       DOT + CSS_CONTEXTPANEL_ARROW + BL
    ]
                .join(',');

            var left = [
     DOT + CSS_CONTEXTPANEL_ARROW + LB,
      DOT + CSS_CONTEXTPANEL_ARROW + LC,
       DOT + CSS_CONTEXTPANEL_ARROW + LT
    ]
                .join(',');

            if (contentBox.test(right)) {
                border = 'borderLeftColor';
            }
            else if (contentBox.test(bottom)) {
                border = 'borderTopColor';
            }
            else if (contentBox.test(left)) {
                border = 'borderRightColor';
            }

            pointer.setStyle(border, bColor);
        },

        /**
         * Normalize the align point value. The align point 'cc' is not a valid
         * position for the arrow and then it's normalized to the 'bc' point.
         *
         * @method getAlignPoint
         * @return {String}
         */
        getAlignPoint: function() {
            var instance = this;
            var overlayPoint = instance.get(ALIGN).points[0];

            if (overlayPoint == CC) {
                // CC is not a valid position for the arrow
                overlayPoint = BC;
            }

            return instance.get(ARROW) || overlayPoint;
        },

        /**
         * Hides the OverlayContextPanel.
         *
         * @method hide
         * @param {EventFacade} event
         */
        hide: function(event) {
            var instance = this;

            if (instance._hideAnim) {
                var visible = instance.get(VISIBLE);

                if (visible) {
                    instance._hideAnim.once(END, function() {
                        OverlayContextPanel.superclass.hide.apply(instance, arguments);
                    });

                    instance._hideAnim.run();
                }
            }
            else {
                OverlayContextPanel.superclass.hide.apply(instance, arguments);
            }
        },

        /**
         * Render DOM elements for the OverlayContextPanel.
         *
         * @method _renderElements
         * @protected
         */
        _renderElements: function() {
            var instance = this;
            var contentBox = instance.get(CONTENT_BOX);
            var align = instance.get(ALIGN);
            var overlayPoint = align.points[0];

            contentBox.addClass(CSS_STATE_DEFAULT);

            instance._pointerNode = A.Node.create(TPL_POINTER).append(TPL_POINTER_INNER);

            contentBox.append(
                instance._pointerNode
            );
        },

        /**
         * Sync the UI of the OverlayContextPanel elements.
         *
         * @method _syncElements
         * @protected
         */
        _syncElements: function() {
            var instance = this;
            var contentBox = instance.get(CONTENT_BOX);
            var pointerNode = instance._pointerNode;
            var overlayPoint = instance.getAlignPoint();

            if (instance.get(SHOW_ARROW)) {
                pointerNode.removeClass(CSS_CONTEXTPANEL_HIDDEN);
                contentBox.removeClass(CSS_CONTEXTPANEL_ARROW + instance._lastOverlayPoint);
                contentBox.addClass(CSS_CONTEXTPANEL_ARROW + overlayPoint);

                instance.fixPointerColor();
            }
            else {
                pointerNode.addClass(CSS_CONTEXTPANEL_HIDDEN);
            }

            instance._lastOverlayPoint = overlayPoint;
        },

        /**
         * Setter for the
         * <a href="OverlayContextPanel.html#config_stack">stack</a> attribute.
         *
         * @method _setStack
         * @param {boolean} value
         * @protected
         * @return {boolean}
         */
        _setStack: function(value) {
            var instance = this;

            if (value) {
                A.OverlayContextPanelManager.register(instance);
            }
            else {
                A.OverlayContextPanelManager.remove(instance);
            }

            return value;
        },

        /**
         * Setter for the
         * <a href="OverlayContextPanel.html#config_anim">anim</a> attribute.
         *
         * @method _setAnim
         * @param {Object} value
         * @protected
         * @return {Object}
         */
        _setAnim: function(value) {
            var instance = this;
            var boundingBox = instance.get(BOUNDING_BOX);

            if (value) {
                var defaults = {
                    node: boundingBox,
                    duration: 0.1
                };

                var showOptions = A.merge(defaults, {
                    from: {
                        opacity: 0
                    },
                    to: {
                        opacity: 1
                    }
                });

                var hideOptions = A.merge(defaults, {
                    from: {
                        opacity: 1
                    },
                    to: {
                        opacity: 0
                    }
                });

                if (isObject(value)) {
                    // loading user settings for animation
                    showOptions = A.merge(showOptions, value.show);
                    hideOptions = A.merge(hideOptions, value.hide);
                }

                instance._showAnim = new A.Anim(showOptions);
                instance._hideAnim = new A.Anim(hideOptions);

                // if anim.show or anim.hide === false, cancel respective animation
                if (isObject(value)) {
                    if (value.show === false) {
                        instance._showAnim = null;
                    }

                    if (value.hide === false) {
                        instance._hideAnim = null;
                    }
                }
            }

            return value;
        },

        /**
         * Fires before show the OverlayContextPanel.
         *
         * @method _beforeShow
         * @param {EventFacade} event
         * @protected
         */
        _beforeShow: function(event) {
            var instance = this;
            var boundingBox = instance.get(BOUNDING_BOX);
            var visible = instance.get(VISIBLE);

            if (!visible && instance._showAnim) {
                boundingBox.setStyle(OPACITY, 0);

                instance._showAnim.run();
            }
            else {
                boundingBox.setStyle(OPACITY, 1);
            }
        },

        /**
         * Fires after showArrow attribute changes.
         *
         * @method _afterShowArrowChange
         * @param {EventFacade} event
         * @protected
         */
        _afterShowArrowChange: function() {
            var instance = this;

            instance._syncElements();
        }
    }
});

A.OverlayContextPanel = OverlayContextPanel;

/**
 * A base class for OverlayContextPanelManager:
 *
 * @param config {Object} Object literal specifying widget configuration properties.
 *
 * @class OverlayContextPanelManager
 * @constructor
 * @extends OverlayManager
 * @static
 */
A.OverlayContextPanelManager = new A.OverlayManager({
    zIndexBase: 1000
});


}, '3.1.0-deprecated.110', {"requires": ["anim", "aui-overlay-context-deprecated"], "skinnable": true});
