/**
 * A Button Widget
 *
 * @module button
 * @since 3.5.0
 */

var ButtonCore = Y.ButtonCore,
    CLASS_NAMES = ButtonCore.CLASS_NAMES,
    ARIA_STATES = ButtonCore.ARIA_STATES,
    ARIA_ROLES = ButtonCore.ARIA_ROLES;

/**
 * Creates a Button
 *
 * @class Button
 * @extends Widget
 * @uses ButtonCore
 * @param config {Object} Configuration object
 * @constructor
 */
function Button() {
    Button.superclass.constructor.apply(this, arguments);
}

/* Button extends Widget */
Y.extend(Button, Y.Widget,  {

    // Y.Button prototype properties

    /**
     * Bounding box template that will contain the Button's DOM subtree.
     *
     * @property BOUNDING_TEMPLATE
     * @type {String}
     * @default <button/>
     */
    BOUNDING_TEMPLATE : ButtonCore.prototype.TEMPLATE,

    /**
     * Content box template
     *
     * @property CONTENT_TEMPLATE
     * @type {String}
     * @default null
     */
    CONTENT_TEMPLATE : null

}, {

    // Y.Button static properties

    /**
     * The identity of the widget.
     *
     * @property NAME
     * @type String
     * @default 'button'
     * @readOnly
     * @protected
     * @static
     */
    NAME: ButtonCore.NAME,

    /**
     * Static property used to define the default attribute configuration of
     * the Widget.
     *
     * @property ATTRS
     * @type {Object}
     * @protected
     * @static
     */
    ATTRS: ButtonCore.ATTRS,

    /**
     * The text of the button's label
     *
     * @attribute label
     * @type String
     */

    /**
     * The HTML of the button's label
     *
     * This attribute accepts HTML and inserts it into the DOM **without**
     * sanitization.  This attribute should only be used with HTML that has
     * either been escaped (using `Y.Escape.html`), or sanitized according to
     * the requirements of your application.
     *
     * If all you need is support for text labels, please use the `label`
     * attribute instead.
     *
     * @attribute labelHTML
     * @type HTML
     */

    /**
     * @property HTML_PARSER
     * @type {Object}
     * @protected
     * @static
     */
    HTML_PARSER: {
        labelHTML: ButtonCore._getHTMLFromNode,
        disabled: ButtonCore._getDisabledFromNode
    },

    /**
     * List of class names used in the Button's DOM
     *
     * @property CLASS_NAMES
     * @type Object
     * @static
     */
    CLASS_NAMES: CLASS_NAMES
});

Y.mix(Button.prototype, ButtonCore.prototype);

/**
 * Creates a ToggleButton
 *
 * @class ToggleButton
 * @extends Button
 * @param config {Object} Configuration object
 * @constructor
 */
function ToggleButton() {
    Button.superclass.constructor.apply(this, arguments);
}

// TODO: move to ButtonCore subclass to enable toggle plugin, widget, etc.
/* ToggleButton extends Button */
Y.extend(ToggleButton, Button,  {

    /**
     *
     *
     * @property trigger
     * @type {String}
     * @default
     */
    trigger: 'click',

    /**
     *
     *
     * @property selectedAttrName
     * @type {String}
     * @default
     */
    selectedAttrName: '',

    /**
     *
     * @method initializer
     */
    initializer: function (config) {
        var button = this,
            type = button.get('type'),
            selectedAttrName = (type === "checkbox" ? 'checked' : 'pressed'),
            selectedState = config[selectedAttrName] || false;

        // Create the checked/pressed attribute
        button.addAttr(selectedAttrName, {
            value: selectedState
        });

        button.selectedAttrName = selectedAttrName;
    },

    /**
     *
     * @method destructor
     */
    destructor: function () {
        delete this.selectedAttrName;
    },

    /**
     * @method bindUI
     * @description Hooks up events for the widget
     */
    bindUI: function() {
         var button = this,
             cb = button.get('contentBox');

        ToggleButton.superclass.bindUI.call(button);

        cb.on(button.trigger, button.toggle, button);
        button.after(button.selectedAttrName + 'Change', button._afterSelectedChange);
    },

    /**
     * @method syncUI
     * @description Syncs the UI for the widget
     */
    syncUI: function() {
        var button = this,
            cb = button.get('contentBox'),
            type = button.get('type'),
            ROLES = ToggleButton.ARIA_ROLES,
            role = (type === 'checkbox' ? ROLES.CHECKBOX : ROLES.TOGGLE),
            selectedAttrName = button.selectedAttrName;

        ToggleButton.superclass.syncUI.call(button);

        cb.set('role', role);
        button._uiSetSelected(button.get(selectedAttrName));
    },

    /**
     * @method _afterSelectedChange
     * @private
     */
    _afterSelectedChange: function(e){
        this._uiSetSelected(e.newVal);
    },

    /**
     * @method _uiSetSelected
     * @private
     */
    _uiSetSelected: function(value) {
        var button = this,
            cb = button.get('contentBox'),
            STATES = ToggleButton.ARIA_STATES,
            type = button.get('type'),
            ariaState = (type === 'checkbox' ? STATES.CHECKED : STATES.PRESSED);

        cb.toggleClass(Button.CLASS_NAMES.SELECTED, value);
        cb.set(ariaState, value);
    },

    /**
     * @method toggle
     * @description Toggles the selected/pressed/checked state of a ToggleButton
     * @public
     */
    toggle: function() {
        var button = this;
        button._set(button.selectedAttrName, !button.get(button.selectedAttrName));
    }

}, {

    /**
     * The identity of the widget.
     *
     * @property NAME
     * @type {String}
     * @default 'buttongroup'
     * @readOnly
     * @protected
     * @static
     */
    NAME: 'toggleButton',

    /**
     * Static property used to define the default attribute configuration of
     * the Widget.
     *
     * @property ATTRS
     * @type {Object}
     * @protected
     * @static
     */
    ATTRS: {

       /**
        *
        *
        * @attribute type
        * @type String
        */
        type: {
            value: 'toggle',
            writeOnce: 'initOnly'
        }
    },

    /**
     * @property HTML_PARSER
     * @type {Object}
     * @protected
     * @static
     */
    HTML_PARSER: {
        checked: function(node) {
            return node.hasClass(CLASS_NAMES.SELECTED);
        },
        pressed: function(node) {
            return node.hasClass(CLASS_NAMES.SELECTED);
        }
    },

    /**
     * @property ARIA_STATES
     * @type {Object}
     * @protected
     * @static
     */
    ARIA_STATES: ARIA_STATES,

    /**
     * @property ARIA_ROLES
     * @type {Object}
     * @protected
     * @static
     */
    ARIA_ROLES: ARIA_ROLES,

    /**
     * Array of static constants used to identify the classnames applied to DOM nodes
     *
     * @property CLASS_NAMES
     * @type Object
     * @static
     */
    CLASS_NAMES: CLASS_NAMES

});

// Export
Y.Button = Button;
Y.ToggleButton = ToggleButton;
