/*
 *  Copyright 2013 Anyware Services
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

/**
 * This class provides a widget to select a file.<br>
 * 
 * This widget is the default widget registered for fields of type Ametys.form.WidgetManager#TYPE_FILE and Ametys.form.WidgetManager#TYPE_BINARY.<br>
 * 
 * This widget is configurable:<br>
 * - Use {@link #cfg-filter} to restrict files by types. The available filters are 'image', 'video', 'multimedia', 'audio' or 'flash'.<br>
 * - Use {@link #cfg-allowExtensions} to restrict files by extensions such as 'pdf', 'xml', 'png'.... <br>
 * - Use {@link #cfg-allowSources} to specify the authorized file sources (eg: 'external' for local resource, 'resource' for shared resource). Separated by comma.<br>
 * See the subclasses of {@link Ametys.form.widget.File.FileSource} for the available sources.<br>
 */
Ext.define('Ametys.form.widget.File', {
    extend: 'Ametys.form.AbstractField',
    
    canDisplayComparisons: true,
  
    statics: {
    	
    	/**
         * @property {Object} _fileSources The accepted file types (external, resource, ..)
         * @private
         */
        _fileSources: {},
        
        /**
         * Register a new file type
         * @param {String} source The file source as such 'external', 'resource', ...
         * @param {Ametys.form.widget.File.FileSource} className The object class associated with this source
         */
    	registerFileSource: function (source, className)
        {
        	this._fileSources[source] = className;
        },
        
        /**
         * Get the object class associated with the given file type
         * @param {String} source The file source as such 'external', 'resource', ...
         * @return {Ametys.form.widget.File.FileSource} The file source class
         */
        getFileSource: function (source)
        {
        	return this._fileSources[source];
        },

        /**
		 * @property {String} IMAGE_FILTER Filter for image files
		 * @readonly
		 */
    	IMAGE_FILTER: 'image',
    	/**
		 * @property {String} MULTIMEDIA_FILTER Filter for multimedia files
		 * @readonly
		 */
    	MULTIMEDIA_FILTER: 'multimedia',
    	/**
		 * @property {String} VIDEO_FILTER Filter for video files
		 * @readonly
		 */
    	VIDEO_FILTER: 'video',
    	/**
		 * @property {String} AUDIO_FILTER Filter for audio files
		 * @readonly
		 */
    	AUDIO_FILTER: 'audio',
    	/**
		 * @property {String} FLASH_FILTER Filter for flash files
		 * @readonly
		 */
    	FLASH_FILTER: 'flash',
        /**
         * @property {String} PDF_FILTER Filter for pdf files
         * @readonly
         */
        PDF_FILTER: 'pdf',
    	
    	/**
    	 * The filters configuration
    	 * @private
    	 */
    	filters: {
    		none: {
    			buttonMenuText: "",
    			buttonMenuTooltip: "{{i18n PLUGINS_CORE_UI_WIDGET_RESOURCES_PICKER_SELECT_FILE_BUTTON}}",
    			buttonMenuIconCls: 'ametysicon-document9',
				
    			emptyText: "{{i18n PLUGINS_CORE_UI_WIDGET_RESOURCES_PICKER_NO_FILE_SELECTED}}",
    			
    			deleteText: "{{i18n PLUGINS_CORE_UI_WIDGET_RESOURCES_PICKER_DELETE_FILE_BUTTON}}",
    			deleteTextConfirm: "{{i18n PLUGINS_CORE_UI_WIDGET_RESOURCES_PICKER_DELETE_FILE_CONFIRM}}",
    			
    			downloadText: "{{i18n PLUGINS_CORE_UI_WIDGET_RESOURCES_PICKER_DOWNLOAD_FILE}}",
                notFoundText: "{{i18n PLUGINS_CORE_UI_WIDGET_RESOURCES_PICKER_NOTFOUND_FILE}}"
    		},
    		
    		image: {
    			buttonMenuText: "",
    			buttonMenuTooltip: "{{i18n PLUGINS_CORE_UI_WIDGET_RESOURCES_PICKER_SELECT_IMAGE_BUTTON}}",
				buttonMenuIconCls: 'ametysicon-image2',
				
    			emptyText: "{{i18n PLUGINS_CORE_UI_WIDGET_RESOURCES_PICKER_NO_IMAGE_SELECTED}}",
    			
    			deleteText: "{{i18n PLUGINS_CORE_UI_WIDGET_RESOURCES_PICKER_DELETE_IMAGE_BUTTON}}",
    			deleteTextConfirm: "{{i18n PLUGINS_CORE_UI_WIDGET_RESOURCES_PICKER_DELETE_IMAGE_CONFIRM}}",
    			
    			downloadText: "{{i18n PLUGINS_CORE_UI_WIDGET_RESOURCES_PICKER_DOWNLOAD_IMAGE}}",
                notFoundText: "{{i18n PLUGINS_CORE_UI_WIDGET_RESOURCES_PICKER_NOTFOUND_IMAGE}}"
    		},
    		
    		multimedia: {
    			buttonMenuText: "",
    			buttonMenuTooltip: "{{i18n PLUGINS_CORE_UI_WIDGET_RESOURCES_PICKER_SELECT_MULTIMEDIA_BUTTON}}",
    			buttonMenuIconCls: 'ametysicon-movie16',
				
    			emptyText: "{{i18n PLUGINS_CORE_UI_WIDGET_RESOURCES_PICKER_NO_MULTIMEDIA_SELECTED}}",
    			
    			deleteText: "{{i18n PLUGINS_CORE_UI_WIDGET_RESOURCES_PICKER_DELETE_MULTIMEDIA_BUTTON}}",
    			deleteTextConfirm: "{{i18n PLUGINS_CORE_UI_WIDGET_RESOURCES_PICKER_DELETE_MULTIMEDIA_CONFIRM}}",
    			
    			downloadText: "{{i18n PLUGINS_CORE_UI_WIDGET_RESOURCES_PICKER_DOWNLOAD_MULTIMEDIA}}",
                notFoundText: "{{i18n PLUGINS_CORE_UI_WIDGET_RESOURCES_PICKER_NOTFOUND_MULTIMEDIA}}"
    		},
    		
    		video: {
    			buttonMenuText: "",
    			buttonMenuTooltip: "{{i18n PLUGINS_CORE_UI_WIDGET_RESOURCES_PICKER_SELECT_VIDEO_BUTTON}}",
    			buttonMenuIconCls: 'ametysicon-movie16',
				
    			emptyText: "{{i18n PLUGINS_CORE_UI_WIDGET_RESOURCES_PICKER_NO_VIDEO_SELECTED}}",
    			
    			deleteText: "{{i18n PLUGINS_CORE_UI_WIDGET_RESOURCES_PICKER_DELETE_VIDEO_BUTTON}}",
    			deleteTextConfirm: "{{i18n PLUGINS_CORE_UI_WIDGET_RESOURCES_PICKER_DELETE_VIDEO_CONFIRM}}",
    			
    			downloadText: "{{i18n PLUGINS_CORE_UI_WIDGET_RESOURCES_PICKER_DOWNLOAD_VIDEO}}",
                notFoundText: "{{i18n PLUGINS_CORE_UI_WIDGET_RESOURCES_PICKER_NOTFOUND_VIDEO}}"
    		},
    		
    		flash: {
    			buttonMenuText: "",
    			buttonMenuTooltip: "{{i18n PLUGINS_CORE_UI_WIDGET_RESOURCES_PICKER_SELECT_FLASH_BUTTON}}",
    			buttonMenuIconCls: 'ametysicon-flash',
				
    			emptyText: "{{i18n PLUGINS_CORE_UI_WIDGET_RESOURCES_PICKER_NO_FLASH_SELECTED}}",
    			
    			deleteText: "{{i18n PLUGINS_CORE_UI_WIDGET_RESOURCES_PICKER_DELETE_FLASH_BUTTON}}",
    			deleteTextConfirm: "{{i18n PLUGINS_CORE_UI_WIDGET_RESOURCES_PICKER_DELETE_FLASH_CONFIRM}}",
    			
    			downloadText: "{{i18n PLUGINS_CORE_UI_WIDGET_RESOURCES_PICKER_DOWNLOAD_FLASH}}",
                notFoundText: "{{i18n PLUGINS_CORE_UI_WIDGET_RESOURCES_PICKER_NOTFOUND_FLASH}}"
    		},
    		
    		audio: {
    			buttonMenuText: "",
    			buttonMenuTooltip: "{{i18n PLUGINS_CORE_UI_WIDGET_RESOURCES_PICKER_SELECT_SOUND_BUTTON}}",
    			buttonMenuIconCls: 'ametysicon-file-extension-generic-music',
				
    			emptyText: "{{i18n PLUGINS_CORE_UI_WIDGET_RESOURCES_PICKER_NO_SOUND_SELECTED}}",
    			
    			deleteText: "{{i18n PLUGINS_CORE_UI_WIDGET_RESOURCES_PICKER_DELETE_SOUND_BUTTON}}",
    			deleteTextConfirm: "{{i18n PLUGINS_CORE_UI_WIDGET_RESOURCES_PICKER_DELETE_SOUND_CONFIRM}}",
    			
    			downloadText: "{{i18n PLUGINS_CORE_UI_WIDGET_RESOURCES_PICKER_DOWNLOAD_SOUND}}",
                notFoundText: "{{i18n PLUGINS_CORE_UI_WIDGET_RESOURCES_PICKER_NOTFOUND_SOUND}}"
    		},
            
            pdf: {
                buttonMenuText: "",
                buttonMenuTooltip: "{{i18n PLUGINS_CORE_UI_WIDGET_RESOURCES_PICKER_SELECT_PDF_BUTTON}}",
                buttonMenuIconCls: 'ametysicon-file-extension-pdf',
                
                emptyText: "{{i18n PLUGINS_CORE_UI_WIDGET_RESOURCES_PICKER_NO_PDF_SELECTED}}",
                
                deleteText: "{{i18n PLUGINS_CORE_UI_WIDGET_RESOURCES_PICKER_DELETE_PDF_BUTTON}}",
                deleteTextConfirm: "{{i18n PLUGINS_CORE_UI_WIDGET_RESOURCES_PICKER_DELETE_PDF_CONFIRM}}",
                
                downloadText: "{{i18n PLUGINS_CORE_UI_WIDGET_RESOURCES_PICKER_DOWNLOAD_PDF}}",
                notFoundText: "{{i18n PLUGINS_CORE_UI_WIDGET_RESOURCES_PICKER_NOTFOUND_PDF}}"
            }
    	}
    },
    
    /**
     * @cfg {String} [filter="none"] The filter to use for accepted files amongst: 'none', 'image', 'audio', 'video', 'multimedia', 'flash' or 'pdf'. Can be null to accept all files (equivalent to 'none').
     */
    /**
     * @cfg {String|String[]} [allowExtensions] The allowed file extensions in a Array or separated by comma. This parameter is more precise than #cfg-filter. If used, the filter will be forced to 'none'.
     */
    /**
     * @cfg {String|String[]} [allowSources="external"] The allowed file sources in a Array or separated by comma. Default to 'external'.
     */
    
    /**
     * @cfg {Number} [imagePreviewMaxHeight=100] The maximum height for image preview. This is only used with filter 'image' (see #cfg-fileFilter).
     */
    imagePreviewMaxHeight: 100,
    /**
     * @cfg {Number} [imagePreviewMaxWidth=100] The maximum width for image preview. This is only used with filter 'image' (see #cfg-fileFilter).
     */
    imagePreviewMaxWidth: 100,
    
    /**
     * @cfg {String} buttonText The button text to display on the upload button.
     */
    /**
     * @cfg {String} buttonIcon The button icon path for the upload button.
     */
    
    /**
     * @cfg {Object} textConfig The configuration object for the display field. Note that many configuration can be set directly here and will we broadcasted to underlying field (allowBlank...). 
     */
    /**
     * @cfg {String} emptyText The default text to place into an empty field.
     */
    /**
     * @cfg {String} deleteText The text to display on delete button tooltip.
     */
    /**
     * @cfg {String} deleteTextConfirm The text to display when deleting a file.
     */
    /**
	 * @cfg {String} [deleteButtonIcon] The full path to the delete button icon (in 16x16 pixels). Can be null to use #cfg-deleteButtonIconCls instead
	 */
     /**
     * @cfg {String} [deleteButtonIconCls=ametysicon-delete30] The CSS class to apply to delete button icon
     */
    deleteButtonIconCls: 'ametysicon-delete30', 
    /**
     * @cfg {Boolean} buttonOnly True to display the file upload field as a button with no visible
     * text field (defaults to true).  If true, all inherited TextField members will still be available.
     */
    buttonOnly: false,
    /**
     * @cfg {Number} buttonOffset The number of pixels of space reserved between the button and the text field
     * (defaults to 3).  Note that this only applies if {@link #buttonOnly} = false.
     */
    buttonOffset: 5,
    
    /**
     * @cfg {String} fileCls The base class for this field
     */
    fileCls: "x-field-file",
    
    /**
     * @cfg {String} glyphCls The CSS to use for file's glyph. Only used if the file filter is not #IMAGE_FILTER
     */
    glyphCls: 'a-form-file-widget-glyph',
    
    /**
     * @cfg {String} imgCls The CSS to use for image preview. Only used if the file filter is #IMAGE_FILTER
     */
    imgCls: 'a-form-file-widget-img',
    
    
    /**
     * @cfg {String} imgWithBorderCls The CSS to use for image preview. Only used if the file filter is #IMAGE_FILTER
     */
    imgWithBorderCls: 'a-form-file-widget-img-border',
    
    initComponent: function()
    {
        this.cls = [this.emptyCls, this.fileCls];
        this.layout = {
            type: 'hbox'
        };
        
        this.items = this.items || [];
        
        if (!Ametys.form.widget.File.filters[this.fileFilter])
        {
            this.getLogger().error("The filter '" + this.fileFilter + "' does not exists. Switching to 'none'.")
            this.fileFilter = 'none';
        }
        
        if (this.fileFilter ==  Ametys.form.widget.File.IMAGE_FILTER)
        {
            // Preview image
            this.img = Ext.create('Ext.Img', {
                autoEl: 'div', 
                hidden: true,
                width: this.imagePreviewMaxWidth + 6, // image width + padding
                height: this.imagePreviewMaxHeight + 6, // image height + padding
                cls: this.imgWithBorderCls,
                listeners: {
                    'afterrender': {
	                    fn: function() { 
	                        this.img.el.dom.style.lineHeight = (this.imagePreviewMaxHeight - 2) + "px";
                            this.img.imgEl.dom.style.maxWidth = this.imagePreviewMaxWidth + "px";
                            this.img.imgEl.dom.style.maxHeight = this.imagePreviewMaxHeight + "px";
	                    }, 
	                    scope: this, 
	                    options: { single: true } 
	                }
                }
            });
            
            this.items.push(this.img);
        }
        else
        {
            // File glyph
        	this.fileGlyph = Ext.create('Ext.Component', {
	           height: 48,
	           width: 48,
	           cls: this.glyphCls
	        });
            
            this.items.push(this.fileGlyph);
        }
        
        // Display field.
        var textConfig = Ext.applyIf(this.textConfig || {}, {
            html: '',
            flex: 1,
            cls: Ametys.form.AbstractField.READABLE_TEXT_CLS
        });
        this.displayField = Ext.create('Ext.Component', textConfig);
        this.items.push(this.displayField);
        
        if (!this.readOnly)
        {
            // Button which opens the upload dialog box.
            this.button = Ext.create('Ext.button.Button', this.getBtnConfig());
            
            // Button which deletes the selected file.
            var deleteButtonConfig = Ext.applyIf(this.deleteButtonConfig || {}, {
                icon: this.deleteButtonIcon,
                iconCls: this.deleteButtonIcon ? null : this.deleteButtonIconCls,
                disabled: this.disabled,
                
                tooltip: this.deleteText ||  Ametys.form.widget.File.filters[this.fileFilter].deleteText,
                handler: this.deleteFile,
                scope: this,
                hidden: true
            });
        
            this.deleteButton = Ext.create('Ext.button.Button', deleteButtonConfig);
            
            this.items.push(this.button);
            this.items.push(this.deleteButton);
        }
    
        this.callParent(arguments);
    },
    
    constructor: function (config)
    {
    	// Filter
        this.fileFilter = config['filter'] || 'none';
        delete config.filter;
        
        if (!Ext.isEmpty(config['allowExtensions']))
        {
        	this.allowedExtensions = Ext.isArray(config['allowExtensions']) ? config['allowExtensions'] : config['allowExtensions'].split(',');
            this.fileFilter = 'none';
            delete config.allowExtensions;
        }
        
        // File location
        this._prepareFileSources(config);
        
        this.callParent(arguments);
    },
    
    _prepareFileSources: function(config)
    {
        if (Ext.isEmpty(config['allowSources']))
        {
            /**
             * @protected
             * @cfg {String[]} [defaultSources=[Ametys.form.widget.File.External.SOURCE]] The sources to use when {#cfg-allowSources} is null or empty
             */
            this.fileSources = config.defaultSources || [Ametys.form.widget.File.External.SOURCE];
        }
        else
        {
            this.fileSources = Ext.isArray(config['allowSources']) ? config['allowSources'] : config['allowSources'].split(',');
        }
        delete config.allowSources;
    },
    
    /**
     * Get the configuration of the button to pick/upload a resource
     * @return {Object} The button configuration
     */
    getBtnConfig: function ()
    {
        if (this.fileSources.length > 1)
        {
            var menuItems = this._getMenuItemsForFileSources();
            
            return {
                text: this.getInitialConfig('buttonText') ||  Ametys.form.widget.File.filters[this.fileFilter].buttonMenuText, 
                tooltip: this.getInitialConfig('buttonTooltip') ||  Ametys.form.widget.File.filters[this.fileFilter].buttonMenuTooltip, 
                iconCls: this.getInitialConfig('buttonIconCls')  ||  Ametys.form.widget.File.filters[this.fileFilter].buttonMenuIconCls,
                
                menu: menuItems,
                
                disabled: this.disabled
            }
        }
        else
        {
            var source = Ametys.form.widget.File.getFileSource(this.fileSources[0]);
            var btnCfg = source.getBtnConfig (this.getInitialConfig(), this.fileFilter);
            
            return Ext.apply(btnCfg, {
                handler: this._selectFile,
                scope: this,
                
                disabled: this.disabled
            });
        }
    },
    
    /**
     * @private
     * Get the configuration for menu items for the available file sources
     * @return {Object} The menu items
     */
    _getMenuItemsForFileSources:function()
    {
        var items = [];
        
        for (var i=0; i < this.fileSources.length; i++)
        {
            var source = Ametys.form.widget.File.getFileSource(this.fileSources[i]);
            var itemCfg = source.getMenuItemConfig (this.getInitialConfig(), this.fileFilter);
            
            items.push(Ext.apply(itemCfg, {
                xtype: 'menuitem',
                handler: this._selectFile,
                scope: this
            }))
        }
        
        return items;
    },
    
    /**
     * Select a file.
     * @param {Ext.Button} btn The button calling this function
     * @protected
     */
    _selectFile: function (btn)
    {
        this.triggerDialogBoxOpened = true;
        
    	var source = Ametys.form.widget.File.getFileSource(btn.source);
    	source.handler (this.getInitialConfig(), this.fileFilter, this.allowedExtensions, Ext.bind(this._insertResourceCb, this, [source.getFileType()], true), this);
    },
    
    /**
     * Callback function, called when a resource is uploaded in the dialog.
     * @param {String} id The uploaded file id.
     * @param {String} filename The uploaded file name.
     * @param {Number} fileSize The uploaded file size in bytes.
     * @param {String} viewHref A URL to view the file.
     * @param {String} downloadHref A URL to download the file.
     * @param {Object} actionResult The result of the upload action. Can be null.
     * @param {String} type The type of the resource. Can be null.
     * @protected
     */
    _insertResourceCb: function(id, filename, fileSize, viewHref, downloadHref, actionResult, type)
    {
        if (id == null)
        {
            return;
        }
        
        this.setValue({
        	id: id,
        	filename: filename,
        	size: fileSize,
        	viewUrl: viewHref,
        	downloadUrl: downloadHref,
        	type: type
        });
        
        this.triggerDialogBoxOpened = false; 
        this.focus();
    },
    
    /**
     * Delete the file.
     * @private
     */
    deleteFile: function()
    {
        this.triggerDialogBoxOpened = true; 
        
        // Show the confirmation dialog.
        Ametys.Msg.confirm(
        	this.getInitialConfig('deleteText') ||  Ametys.form.widget.File.filters[this.fileFilter].deleteText, 
        	this.getInitialConfig('deleteTextConfirm') ||  Ametys.form.widget.File.filters[this.fileFilter].deleteTextConfirm,
            function (btn) {
                if (btn == 'yes')
                {
                    this.setValue();
                }
                
                this.triggerDialogBoxOpened = false;
                this.focus();
            },
            this
        );
    },
    
    getErrors: function (value)
    {
    	value = value || this.getValue();
    	
    	var errors = this.callParent(arguments);
    	
    	if (!this.allowBlank && (value && !value.id))
    	{
    		errors.push(this.blankText);
    	}
    	
    	return errors;
    },
    
    /**, 
     * Sets a data value into the field.
     * @param {Object} value The value to set.
     * @param {String} [value.id] The file identifier.
     * @param {String} value.filename The file name (if applicable).
     * @param {String} value.type The file object type ('metadata').
     * @param {Number} value.size The file size in bytes.
     * @param {Number} value.lastModified The file's last modification date.
     * @param {Number} value.viewUrl A URL to view the file.
     * @param {Number} value.downloadUrl A URL to download the file.
     */
    setValue: function (value)
    {
    	if (value && !Ext.Object.isEmpty(value))
    	{
    		value = Ext.applyIf (value, {
        		id: 'untouched',
        		type: 'external'
        	});
    	}
    	else
    	{
    		value = {};
    	}
    	
    	this.callParent([value]);

        Ext.suspendLayouts();
        try
        {
    	   this._updateUI();
        }
        finally
        {
            Ext.resumeLayouts(true);
        }
    },
    
    isEqual: function(value1, value2) 
    {
    	return value1 != null && value2 != null && value1.id === value2.id;
    }, 
    
    getSubmitValue: function ()
    {
        return this.value ? Ext.encode(this.value) : '';
    },
    
    getReadableValue: function ()
    {
    	return this.value ? this.value.filename : '';
    },
    
    /**
     * Update UI
     * @private
     */
    _updateUI: function()
    {
    	var value = this.value;
    	
    	if (!value || !value.id)
    	{
    		this._showHideImgPreview(false);
    		// Update the file description.
            this.displayField.setHeight(21); // Let's freeze height to avoid useless layout afterward
            
            if (!this.readOnly)
            {
                this.deleteButton.hide();
                this.button.show();
            }
            
            this.displayField.update(this.getInitialConfig('emptyText') ||  Ametys.form.widget.File.filters[this.fileFilter].emptyText);
    	}
    	else
    	{
            if (!this.readOnly)
            {
                this.deleteButton.show();
                this.button.hide();
            }
            
            // Update file description after resizing the fields to be able to fit the file name to the available space.
            this._updateFileDescription(value.id, value.filename, value.size, value.viewUrl, value.downloadUrl);
        }
    },
    
    /**
     * @private
     * Show or hide the image preview or fiele glyph
     * @param {Boolean} show true to show
     */
    _showHideImgPreview : function (show)
    {
        if (this.fileFilter ==  Ametys.form.widget.File.IMAGE_FILTER)
        {
            this.img.setVisible(show);
            this.setHeight(show && !this.img.rendered ? this.img.height : null);
        }
        else
        {
            this.fileGlyph.setVisible(show);
        }
    },
    
    /**
     * Construct the file description (icon, name, size and link to download it) and update the display field.
     * @param {String} id The file id.
     * @param {String} fileName The file name
     * @param {Number} fileSize The file size in bytes.
     * @param {Number} viewHref A URL to view the file.
     * @param {Number} downloadHref A URL to download the file.
     * @return The HTML described file
     * @private
     */
    _updateFileDescription: function(id, fileName, fileSize, viewHref, downloadHref)
    {
    	if (this.fileFilter ==  Ametys.form.widget.File.IMAGE_FILTER)
    	{
            if (!viewHref)
            {
                var imgSrc = Ametys.getPluginResourcesPrefix('core-ui') + '/img/imagenotfound_max' + this.imagePreviewMaxWidth + 'x' + this.imagePreviewMaxHeight + '.png';
                this.img.setSrc(imgSrc);
            }
            else
            {
                var separator = '&';
                if (viewHref.indexOf('?') < 0)
                {
                    separator = '?';
                }
                var imgSrc = viewHref + separator + 'maxWidth=' + this.imagePreviewMaxWidth + '&maxHeight=' + this.imagePreviewMaxHeight + '&foo=' + Math.random();
                this.img.setSrc(imgSrc);
            }
    		
    	}
        else
        {
            var iconGlyph = Ametys.file.AbstractFileExplorerTree.getFileIconGlyph(fileName);
            this.fileGlyph.update('<span class="' + iconGlyph + '"></span>');
        }
    	
        this._showHideImgPreview(true);
        
        var text = '';
        if (!downloadHref && !fileName)
        {
            text = this.getInitialConfig('notFoundText') ||  Ametys.form.widget.File.filters[this.fileFilter].notFoundText || '{{i18n PLUGINS_CORE_UI_WIDGET_RESOURCES_PICKER_NOTFOUND_FILE}}';
        }
        else
        {
            var text = '';
            if (downloadHref)
            {
                // Do not write the file name in the link just now.
                text = '<a href="' + downloadHref + '" title="' + (this.getInitialConfig('downloadText') ||  Ametys.form.widget.File.filters[this.fileFilter].downloadText) + '">' + fileName + '</a>';
            }
            else
            {
                text = '<span>' + fileName + '</span>';
            }
            
            if (fileSize)
	        {
	            text += '<br/><span class="ametys-field-hint">' + Ext.util.Format.fileSize(fileSize) + '</span>';
	            this.displayField.setHeight(34); // Let's freeze height to avoid useless layout afterward
	        }
	        else
	        {
	            this.displayField.setHeight(21); // Let's freeze height to avoid useless layout afterward
	        }
        }
        
        this.displayField.update(text);
    },
    
    setComparisonValue: function(otherValue, base)
    {
        this.toggleCls("ametys-file-comparable", otherValue !== undefined);
    }
});