/*
 *  Copyright 2010 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 tool displays the metadata of a Ametys object in a table.
 * @private
 */
Ext.define('Ametys.plugins.repository.tool.AmetysObjectMetadataTool',
{
    extend: 'Ametys.repository.tool.RepositoryTool',
    
    /**
     * @private
     * @property {String} _aoId The identifier of the Ametys object
     */
    
    /**
     * @private
     * @property {String} [_workspaceName=default] The JCR workspace name
     */
    
    /**
     * @private
     * @property {String} [_compositePath] The path of the composite metadata
     */
    
    /**
     * @private
     * @property {String} [_richtextPath] The path of the richtext metadata
     */
    
    statics: {
        /**
         * Open the AmetysObject metadata tool.
         * @param {String} id The ID of the AmetysObject to open.
         */
        open: function(id)
        {
            Ametys.tool.ToolsManager.openTool('uitool-repository-ametysobject-metadata', {id: id});
        }
    },
    
    constructor: function(config)
    {
        this.callParent(arguments);
        
        // Bus messages listeners
        Ametys.message.MessageBus.on(Ametys.message.Message.MODIFIED, this._onMessageModified, this);
        Ametys.message.MessageBus.on(Ametys.message.Message.DELETED, this._onMessageDeleted, this);
    },
    
    createPanel: function()
    {
        this.metadataPanel = Ext.create('Ametys.repository.tool.NodePropertiesTool.TablePropertiesPanel', {
            title: "{{i18n PLUGINS_REPOSITORY_METADATA_PANEL_TITLE}}",
            
            binaryTypes: ['binary', 'file-content', 'richtext-content', 'richtext'],
            
            showPendingChanges: false, // session is saved to each modification
            deleteProperty: Ext.bind (this._deleteMetadata, this),
            saveProperty: Ext.bind (this._saveMetadata, this),
            
            downloadBinaryProperty: Ext.bind(this._downloadBinary, this)
        });
        
        return Ext.create('Ext.panel.Panel', {
            scrollable: true,
            
            // Metadata node path
            dockedItems: {
                dock: 'top',
                ui: 'tool-hintmessage',
                xtype: 'component',
                html: ''
            },
            
            layout: {
                type: 'vbox',
                align: 'stretch'
            },
            items: [
                this.metadataPanel
            ]
        });
    },
    
    getMBSelectionInteraction: function() 
    {
        return Ametys.tool.Tool.MB_TYPE_ACTIVE;
    },
    
    getType: function()
    {
        return Ametys.tool.Tool.TYPE_REPOSITORY;  
    },    
    
    sendCurrentSelection: function()
    {
        Ext.create('Ametys.message.Message', {
            type: Ametys.message.Message.SELECTION_CHANGED,
            targets: {
                id: Ametys.message.MessageTarget.AMETYS_OBJECT,
                parameters: {
                    ids: [this.getParams().id],
                    workspaceName: this._workspaceName
                }
            }
        });
    },
    
    /**
     * @inheritdoc
     * @param {Object} params The configuration object
     * @param {String} params.id (required) The Ametys object id.
     * @param {String} [params.workspaceName] The JCR workspace's name
     * @param {String} [params.compositePath] The path to the composite metadata.
     * @param {String} [params.richtextPath] The path to the richtext metadata.
     */
    setParams: function(params)
    {
        var refreshNeeded = params.id != this._aoId || params.workspaceName != this._workspaceName || params.compositePath != this._compositePath || params.richtextPath != this._richtextPath;
        
        this._aoId = params.id;
        this._workspaceName = params.workspaceName || 'default';
        this._compositePath = params.compositePath;
        this._richtextPath = params.richtextPath;
        
        this.callParent(arguments);
        
        if (refreshNeeded)
        {
            this.refresh();
        }
    },
    
    refresh: function(manual)
    {
        this.showRefreshing();
        
        var id = this.getParams().id;
        
        Ametys.data.ServerComm.send({
            plugin: 'repository',
            url: 'repository/logic-node',
            parameters: {
                id: id
            },
            priority: Ametys.data.ServerComm.PRIORITY_MAJOR,
            callback: {
                handler: this._refreshCb,
                scope: this
            }
        });
    },
    
    /**
     * Callback: update all the UI (toolbar and panels) to reflect the selected repository node.
     * @param {HTMLElement} response The XML document.
     * @param {Array} args The callback arguments.
     * @private
     */
    _refreshCb: function(response, args)
    {
        var id = Ext.dom.Query.selectValue('repository > ametysObject > @id', response, '');
        var name = Ext.dom.Query.selectValue('repository > ametysObject > @name', response, '');
        var path = Ext.dom.Query.selectValue('repository > ametysObject > @path', response, '');
        
        this._jcrAo = Ext.dom.Query.selectValue('repository > ametysObject > isJCRAO', response, '') == 'true';
        this._jcrPath = Ext.dom.Query.selectValue('repository > ametysObject > JCRPath', response, '');
        
        // Update path
        this.getContentPanel().down("*[dock='top']").update(path + ' (' + id + ')');
        this.setTitle(name);

        // Update metadata
        var metadatas = Ext.dom.Query.select('repository > ametysObject > metadata', response);
        this.metadataPanel.updatePropertiesFromXml(metadatas);
        
        // this.updatePanel(metadatas, isModifiable, isLocked);
        
        this.showRefreshed();
    },
    
    /**
     * Called when an object is modified.
     * @param {Ametys.message.Message} message The bus message.
     */
    _onMessageModified: function(message)
    {
        var aoTarget = message.getTarget(Ametys.message.MessageTarget.AMETYS_OBJECT);
        if (aoTarget != null && aoTarget.getParameters().id == this.getParams().id && message.getParameters().major)
        {
            this.showOutOfDate();
        }
        
        var nodeTarget = message.getTarget(Ametys.message.MessageTarget.REPOSITORY_NODE);
        if (nodeTarget != null && nodeTarget.getParameters().path == this._jcrPath)
        {
            this.showOutOfDate();
        }
    },
    
    /**
     * Called when an object is deleted.
     * @param {Ametys.message.Message} message The bus message.
     */
    _onMessageDeleted: function(message)
    {
        var target = message.getTarget(Ametys.message.MessageTarget.AMETYS_OBJECT);
        if (target != null && target.getParameters().id == this.getParams().id)
        {
            this.close();
        }
        
        var nodeTarget = message.getTarget(Ametys.message.MessageTarget.REPOSITORY_NODE);
        if (nodeTarget != null && nodeTarget.getParameters().path == this._jcrPath)
        {
            this.close();
        }
    },
    
    /**
     * Save the metadata value.
     * @param {Ext.form.Panel} form The form panel to submit the value
     * @param {String} type The metadata's type
     * @param {String} id The field id
     * @param {String} name The metadata's name.
     * @param {String} value The metadata's new value as string
     * @param {Boolean} multiple true if the metadata is multiple
     * @param {Function} [successCb] The callback function to call in case of success
     * @param {Function} [failureCb] The callback function to call in case of failure
     * @private
     */
    _saveMetadata: function(form, type, id, name, value, multiple, successCb, failureCb)
    {
        form.getForm().submit({
            url: Ametys.getPluginDirectPrefix('repository') + '/repository/set-metadata',
            params: {
                id: this.getParams().id,
                name: name,
                value: value,
                multiple: multiple,
                cPath: this._compositePath,
                rtPath: this._richtextPath,
                type: type,
                filefieldid: id
            },
            success: Ext.bind(this._saveMetadataSuccess, this, [successCb], true),
            failure: Ext.bind(this._saveMetadataFail, this, [failureCb], true)
        });
    },
    
    /**
     * Callback function invoked when a metadata has been successfully saved.
     * @param {Ext.form.Basic} form The form that requested the action.
     * @param {Ext.form.action.Action} action The Action class.
     * @param {Function} [callback] The callback function
     * @private
     */
    _saveMetadataSuccess: function (form, action, callback)
    {
        if (Ext.isFunction(callback))
        {
            callback();
        }
        
        // Notify the modification.
        var targets = [{
            id: Ametys.message.MessageTarget.AMETYS_OBJECT,
            parameters: {
                ids: [this.getParams().id],
                workspaceName: this._workspaceName
            }
        }];
        
        if (this._jcrAo && this._jcrPath)
        {
            targets.push({
                id: Ametys.message.MessageTarget.REPOSITORY_NODE,
                parameters: {
                    paths: [this._jcrPath],
                    workspaceName: this._workspaceName
                }
            });
        }
        
        Ext.create('Ametys.message.Message', {
            type: Ametys.message.Message.MODIFYING,
            parameters: {
                major: false
            },
            targets: targets
        });
    },
    
    /**
     * Callback function invoked when a property failed to be saved.
     * @param {Ext.form.Basic} form The form that requested the action.
     * @param {Ext.form.action.Action} action The Action class.
     * @param {Function} [callback] The callback function
     * @private
     */
    _saveMetadataFail: function(form, action, callback)
    {
        if (Ext.isFunction(callback))
        {
            callback();
        }
        
        Ametys.log.ErrorDialog.display({
            title: "{{i18n PLUGINS_REPOSITORY_EDIT_METADATA_ERROR_TITLE}}",
            text: "{{i18n PLUGINS_REPOSITORY_EDIT_METADATA_ERROR_TEXT}}",
            details: action.result ? action.result.message : ''
        });
    },
    
    /**
     * Delete a metadata.
     * @param {String} name The metadata's name.
     * @param {Function} [successCb] The callback function to call in case of success
     * @param {Function} [failureCb] The callback function to call in case of failure
     * @private
     */
    _deleteMetadata: function (name, successCb, failureCb)
    {
        Ametys.Msg.confirm(
            "{{i18n PLUGINS_REPOSITORY_DELETE_METADATA_TITLE}}", 
            "{{i18n PLUGINS_REPOSITORY_DELETE_METADATA_CONFIRM}} (" + name + ")", 
            function (btn) {
                if (btn == 'yes')
                {
                    this._doDelete(name, successCb);
                }
            },
            this
        );
    },
    
    /**
     * Delete a metadata (after user confirmation).
     * @param {String} name The property name.
     * @param {Function} [successCb] The callback function to call in case of success
     * @private
     */
    _doDelete: function(name, successCb)
    {
        // FIXME compositePath and richtextPath are not supported here
        Ametys.workspace.repository.actions.RemoveMetadata.act(this._aoId, this._workspaceName, this._compositePath, name, successCb);
    },
    
     /**
     * Read a binary from a binary metadata
     * @param {String} name The binary metadata name.
     * @param {String} type The type (binary, rich-text, file-content)
     * @private
     */
    _downloadBinary: function (name, type)
    {
        var args = {
            'id': this._aoId,
            'cp': this._compositePath,
            'rtp': this._richtextPath 
        }
        
        var url = Ametys.getPluginDirectPrefix('repository') + '/binaryMD/'+ this._workspaceName + '/' + type.toUpperCase() + '/' + name;
        
        Ametys.openWindow(url, args);
    }
    
});