/**
 *
 */
Ext.define('Ext.form.field.FileButton', {
    extend: 'Ext.button.Button',
    alias: 'widget.filebutton',
    
    childEls: [
        'fileInputEl'
    ],
    
    inputCls: Ext.baseCSSPrefix + 'form-file-input',
    
    cls: Ext.baseCSSPrefix + 'form-file-btn',
    
    preventDefault: false,
    
    // Button element *looks* focused but it should never really receive focus itself, 
    // and with it being a <div></div> we don't need to render tabindex attribute at all 
    tabIndex: undefined,
 
    promptCalled: false,
 
    autoEl: {
        tag: 'div',
        unselectable: 'on'
    },
    
    /*
     * This <input type="file"/> element is placed above the button element to intercept
     * mouse clicks, as well as receive focus. This is the only way to make browser file input
     * dialog open on user action, and populate the file input value when file(s) are selected.
     * The tabIndex value here comes from the template arguments generated in getTemplateArgs
     * method below; it is copied from the owner FileInput's tabIndex property.
     */
    afterTpl: [
        '<input id="{id}-fileInputEl" data-ref="fileInputEl" class="{childElCls} {inputCls}" ',
            'type="file" size="1" name="{inputName}" role="{role}" ',
            '<tpl if="tabIndex != null">tabindex="{tabIndex}"</tpl>',
        '>'
    ],
    
    keyHandlers: null,
    ariaEl: 'fileInputEl',
 
    /**
     * @private
     */
    getAfterMarkup: function(values) {
        return this.getTpl('afterTpl').apply(values);
    },
    
    getTemplateArgs: function() {
        var me = this,
            args;
        
        args = me.callParent();
        
        args.inputCls = me.inputCls;
        args.inputName = me.inputName || me.id;
        args.tabIndex = me.tabIndex != null ? me.tabIndex : null;
        args.role = me.ariaRole;
        
        return args;
    },
    
    afterRender: function() {
        var me = this;
        
        me.callParent(arguments);
        
        // We place focus and blur listeners on fileInputEl to activate Button's 
        // focus and blur style treatment 
        me.fileInputEl.on({
            scope: me,
            mousedown: me.handlePrompt,
            keydown: me.handlePrompt,
            change: me.fireChange,
            focus: me.onFileFocus,
            blur: me.onFileBlur
        });
    },
    
    fireChange: function(e) {
        this.fireEvent('change', this, e, this.fileInputEl.dom.value);
    },
    
    /**
     * @private
     * Creates the file input element. It is inserted into the trigger button component, made
     * invisible, and floated on top of the button's other content so that it will receive the
     * button's clicks.
     */
    createFileInput: function(isTemporary) {
        var me = this,
            fileInputEl;
        
        fileInputEl = me.fileInputEl = me.el.createChild({
            name: me.inputName || me.id,
            id: !isTemporary ? me.id + '-fileInputEl' : undefined,
            cls: me.inputCls + (me.getInherited().rtl ? ' ' + Ext.baseCSSPrefix + 'rtl' : ''),
            tag: 'input',
            type: 'file',
            size: 1,
            role: 'button'
        });
 
        // This is our focusEl 
        fileInputEl.dom.setAttribute('data-componentid', me.id);
        
        // We place focus and blur listeners on fileInputEl to activate Button's 
        // focus and blur style treatment 
        fileInputEl.on({
            scope: me,
            mousedown: me.handlePrompt,
            keydown: me.handlePrompt,
            change: me.fireChange,
            focus: me.onFileFocus,
            blur: me.onFileBlur
        });
    },
 
    handlePrompt: function(e) {
        var key;
 
        if (e.type == 'keydown') {
            key = e.getKey();
            // We need this conditional here because IE doesn't open the prompt on ENTER 
            this.promptCalled = ((!Ext.isIE && key === e.ENTER) || key === e.SPACE) ? true : false;
        } else {
            this.promptCalled = true;
        }
    },
 
    onFileFocus: function(e) {
        var ownerCt = this.ownerCt;
        
        if (!this.hasFocus) {
            this.onFocus(e);
        }
        
        if (ownerCt && !ownerCt.hasFocus) {
            ownerCt.onFocus(e);
        }
    },
 
    onFileBlur: function(e) {
        var ownerCt = this.ownerCt;
 
        // We should not go ahead with blur if this was called because 
        // the fileInput was clicked and the upload window is causing this event 
        if (this.promptCalled) {
            this.promptCalled = false;
            e.preventDefault();
            return;
        }
 
        if (this.hasFocus) {
            this.onBlur(e);
        }
        
        if (ownerCt && ownerCt.hasFocus) {
            ownerCt.onBlur(e);
        }
    },
    
    reset: function(remove) {
        // We do not add listeners to focusEls now. 
        // The Focus event publisher calls into Components on focus and blur 
        var me = this;
        
        if (remove) {
            me.fileInputEl.destroy();
        }
        
        me.createFileInput(!remove);
        
        if (remove) {
            me.ariaEl = me.fileInputEl;
        }
    },
    
    restoreInput: function(el) {
        // We do not add listeners to focusEls now. 
        // The Focus event publisher calls into Components on focus and blur 
        var me = this;
        me.fileInputEl.destroy();
        el = Ext.get(el);
        me.el.appendChild(el);
        me.fileInputEl = el;
    },
    
    onDisable: function(){
        this.callParent();
        this.fileInputEl.dom.disabled = true;
    },
 
    onEnable : function() {
        this.callParent();
        this.fileInputEl.dom.disabled = false;
    },
    
    privates: {
        getFocusEl: function() {
            return this.fileInputEl;
        },
        
        getFocusClsEl: function() {
            return this.el;
        }
    }
});