/*
 *  Copyright 2016 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.
 */
 
/**
 * @private
 * This tool displays the tree of datasources and subnodes
 * Can be parametrized with 'id', an id of a datasource to select and expand it
 */ 
Ext.define('Ametys.plugins.datasourcesexplorer.tool.DatasourcesExplorerTreeTool', {
    extend: 'Ametys.tool.Tool',

    statics: {
        /**
         * The action to open the currently selected datasource in the explorer
         */
        openDatasource: function()
        {
            var id = Ametys.message.MessageBus.getCurrentSelectionMessage().getTarget(Ametys.message.MessageTarget.DATASOURCE).getParameters().id; 
            Ametys.tool.ToolsManager.openTool('uitool-datasources-explorer-tree', {'id': id});
        },
        
        /**
         * The action to open the curretly selected datasoure explorer tree node
         */
        openNode: function()
        {
            var sqlTarget = Ametys.message.MessageBus.getCurrentSelectionMessage().getTarget(Ametys.message.MessageTarget.DATASOURCE_SQLTABLE);
            if (sqlTarget)
            {
                var parameters = sqlTarget.getParameters();
                var datasourceId = parameters.id; 
                var tableName = parameters.name;
                Ametys.tool.ToolsManager.openTool('uitool-datasources-explorer-sqltableview', {'id': datasourceId + '#' + tableName, 'datasource-id': datasourceId, 'table': tableName});
            }
            
            var ldapTarget = Ametys.message.MessageBus.getCurrentSelectionMessage().getTarget(Ametys.message.MessageTarget.DATASOURCE_LDAPNODE);
            if (ldapTarget)
            {
                var parameters = ldapTarget.getParameters();
                var datasourceId = parameters.id;
                var ldapDN = parameters.dn;
                Ametys.tool.ToolsManager.openTool('uitool-datasources-explorer-ldapnodeview', {'id': datasourceId + '#' + ldapDN, 'datasource-id': datasourceId, 'dn': ldapDN});
            }
        }
    },
    
    /** 
     * @private
     * @property {Ext.tree.Panel} _treePanel The main tree panel 
     */
    /** 
     * @private
     * @property {String} _idToSelectOnLoad The node id that will be selected and expanded on next tree load
     */
    
    constructor: function(config)
    {
        this.callParent(arguments);
        
        // Bus messages listeners
        Ametys.message.MessageBus.on(Ametys.message.Message.CREATED, this._onCreated, this);
        Ametys.message.MessageBus.on(Ametys.message.Message.MODIFIED, this._onModified, this);
        Ametys.message.MessageBus.on(Ametys.message.Message.DELETED, this._onDeleted, this);
    },
    
    createPanel: function()
    {
        var store = Ext.create('Ext.data.TreeStore', {
            model: "Ametys.plugins.datasourcesexplorer.tool.DatasourcesExplorerTreeTool.datasource",
            proxy: {
                type: 'ametys',
                plugin: 'datasources-explorer',
                url: 'datasources.json',
                reader: {
                    type: 'json',
                    rootProperty: 'children'
                }
            },
            root: {
                id: 'root',
                text: "{{i18n plugin.datasources-explorer:PLUGINS_DATASOURCES_EXPLORER_ADMINISTRATOR_TREETOOL_ROOT_LABEL}}",
                iconCls: 'ametysicon-query-search',
                expanded: false // loading will be done during refresh
            }
        });
        store.on('load', this._onLoad, this);

        this._treePanel = Ext.create('Ext.tree.Panel', {
            store: store,
            rootVisible: true,
            
            listeners: {
                'selectionchange': Ext.bind(this.sendCurrentSelection, this),
                'itemdblclick': Ametys.plugins.datasourcesexplorer.tool.DatasourcesExplorerTreeTool.openNode
            }
        });
        this._treePanel.getSelectionModel().select([this._treePanel.getRootNode()]);
        
        return this._treePanel;
    },
    
    /**
     * @private
     * Listener when the store is loaded
     * @param {Ext.data.TreeStore} store The tree store
     * @param {Ext.data.TreeModel[]} records An array of records.
     * @param {Boolean} successful True if the operation was successful.
     * @param {Ext.data.Operation} operation The operation that triggered this load.
     * @param {Ext.data.NodeInterface} node The node that was loaded. 
     */
    _onLoad: function(store, records, successful, operation, node)
    {
        if (successful && this._idToSelectOnLoad)
        {
            var node;
            Ext.Array.each(records, function(record) {
                if (record.getId() == this._idToSelectOnLoad)
                {
                    node = record;
                }
            }, this);

            if (node)
            {
                this._treePanel.getSelectionModel().select(node);
                this._treePanel.expandNode(node);
            }
            
            this._idToSelectOnLoad = undefined;
        }
    },
    
    setParams: function(params)
    {
        this.callParent(arguments);
        this._idToSelectOnLoad = params['id'];
        this.refresh();
    },
    
    getMBSelectionInteraction: function() 
    {
        return Ametys.tool.Tool.MB_TYPE_ACTIVE;
    },
    
    
    sendCurrentSelection : function()
    {
        var targets = [];
        
        var records = this._treePanel.getSelection();
        if (records.length > 0 && records[0].getId() != 'root')
        {
            if (records[0].get('nodetype') == 'datasource')
            {
                targets.push({
                    id: Ametys.message.MessageTarget.DATASOURCE,
                    parameters: {
                        id: records[0].get('id'),
                        type: records[0].get('type'),
                        isDefault: records[0].get('isDefault'),
                        isInUse: records[0].get('isInUse')
                    }
                });
            }
            else if (records[0].get('nodetype') == 'sqltable')
            {
                targets.push({
                    id: Ametys.message.MessageTarget.DATASOURCE_SQLTABLE,
                    parameters: {
                        id: records[0].get('datasourceId'),
                        name: records[0].get('id')
                    }
                });
            }
            else if (records[0].get('nodetype') == 'ldapnode')
            {
                targets.push({
                    id: Ametys.message.MessageTarget.DATASOURCE_LDAPNODE,
                    parameters: {
                        id: records[0].get('datasourceId'),
                        dn: records[0].get('id').substring(records[0].get('datasourceId').length + 1)
                    }
                });
            }
        }
        
        Ext.create("Ametys.message.Message", {
            type: Ametys.message.Message.SELECTION_CHANGED,
            targets: targets
        });
    },
    
    refresh: function ()
    {
        this.showRefreshing();
        this._treePanel.getStore().load({
            node: this._treePanel.getRootNode(),
            callback: function() {
                this.showRefreshed();
                this._treePanel.getRootNode().expand();
            },
            scope: this
        });
    },
    
            /**
     * @private
     * Handler function invoked whenever a {@link Ametys.message.Message#CREATED} message is sent out on the 
     * message bus. Add the corresponding record to the grid panel's store.
     * @param {Ametys.message.Message} message the message
     */
    _onCreated: function(message)
    {
        var targets = message.getTargets(Ametys.message.MessageTarget.DATASOURCE);
        if (targets.length > 0)
        {
            this.showOutOfDate();
        }
    },
    
    /**
     * @private
     * Handler function invoked whenever a {@link Ametys.message.Message#MODIFIED} message is sent out on the 
     * message bus. Update the corresponding record of the grid panel's store.
     * @param {Ametys.message.Message} message the message
     */
    _onModified: function (message)
    {
        var targets = message.getTargets(Ametys.message.MessageTarget.DATASOURCE);
        if (targets.length > 0)
        {
            this.showOutOfDate();
        }
    },
    
    /**
     * @private
     * Handler function invoked whenever a {@link Ametys.message.Message#DELETED} message 
     * is sent out on the message bus. Delete the corresponding record from the grid panel's store.
     * @param {Ametys.message.Message} message the message
     */
    _onDeleted: function (message)
    {
        var targets = message.getTargets(Ametys.message.MessageTarget.DATASOURCE);
        for (var i = 0; i < targets.length; i++)
        {
            var record = this._treePanel.getStore().getById(targets[i].getParameters().id);
            this._treePanel.getStore().remove(record);
        }
        
        if (targets.length > 0)
        {
            this.showOutOfDate();
        }
    }
});

