# Source: ui/base/abstract-radio-button.js

    /*global require, exports, document, Error*/
    var AbstractControl = require("./abstract-control").AbstractControl,
        PressComposer = require("../../composer/press-composer").PressComposer,
        KeyComposer = require("../../composer/key-composer").KeyComposer;

    var CLASS_MONTAGE_DISABLED = "montage--disabled",
        CLASS_MONTAGE_ACTIVE = "montage--active",
        CLASS_MONTAGE_CHECKED = "montage-RadioButton--checked";

    /**
     * @class AbstractRadioButton
     * @classdesc Provides common implementation details for radio buttons.
     * @extends AbstractControl
     */
    var AbstractRadioButton = exports.AbstractRadioButton = AbstractControl.specialize(
        /** @lends AbstractRadioButton# */
    {

        /**
         * Dispatched when the radio button is activated through a mouse click,
         * finger tap, or when focused and the spacebar is pressed.
         * @event action
         * @memberof AbstractRadioButton
         * @param {Event} event
         */

        constructor: {
            value: function AbstractRadioButton() {
                if(this.constructor === AbstractRadioButton) {
                    throw new Error("AbstractRadioButton cannot be instantiated.");
                }
            }
        },

        /**
         * Whether the user is pressing the radio button.
         * @type {boolean}
         */
        _active: {
            value: false
        },

        active: {
            set: function (_active) {
                _active = !!_active;

                if (this._active !== _active) {
                    this._active = _active;

                    if (_active) {
                        this.classList.add(this.activeClass);
                    } else {
                        this.classList.remove(this.activeClass);
                    }
                }
            },
            get: function () {
                return this._active;
            }
        },

        _checked: {
            value: null
        },

        /**
         * Whether this radio button is checked.
         * @type {boolean}
         */
        checked: {
            set: function (_checked) {
                _checked = !!_checked;

                if (this._checked !== _checked) {
                    this._checked = _checked;

                    if (_checked) {
                        this.classList.add(this.checkedClass);
                    } else {
                        this.classList.remove(this.checkedClass);
                    }
                }
            },
            get: function () {
                return this._checked;
            }
        },

        _disabledClass: {
            value: null
        },

        disabledClass: {
            set: function (_disabledClass) {
                var previousClass = this.disabledClass; // need to call the getter

                if (_disabledClass && typeof _disabledClass === "string" && previousClass !== _disabledClass) {
                    this._swapClassNameIfNeeded(previousClass, _disabledClass);
                    this._disabledClass = _disabledClass;
                }
            },
            get: function () {
                return this._disabledClass || CLASS_MONTAGE_DISABLED;
            }
        },

        _activeClass: {
            value: null
        },

        activeClass: {
            set: function (_activeClass) {
                var previousClass = this.activeClass; // need to call the getter

                if (_activeClass && typeof _activeClass === "string" && previousClass !== _activeClass) {
                    this._swapClassNameIfNeeded(previousClass, _activeClass);
                    this._activeClass = _activeClass;
                }
            },
            get: function () {
                return this._activeClass || CLASS_MONTAGE_ACTIVE;
            }
        },

        _checkedClass: {
            value: null
        },

        checkedClass: {
            set: function (_checkedClass) {
                var previousClass = this.checkedClass; // need to call the getter

                if (_checkedClass && typeof _checkedClass === "string" && previousClass !== _checkedClass) {
                    this._swapClassNameIfNeeded(previousClass, _checkedClass);
                    this._checkedClass = _checkedClass;
                }
            },
            get: function () {
                return this._checkedClass || CLASS_MONTAGE_CHECKED;
            }
        },

        _swapClassNameIfNeeded: {
            value: function (_previous, _new) {
                if (_previous && _new && this.classList.has(_previous)) {
                    this.classList.remove(_previous);
                    this.classList.add(_new);
                }
            }
        },

        /**
         * Whether this radio button is enabled.
         * @type {boolean}
         */
        _enabled: {
            value: true
        },

        enabled: {
            set: function (_enabled) {
                _enabled = !!_enabled;

                if (this._enabled !== _enabled) {
                    this._enabled = _enabled;

                    if (!_enabled) {
                        this.classList.add(this.disabledClass);
                    } else {
                        this.classList.remove(this.disabledClass);
                    }
                }
            },
            get: function () {
                return this._enabled;
            }
        },

        __keyComposer: {
            value: null
        },

        _keyComposer: {
            get: function () {
                if (!this.__keyComposer) {
                    this.__keyComposer = new KeyComposer();
                    this.__keyComposer.keys = "space";
                    this.addComposer(this.__keyComposer);
                }

                return this.__keyComposer;
            }
        },

        _radioButtonController: {
            value: null
        },

        /**
         * The radio button controller that ensures that only one radio button in
         * its `content` is `checked` at any time.
         * @type {RadioButtonController}
         */
        radioButtonController: {
            set: function (value) {
                if (this._radioButtonController) {
                    this._radioButtonController.unregisterRadioButton(this);
                }
                this._radioButtonController = value;
                value.registerRadioButton(this);
            },
            get: function () {
                return this._radioButtonController;
            }
        },

        __pressComposer: {
            value: null
        },

        _pressComposer: {
            get: function () {
                if (!this.__pressComposer) {
                    this.__pressComposer = new PressComposer();
                    this.addComposer(this.__pressComposer);
                }

                return this.__pressComposer;
            }
        },

        enterDocument: {
            value: function (firstTime) {
                if (firstTime) {
                    this.element.setAttribute("role", "radio");
                }
            }
        },

        draw: {
            value: function () {
                if (this.checked) {
                    this.element.setAttribute("aria-checked", "true");
                } else {
                    this.element.setAttribute("aria-checked", "false");
                }
            }
        },

        handlePressStart: {
            value: function (event) {
                this.active = true;

                if (event.touch) {
                    // Prevent default on touchmove so that if we are inside a scroller,
                    // it scrolls and not the webpage
                    document.addEventListener("touchmove", this, false);
                }
            }
        },

        check: {
            value: function () {
                if (!this.enabled || this.checked) {
                    return;
                }

                this.dispatchActionEvent();
                this.checked = true;
            }
        },

        /**
         Handle press event from press composer
         */
        handlePress: {
            value: function (/* event */) {
                this.active = false;
                this.check();
            }
        },

        /**
         Called when all interaction is over.
         @private
         */
        handlePressCancel: {
            value: function (/* event */) {
                this.active = false;
                document.removeEventListener("touchmove", this, false);
            }
        },

        handleKeyPress: {
            value: function () {
                this.active = true;
            }
        },

        handleKeyRelease: {
            value: function () {
                this.active = false;
                this.check();
            }
        },

        prepareForActivationEvents: {
            value: function () {
                this._keyComposer.addEventListener("keyPress", this, false);
                this._keyComposer.addEventListener("keyRelease", this, false);

                this._pressComposer.addEventListener("pressStart", this, false);
                this._pressComposer.addEventListener("press", this, false);
                this._pressComposer.addEventListener("pressCancel", this, false);
            }
        },

        activate: {
            value: function () {
                this.check();
            }
        }
    });