/**
 * @private
 * Private Container class used by the {@link Ext.grid.RowEditor} to hold its buttons.
 */
Ext.define('Ext.grid.RowEditorButtons', {
    extend: 'Ext.container.Container',
    alias: 'widget.roweditorbuttons',

    frame: true,
    shrinkWrap: true,
    position: 'bottom',

    constructor: function(config) {
        var me = this,
            rowEditor = config.rowEditor,
            cssPrefix = Ext.baseCSSPrefix,
            plugin = rowEditor.editingPlugin;

        config = Ext.apply({
            baseCls: cssPrefix + 'grid-row-editor-buttons',
            defaults: {
                xtype: 'button',
                ui: rowEditor.buttonUI,
                scope: plugin,
                flex: 1,
                minWidth: Ext.panel.Panel.prototype.minButtonWidth
            },
            items: [{
                cls: cssPrefix + 'row-editor-update-button',
                itemId: 'update',
                handler: plugin.completeEdit,
                text: rowEditor.saveBtnText,
                disabled: rowEditor.updateButtonDisabled,
                listeners: {
                    element: 'el',
                    keydown: me.onUpdateKeyDown,
                    scope: me
                }
            }, {
                cls: cssPrefix + 'row-editor-cancel-button',
                itemId: 'cancel',
                handler: plugin.cancelEdit,
                text: rowEditor.cancelBtnText,
                listeners: {
                    element: 'el',
                    keydown: me.onCancelKeyDown,
                    scope: me
                }
            }]
        }, config);

        me.callParent([config]);

        me.addClsWithUI(me.position);
    },

    // SHIFT+TAB off the update button loops back into the last field.
    onUpdateKeyDown: function(e) {
        if (e.shiftKey && e.getKey() === e.TAB) {
            e.stopEvent();
            // Must delay the focus, otherwise the imminent keyup will TAB off that field
            this.rowEditor.child(':focusable:not([isButton]):last').focus(false, true);
        }
    },

    // TAB off the cancel button loops back into the first field.
    onCancelKeyDown: function(e) {
        if (!e.shiftKey && e.getKey() === e.TAB) {
            e.stopEvent();
            // Must delay the focus, otherwise the imminent keyup will TAB off that field
            this.rowEditor.child(':focusable').focus(false, true);
        }
    },

    setButtonPosition: function(position) {
        var me = this,
            rowEditor = this.rowEditor,
            rowEditorHeight = rowEditor.getHeight(),
            rowEditorBody = rowEditor.body,
            bottom = '',
            top = '';

        me.removeClsWithUI(me.position);
        me.position = position;
        me.addClsWithUI(position);
        // we tried setting the top/bottom value in the stylesheet based on form field
        // height + row editor padding, but that approach does not work when there are
        // larger things inside the editor, e.g. textarea, so we have to measure
        // the row editor height and position the buttons accordingly (see EXTJSIV-9914).
        if (position === 'top') {
            bottom = (rowEditorHeight - rowEditorBody.getBorderWidth('t')) + 'px';
        } else {
            top = (rowEditorHeight - rowEditorBody.getBorderWidth('b')) + 'px';
        }

        me.el.setStyle({
            top: top,
            bottom: bottom
        });
    },

    privates: {
        getFramingInfoCls: function(){
            return this.baseCls + '-' + this.ui + '-' + this.position;
        },

        getFrameInfo: function() {
            var frameInfo = this.callParent();

            // Trick Renderable into rendering the top framing elements, even though they
            // are not needed in the default "bottom" position.  This allows us to flip the
            // buttons into "top" position without re-rendering.
            frameInfo.top = true;

            return frameInfo;
        }
    }
});
