/**
 * A checkable menu item that participates in a `group` of mutually exclusive items.
 *
 * Radio items must be a assigned to a `{@link #cfg!group group}` and only one member of
 * that group is allowed to be checked. The owning `{@link Ext.menu.Menu menu}` provides
 * the `{@link Ext.menu.Menu#cfg!groups groups}` config to assist in managing the state
 * of its radio items.
 *
 * ```javascript
 * @example({ framework: 'extjs' })
 * Ext.Viewport.add({
 *     xtype: 'container',
 *     items: [{
 *         xtype: 'button',
 *         bind: 'Call {menuGroups.option}',
 *
 *         viewModel: {
 *             data: {
 *                 menuGroups: {
 *                     option: 'home'
 *                 }
 *             }
 *         },
 *
 *         menu: {
 *             bind: {
 *                 groups: '{menuGroups}'
 *             },
 *             items: [{
 *                 text: 'Home',
 *                 group: 'option',  // causes Menu to create this class of item
 *                 value: 'home'
 *             }, {
 *                 text: 'Work',
 *                 group: 'option',
 *                 value: 'work'
 *             }, {
 *                 text: 'Mobile',
 *                 group: 'option',
 *                 value: 'mobile'
 *             }]
 *         }
 *     }]
 * });
 * ```
 * ```javascript
 * @example({framework: 'ext-react', packages:['ext-react']})
 * import React, { Component } from 'react';
 * import { ExtButton, ExtContainer, ExtMenu, ExtMenuRadioItem } from '@sencha/ext-react';
 *
 * export default class MyExample extends Component {
 *     render() {
 *         return (
 *            <ExtContainer>
 *                <ExtButton text="Menu">
 *                    <ExtMenu rel="menu" >
 *                        <ExtMenuRadioItem text="Mobile" name="ui-type" />
 *                        <ExtMenuRadioItem text="Desktop" name="ui-type"/>
 *                    </ExtMenu>
 *                </ExtButton>
 *            </ExtContainer>
 *         )
 *     }
 * }
 * ```
 * ```javascript
 * @example({framework: 'ext-angular', packages:['ext-angular']})
 * import { Component } from '@angular/core'
 * declare var Ext: any;
 * @Component({
 *    selector: 'app-root',
 *    styles: [``],
 *    template: `
 *       <ExtContainer>
 *           <ExtButton text="Menu">
 *               <ExtMenu rel="menu" >
 *                   <ExtMenuRadioItem text="Mobile" name="ui-type"
 *                      group="group1">
 *                   </ExtMenuRadioItem>
 *                   <ExtMenuRadioItem text="Desktop" name="ui-type"
 *                      group="group1">
 *                   </ExtMenuRadioItem>
 *               </ExtMenu>
 *           </ExtButton>
 *       </ExtContainer>
 *    `
 * })
 * export class AppComponent {} 
 * ```
 * ```html
 * @example({framework: 'ext-web-components', packages:['ext-web-components'], tab: 1 })
 * <ext-container>
 *    <ext-button text="Menu">
 *        <ext-menu rel="menu" >
 *            <ext-menuradioitem text="Mobile" group="options" name="ui-type" ></ext-menuradioitem>
 *            <ext-menuradioitem text="Desktop" group="options" name="ui-type"><ext-menuradioitem>
 *        </ext-menu>
 *    </ext-button>
 * </ext-container>
 * ```
 * ```javascript
 * @example({framework: 'ext-web-components', packages:['ext-web-components'], tab: 2 })
 * import '@sencha/ext-web-components/dist/ext-container.component';
 * import '@sencha/ext-web-components/dist/ext-button.component';
 * import '@sencha/ext-web-components/dist/ext-menu.component';
 * import '@sencha/ext-web-components/dist/ext-menuradioitem.component';
 *
 * export default class RadioItemComponent {} 
 *
 * @since 6.5.0
 */
Ext.define('Ext.menu.RadioItem', {
    extend: 'Ext.menu.CheckItem',
    xtype: 'menuradioitem',
 
    classCls: Ext.baseCSSPrefix + 'menuradioitem',
 
    nameable: true,
    shareableName: true,
 
    ariaRole: 'menuitemradio',
 
    /**
     * @cfg {String} name
     * This config is used internally by the {@link #cfg!group} config and should not be set.
     */
 
    config: {
        /**
         * @cfg {String} group (required)
         * Name of a radio group that the item belongs.
         *
         * This assigns a common name to several RadioItems to allow selection of a single value.
         *
         * Note that the group name is local to the owning Menu.
         */
        group: null,
 
        /**
         * @cfg {Boolean} [allowUncheck=false]
         * By default, as in native RadioGroups, a checked radio item cannot be unchecked
         * by the UI. Set this to `true` to allow unchecking of checked RadioItems.
         */
        allowUncheck: null
    },
 
    //<debug>
    initialize: function() {
        if (!this.getGroup()) {
            Ext.raise('Menu RadioItems must be configured with a group');
        }
 
        this.callParent();
    },
    //</debug>
 
    privates: {
        onSpace: function(e) {
            // Veto uncheck for radio items.
            if (this.checkboxElement.dom.checked) {
                e.preventDefault();
            }
        },
 
        updateGroup: function(group) {
            // Inheritable will update the NameHolder upon add.
            this.name = group;
        },
 
        onCheckboxChange: function() {
            var checkboxElement = this.checkboxElement.dom,
                isChecked = checkboxElement.checked;
 
            // If the DOM is insync with the config state, we are good, there's nothng to do.
            if (isChecked === this.getChecked() || this.getDisabled()) {
                return;
            }
 
            // The change event only fires in response to UI changes.
            // And the UI is not allowed to UNcheck radio items.
            // So immediately reverse the setting before the event propagates.
            // We do not take over the click event, and control programatically  because:
            // 1. We want interaction to be native wherever possible for accessibility reasons.
            // 2. The click events fires after the change on some platforms so we have no control.
            // 3. We'd also have to handle keystroke accessibility.
            if (!isChecked && !this.getAllowUncheck()) {
                checkboxElement.checked = true;
            }
            // Sync our widget state with the reality of the accessible checkbox field.
            else {
                this.callParent();
            }
        },
 
        onCheckChange: function() {
            var me = this,
                checkboxElement = me.checkboxElement.dom,
                parentMenu = me.getParent(),
                name, groups, siblings, len, i;
 
            // Forces the group config to be read and pushed into the name property
            me.getGroup();
            name = me.name;
 
            // Sync state of all siblings in group via the parent menu *before* we call parent.
            // State must be correct.
            if (name && parentMenu && !parentMenu.updatingGroups) {
                groups = {};
 
                if (checkboxElement.checked) {
                    groups[name] = me.getValue();
                    parentMenu.setGroups(groups);
                }
                // Now we have to see if our group has become all unchecked
                // and potentially declare our group value as null.
                else {
                    siblings = parentMenu.lookupName(name);
                    len = siblings && siblings.length;
 
                    for (= 0; i < len && !siblings[i].checkboxElement.dom.checked; i++) {
                        // just loop
                    }
 
                    // If we ran out the end of the loop without finding a check item,
                    // or we are in the config phase, and the menu has no items by that name,
                    // we set the group's value to null.
                    // If we are in the config phase, the parent menu just accumulates the
                    // group values silently, it does not fire the groupchange event, or
                    // publish the groups object.
                    if (=== len) {
                        groups[name] = null;
                        parentMenu.setGroups(groups);
                    }
                }
            }
 
            me.callParent();
        }
    }
});