Ext.define('Ametys.plugins.datasourcesexplorer.tool.DatasourcesExplorerTreeTool.datasource', {
    extend: 'Ext.data.TreeModel',
    fields: [
        { name: 'id',    type: 'string' },
        { name: 'text',     type: 'string' },
        { name: 'iconCls',     type: 'string' }
    ]
});

Ext.define('Ametys.message.DatasourceMessageTarget', {
    
    override: 'Ametys.message.MessageTarget',
    statics: 
    {
        /**
         * @member Ametys.message.MessageTarget
         * @readonly
         * @property {String} DATASOURCE_SQLTABLE The target of the message is a sql table of a sql data source. The expected parameters are: 
         * @property {String} DATASOURCE_SQLTABLE.id The id of the data source
         * @property {String} DATASOURCE_SQLTABLE.name The name of the sql table
         */
        DATASOURCE_SQLTABLE: "datasource-sqltable",

        /**
         * @member Ametys.message.MessageTarget
         * @readonly
         * @property {String} DATASOURCE_LDAPNODE The target of the message is a ldap node of a ldap data source. The expected parameters are: 
         * @property {String} DATASOURCE_LDAPNODE.id The id of the data source
         * @property {String} DATASOURCE_LDAPNODE.dn The dn of the ldap node
         */
        DATASOURCE_LDAPNODE: "datasource-ldapnode"
    }
});