YUI.add('aui-button-item-deprecated', function (A, NAME) {

/**
 * The ButtonItem Utility
 *
 * @module aui-button-item
 */

var Lang = A.Lang,
    isString = Lang.isString,

    getClassName = A.getClassName,

    NAME = 'buttonitem',

    BOUNDING_BOX = 'boundingBox',
    BUTTON = 'button',
    CONTENT_BOX = 'contentBox',
    DOT = '.',
    HANDLER = 'handler',
    ICON = 'icon',
    ICON_NODE = 'iconNode',
    LABEL = 'label',
    LABEL_NODE = 'labelNode',
    ONLY = 'only',
    RESET = 'reset',
    STATE = 'state',
    SUBMIT = 'submit',
    TITLE = 'title',
    TYPE = 'type',

    CSS_BUTTON = getClassName(NAME),
    CSS_BUTTON_ICON = getClassName(NAME, ICON),
    CSS_BUTTON_LABEL = getClassName(NAME, LABEL),

    CSS_BUTTON_ICON_LABEL = getClassName(NAME, ICON, LABEL),
    CSS_BUTTON_ICON_ONLY = getClassName(NAME, ICON, ONLY),
    CSS_BUTTON_LABEL_ONLY = getClassName(NAME, LABEL, ONLY),

    CSS_ICON = getClassName(ICON),

    REGEX_ICON = new RegExp(CSS_ICON + '-([a-zA-Z0-9-]+)'),

    TPL_BUTTON = '<button type="{0}"></button>',
    TPL_ICON = '<span class="' + [CSS_BUTTON_ICON, CSS_ICON].join(' ') + '"></span>',
    TPL_LABEL = '<span class="' + CSS_BUTTON_LABEL + '"></span>';

/**
 * A base class for ButtonItem, providing:
 * <ul>
 *    <li>Widget Lifecycle (initializer, renderUI, bindUI, syncUI, destructor)</li>
 *    <li>An optional icon or label</li>
 *    <li>Managed user interaction states (default, active, hover)</li>
 *    <li>Keyboard accessible</li>
 * </ul>
 *
 * Quick Example:<br/>
 *
 * <pre><code>var instance = new A.ButtonItem({
 *	icon: 'gear',
 * label: 'Configuration'
 * }).render();
 * </code></pre>
 *
 * Check the list of <a href="ButtonItem.html#configattributes">Configuration Attributes</a> available for
 * ButtonItem.
 *
 * @param config {Object} Object literal specifying widget configuration properties.
 *
 * @class ButtonItem
 * @constructor
 * @extends Component
 * @uses WidgetChild
 */

var ButtonItem = A.Component.create({
    /**
     * Static property provides a string to identify the class.
     *
     * @property ButtonItem.NAME
     * @type String
     * @static
     */

    NAME: NAME,

    /**
     * Static property provides an array to specify which classes augment this one.
     *
     * @property ButtonItem.AUGMENTS
     * @type array
     * @static
     */

    AUGMENTS: [A.WidgetChild],

    /**
     * Static property used to define the default attribute
     * configuration for the ButtonItem.
     *
     * @property ButtonItem.ATTRS
     * @type Object
     * @static
     */

    ATTRS: {
        /**
         * Whether to track the active state of the button.
         *
         * @attribute activeState
         * @default false
         * @type Boolean
         */
        activeState: {
            value: false
        },

        /**
         * An object map of the CSS class names to use for the different interaction states.
         *
         * @attribute classNames
         * @type Object
         */
        classNames: {},

        /**
         * Whether to apply the default interaction state to the button
         *
         * @attribute defaultState
         * @default true
         * @type Boolean
         */
        defaultState: {},

        /**
         * An event callback to handle when a user interacts with the button.
         * This can either be a function that will be attached on click, or
         * an object map that accepts the following keys:
         * <code>{fn: // The function to execute
         * context: // The context to execute the function in
         * type: // The type of event to listen for (defaults to "click")
         * }</code>
         *
         * @attribute handler
         * @default false
         * @type Function | Object
         */
        handler: {
            lazyAdd: false,
            value: null
        },

        /**
         * Whether to track the hover interaction state of the button.
         *
         * @attribute hoverState
         * @default true
         * @type Boolean
         */
        hoverState: {},

        /**
         * The icon to use inside of the button. Possible values are:
         *
         * @attribute icon
         * @type String
         */
        icon: {
            value: ''
        },

        /**
         * DOM Node to display the icon of the ButtonItem. If not
         * specified try to query using HTML_PARSER an element inside
         * boundingBox which matches <code>aui-button-icon</code>.
         *
         * @attribute iconNode
         * @default Generated div element.
         * @type String
         */
        iconNode: {
            valueFn: function() {
                return A.Node.create(TPL_ICON);
            }
        },

        /**
         * An id that can be used to identify a button.
         *
         * @attribute hoverState
         * @type Boolean
         */
        id: {
            valueFn: function() {
                return A.guid();
            }
        },

        /**
         * Text to use inside of the button.
         *
         * @attribute label
         * @type String
         */
        label: {
            value: ''
        },

        /**
         * DOM Node to display the text of the ButtonItem. If not
         * specified try to query using HTML_PARSER an element inside
         * boundingBox which matches <code>aui-button-label</code>.
         *
         * @attribute labelNode
         * @default Generated div element.
         * @type String
         */
        labelNode: {
            valueFn: function() {
                return A.Node.create(TPL_LABEL);
            }
        },

        /**
         * Text to use as the title attribute of the button.
         *
         * @attribute title
         * @type String
         */
        title: {
            setter: '_setTitle',
            value: false
        },

        /**
         * Button type.
         *
         * @attribute type
         * @default button
         * @type String
         */
        type: {
            validator: function(val) {
                return (val === BUTTON || val === SUBMIT || val === RESET);
            },
            value: BUTTON
        }
    },

    /**
     * Object hash, defining how attribute values are to be parsed from
     * markup contained in the widget's content box.
     *
     * @property ButtonItem.HTML_PARSER
     * @type Object
     * @static
     */
    HTML_PARSER: {
        iconNode: function(srcNode) {
            return srcNode.one(DOT + CSS_BUTTON_ICON);
        },
        labelNode: function(srcNode) {
            return srcNode.one(DOT + CSS_BUTTON_LABEL);
        },
        icon: function(srcNode) {
            var iconNode = srcNode.one(DOT + CSS_BUTTON_ICON);

            if (iconNode) {
                this.set(ICON_NODE, iconNode);
                var cssClass = iconNode.attr('class');

                var match = cssClass.match(REGEX_ICON);

                return match && match[1];
            }
        },
        label: function(srcNode) {
            var labelNode = srcNode.one(DOT + CSS_BUTTON_LABEL);

            if (labelNode) {
                this.set(LABEL_NODE, labelNode);

                return labelNode.text();
            }
        }
    },

    constructor: function(config) {
        var instance = this;

        var buttonType = 'button';

        if (config) {
            if (isString(config)) {
                config = {
                    icon: config
                };
            }
            else if (config.type) {
                buttonType = config.type;
            }
        }

        instance.BOUNDING_TEMPLATE = Lang.sub(TPL_BUTTON, [buttonType]);

        ButtonItem.superclass.constructor.call(instance, config);
    },

    UI_ATTRS: [HANDLER, ICON, LABEL, TITLE, TYPE],

    prototype: {
        BOUNDING_TEMPLATE: TPL_BUTTON,
        CONTENT_TEMPLATE: null,

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

            instance._renderStates();
            instance._renderIconNode();
            instance._renderLabelNode();
        },

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

            var icon = instance.get('icon');
            var label = instance.get('label');
            var title = instance.get('title');

            if (icon) {
                instance._uiSetIcon(icon);
            }

            if (label) {
                instance._uiSetLabel(label);
            }

            if (title) {
                instance._uiSetTitle(title);
            }
        },

        /**
         * Renders the underlying markup for the <a href="ButtonItem.html#config_icon">icon</a>.
         *
         * @method _renderIconNode
         * @protected
         * @return {Node}
         */
        _renderIconNode: function() {
            var instance = this;

            instance.get(CONTENT_BOX).append(
                instance.get(ICON_NODE)
            );
        },

        /**
         * Renders the underlying markup for the <a href="ButtonItem.html#config_label">label</a>.
         *
         * @method _renderLabelNode
         * @protected
         * @return {Node}
         */
        _renderLabelNode: function() {
            var instance = this;

            instance.get(CONTENT_BOX).append(
                instance.get(LABEL_NODE)
            );
        },

        /**
         * Retrieves the state value from either the current instance, or if defined, the
         * parent widget.
         *
         * @method _getState
         * @param {String} key The state name to retrieve
         * @param {Object} parent The parent widget to attempt to retrieve the state from
         * @protected
         * @return {Object}
         */
        _getState: function(key, parent) {
            var instance = this;

            var value = instance.get(key);

            var state = value;

            if (parent) {
                value = parent.get(key);

                if (!Lang.isUndefined(value)) {
                    state = value;
                }
            }

            return state;
        },

        /**
         * Attaches state interaction management to the widget.
         *
         * @method _renderStates
         * @param {EventFacade} event
         * @protected
         */
        _renderStates: function(event) {
            var instance = this;

            var parent = instance.get('parent');

            var activeState = instance._getState('activeState', parent);
            var classNames = instance._getState('classNames', parent);
            var defaultState = instance._getState('defaultState', parent);
            var hoverState = instance._getState('hoverState', parent);

            instance.plug(
                A.Plugin.StateInteraction, {
                    activeState: activeState,
                    classNames: classNames,
                    defaultState: defaultState,
                    hoverState: hoverState
                }
            );
        },

        /**
         * Setter for the title attribute
         *
         * @method _setTitle
         * @protected
         */
        _setTitle: function(value) {
            var instance = this;

            if (value === null) {
                value = instance.get('label');
            }
            else if (value === false) {
                value = '';
            }

            return String(value);
        },

        /**
         * Syncs the boundingBox class names to reflect whether the children only have icons or labels or both.
         *
         * @method _syncChildrenStates
         * @protected
         */
        _syncChildrenStates: function() {
            var instance = this;

            var icon = instance.get('icon');
            var label = instance.get('label');

            var hasIconAndLabel = (icon && label);
            var hasLabelOnly = (!icon && label);
            var hasIconOnly = (icon && !label);

            var boundingBox = instance.get(BOUNDING_BOX);

            boundingBox.toggleClass(CSS_BUTTON_ICON_LABEL, hasIconAndLabel);
            boundingBox.toggleClass(CSS_BUTTON_ICON_ONLY, hasIconOnly);
            boundingBox.toggleClass(CSS_BUTTON_LABEL_ONLY, hasLabelOnly);
        },

        _uiSetDisabled: function(val) {
            var instance = this,
                boundingBox = instance.get(BOUNDING_BOX);

            if (val) {
                boundingBox.attr('disabled', 'disabled');
            }
            else {
                boundingBox.removeAttribute('disabled');
            }

            A.ButtonItem.superclass._uiSetDisabled.apply(instance, arguments);
        },

        /**
         * Updates the UI for the icon in response to the <a href="ButtonItem.html#event_HandlerChange">Handler</a> event.
         *
         * @method _uiSetHandler
         * @param {String} val Handler name
         * @protected
         */
        _uiSetHandler: function(value) {
            var instance = this;

            var fn = value;
            var parent = instance.get('parent');
            var context = (parent && parent._DEFAULT_CONTEXT) || instance._DEFAULT_CONTEXT || instance;

            var type = 'click';

            var args = instance;
            var customArgs;

            if (Lang.isObject(fn)) {
                var handlerConfig = fn;

                fn = handlerConfig.fn || fn;
                context = handlerConfig.context || context;
                type = handlerConfig.type || type;

                customArgs = handlerConfig.args;
            }

            if (Lang.isFunction(fn)) {
                var interactionHandle = instance._interactionHandle;

                if (interactionHandle) {
                    interactionHandle.detach();
                }

                var boundFn = A.rbind.apply(A, [fn, context, args].concat(customArgs || []));

                instance._interactionHandle = instance.on(
                    type,
                    function() {
                        if (!instance.get('disabled')) {
                            boundFn.apply(this, arguments);
                        }
                    }
                );
            }
        },

        /**
         * Updates the UI for the icon in response to the <a href="ButtonItem.html#event_iconChange">iconChange</a> event.
         *
         * @method _uiSetIcon
         * @param {String} val Icon name
         * @protected
         */
        _uiSetIcon: function(val) {
            var instance = this;

            var iconNode = instance.get(ICON_NODE);

            var action = 'show';

            if (!val) {
                action = 'hide';
            }

            val = getClassName(ICON, val);

            iconNode.replaceClass(instance._iconPrevVal, val);

            iconNode[action]();

            instance._syncChildrenStates();

            instance._iconPrevVal = val;
        },

        /**
         * Updates the UI for the label in response to the <a href="ButtonItem.html#event_labelChange">labelChange</a> event.
         *
         * @method _uiSetLabel
         * @param {String} val The new value
         * @protected
         */
        _uiSetLabel: function(val) {
            var instance = this;

            var labelNode = instance.get(LABEL_NODE);

            var action = 'show';

            if (!val) {
                action = 'hide';
            }

            labelNode.text(val);

            labelNode[action]();

            instance._syncChildrenStates();
        },

        /**
         * Updates the UI for the title in response to the <a href="ButtonItem.html#event_titleChange">titleChange</a> event.
         *
         * @method _uiSetTitle
         * @param {String} val The new value
         * @protected
         */
        _uiSetTitle: function(val) {
            var instance = this;

            var boundingBox = instance.get(BOUNDING_BOX);

            boundingBox.setAttribute(TITLE, val);
        },

        /**
         * Updates the UI for the type in response to the <a href="ButtonItem.html#event_typeChange">typeChange</a> event.
         *
         * @method _uiSetType
         * @param {String} val The new value
         * @protected
         */
        _uiSetType: function(val) {
            var instance = this;

            var boundingBox = instance.get(BOUNDING_BOX);

            boundingBox.setAttribute(TYPE, val);
        }
    }
});

A.ButtonItem = ButtonItem;


}, '3.1.0-deprecated.110', {
    "requires": [
        "aui-base-deprecated",
        "aui-state-interaction-deprecated",
        "widget-child"
    ],
    "skinnable": true
});
