/**
 * A split button that provides a built-in dropdown arrow that can fire an event separately from the default click event
 * of the button. Typically this would be used to display a dropdown menu that provides additional options to the
 * primary button action, but any custom handler can provide the arrowclick implementation.  Example usage:
 *
 *     @example
 *     // display a dropdown menu:
 *     Ext.create('Ext.SplitButton', {
 *         renderTo: Ext.getBody(),
 *         text: 'Options',
 *         // handle a click on the button itself
 *         handler: function() {
 *             alert("The button was clicked");
 *         },
 *         menu: new Ext.menu.Menu({
 *             items: [
 *                 // these will render as dropdown menu items when the arrow is clicked:
 *                 {text: 'Item 1', handler: function(){ alert("Item 1 clicked"); }},
 *                 {text: 'Item 2', handler: function(){ alert("Item 2 clicked"); }}
 *             ]
 *         })
 *     });
 *
 * Provide custom handling to the split button when the dropdown arrow is clicked:
 *
 *     Ext.create('Ext.SplitButton', {
 *         renderTo: 'button-ct',
 *         text: 'Options',
 *         handler: optionsHandler,
 *         arrowHandler: myCustomHandler
 *     });
 *
 */
Ext.define('Ext.SplitButton', {
    extend: 'Ext.Button',
    xtype: 'splitbutton',
    requires: [
        'Ext.menu.Menu'
    ],
    isSplitButton: true,
    baseCls: Ext.baseCSSPrefix + 'splitButton',
 
    /**
     * @event arrowclick
     * Fires when this button's arrow is clicked.
     * @param {Ext.SplitButton} this 
     * @param {Event} e The click event.
     */
 
    config: {
        /**
         * @cfg {Function} arrowHandler
         * @cfg {Ext.SplitButton} arrowHandler.button This Button.
         * @cfg {Ext.event.Event} arrowHandler.e The triggering event.
         * The handler function to run when the Button is tapped on.
         * @controllable
         */
        arrowHandler: null
    },
 
    /**
     * @private
     */
    arrowCls: 'split',
 
    initialize: function() {
        var me = this,
            el = me.el;
 
        me.callParent();
 
        this.arrowElement.addClsOnOver(this.hoveredCls, this.isEnabled, this);
        this.splitInnerElement.addClsOnOver(this.hoveredCls, this.isEnabled, this);
    },
 
    getTemplate: function() {
        return [{
                reference: 'innerElement',
                cls: Ext.baseCSSPrefix + 'splitBody-el',
                children: [{
                        reference: 'splitInnerElement',
                        cls: Ext.baseCSSPrefix + 'splitInner-el',
                        children: [{
                            reference: 'bodyElement',
                            cls: Ext.baseCSSPrefix + 'body-el',
                            children: [{
                                cls: Ext.baseCSSPrefix + 'icon-el ' + Ext.baseCSSPrefix + 'font-icon',
                                reference: 'iconElement'
                            }, {
                                reference: 'textElement',
                                cls: Ext.baseCSSPrefix + 'text-el'
                            }]
                        }, this.getButtonTemplate()]
                    },
                    {
                        reference: 'arrowElement',
                        cls: Ext.baseCSSPrefix + 'splitArrow-el',
                        children: [{
                            reference: 'splitArrowElement',
                            cls: Ext.baseCSSPrefix + 'arrow-el ' + Ext.baseCSSPrefix + 'font-icon'
                        }, this.getArrowButtonTemplate()]
                    }
                ]
            }
        ];
    },
 
    getArrowButtonTemplate: function() {
        return {
            tag: 'button',
            reference: 'splitArrowCoverElement',
            cls: Ext.baseCSSPrefix + 'button-el',
            onfocus: 'return Ext.doEv(this, event);',
            onblur: 'return Ext.doEv(this, event);'
        };
    },
 
    /**
     * @private
     */
    doTap: function(me, e) {
        var arrowEl = this.splitArrowCoverElement,
        arrowKeydown = (e.type === 'keydown' || e.type === 'click') && (e.target === arrowEl.dom);
 
        // this is done so if you hide the button in the handler, the tap event will not fire
        // on the new element where the button was.
        if (&& e.preventDefault && me.preventDefaultAction) {
            e.preventDefault();
        }
 
        if (!me.getDisabled()) {
            if (arrowKeydown) {
                me.toggleMenu(e, me.getMenu());
                me.fireEvent("arrowclick", me, e);
                if (me.getArrowHandler()) {
                    Ext.callback(me.getArrowHandler(), me.getScope(), [me, e], 0, me);
                }
            } else {
                if (me.getMenu().isVisible()) {
                    me.hideMenu(e, me.getMenu());
                }
                Ext.callback(me.getHandler(), me.getScope(), [me, e], 0, me);
            }
        }
    },
 
    onDownKey: function(e) {
        var arrowEl = this.splitArrowCoverElement;
        if (e.target === arrowEl.dom) {
           this.callParent([e]);
        }
    },
 
    updatePressed: function(pressed) {
        this.callParent([pressed]);
        this.arrowElement.toggleCls(this.pressedCls, pressed);
    },
 
    findEventTarget: function(e) {
        return e.target === this.buttonElement.dom ? this.splitInnerElement : this.arrowElement;
    },
 
    shouldRipple: function(e) {
        var arrowEl = this.splitArrowCoverElement,
            ripple = (arrowEl && e.target === arrowEl.dom) ? this.getArrowRipple() : this.getSplitRipple();
 
        this.setRipple(ripple);
        return this.callParent([e]);
    },
 
    enableFocusable: function() {
        this.splitArrowCoverElement.dom.disabled = false;
 
        this.callParent();
    },
 
    disableFocusable: function() {
        this.callParent();
 
        this.splitArrowCoverElement.dom.disabled = true;
    },
 
    privates: {
        onButtonFocus: function(e) {
            this.splitInnerElement.addCls(this.focusCls);
        },
 
        onButtonBlur: function(e) {
            this.splitInnerElement.removeCls(this.focusCls);
        },
 
        onArrowFocus: function(e) {
            this.arrowElement.addCls(this.focusCls);
        },
 
        onArrowBlur: function(e) {
            this.arrowElement.removeCls(this.focusCls);
        },
 
        handleFocusEvent: function(e) {
            var arrowEl = this.splitArrowCoverElement;
            this.callParent([e]);
            if (e.target === arrowEl.dom) {
                this.onArrowFocus([e]);
            } else if (e.target === this.buttonElement.dom) {
                this.onButtonFocus([e]);
            }
        },
 
        handleBlurEvent: function(e) {
            var arrowEl = this.splitArrowCoverElement;
            this.callParent([e]);
            if (e.target === arrowEl.dom) {
                this.onArrowBlur([e]);
            } else if (e.target === this.buttonElement.dom) {
                this.onButtonBlur([e]);
            }
        },
    }
});