/*
 *  Copyright 2018 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.
 */

/**
 * A log tool displayed logs from a file.
 * @private  
 */
Ext.define('Ametys.plugins.coreui.log.ArchivedLogTool', {
    extend: "Ametys.plugins.coreui.log.AbstractLogTool",

    statics: {
        /**
         * @property {Number} DEFAULT_EVENTS_LIMIT The default max number of events to display
         * @private
         * @readonly 
         */
        DEFAULT_EVENTS_LIMIT: 1000
    },
    
    constructor: function(config)
    {
        this.callParent(arguments);
        
        this._detailsTpl = new Ext.XTemplate(
            "<tpl if='timestamp'><b>{{i18n PLUGINS_CORE_UI_TOOLS_SERVERLOGS_TIMESTAMP_TEXT}}</b> {timestamp}<br /></tpl>",
            "<tpl if='thread'><b>{{i18n PLUGINS_CORE_UI_TOOLS_SERVERLOGS_THREAD_TEXT}}</b> {thread}<br /></tpl>",
            "<tpl if='level'><b>{{i18n PLUGINS_CORE_UI_TOOLS_SERVERLOGS_LEVEL_TEXT}}</b> {level}<br /></tpl>",
            "<tpl if='category'><b>{{i18n PLUGINS_CORE_UI_TOOLS_SERVERLOGS_CATEGORY_TEXT}}</b> {category}<br /></tpl>",
            "<tpl if='message'><b>{{i18n PLUGINS_CORE_UI_TOOLS_SERVERLOGS_MESSAGE_TEXT}}</b> {message}<br /></tpl>",
            "<tpl if='callstack'><br /><b>{{i18n PLUGINS_CORE_UI_TOOLS_SERVERLOGS_CALLSTACK_TEXT}}</b><br />{callstack}</tpl>"
        );
    },
    
    getMBSelectionInteraction: function()
    {
        return Ametys.tool.Tool.MB_TYPE_ACTIVE;
    },
    
    sendCurrentSelection: function()
    {
        Ext.create('Ametys.message.Message', {
            type: Ametys.message.Message.SELECTION_CHANGED,
            targets: {
                id: Ametys.message.MessageTarget.LOG_CATEGORY,
                parameters: {
                    ids: ['root']
                }
            }
        });
    },
    
	/**
     * @inheritdoc
     * @param {Object} params the parameters
     * @param {String} params.path The path of the log file
     * @param {String} [params.title=params.path] The title of the tool
     * @param {String} [params.limit=1000] The limit of event to display
     */ 
    setParams: function(params)
    {
        params.title = params.title || params.path;
        params.limit = params.limit || Ametys.plugins.coreui.log.ArchivedLogTool.DEFAULT_EVENTS_LIMIT;
        
        this.callParent(arguments);
        
        this.setTitle(params.title);
        
        if (this.getLimit() >= 0)
        {
            this.setDescription(Ext.String.format("{{i18n PLUGINS_CORE_UI_TOOLS_ARCHIVEDLOGS_DESCRIPTION_WITH_LIMIT}}", this.getLimit(), params.title));
        }
        else
        {
            this.setDescription(Ext.String.format("{{i18n PLUGINS_CORE_UI_TOOLS_ARCHIVEDLOGS_DESCRIPTION}}", params.title));
        }
        
        this.getStore().getProxy().setExtraParam('logFileName', params.path);
        this.getStore().getProxy().setExtraParam('limit', this.getLimit());

        this.showOutOfDate();
    },
    
    refresh: function()
    {
    	this.showUpToDate();
    	this.getStore().load();
    },
    
    getStore: function()
    {
    	if (!this._store)
    	{
	        this._store = Ext.create('Ext.data.Store', {
	            model: 'Ametys.plugins.coreui.log.archivedlogtool.ArchivedLogEntry',
	            remoteFilter: true,
	            proxy: {
	                type: 'ametys',
	                methodName: 'getLogLines',
	                methodArguments: ['logFileName', 'filter', 'limit'],
	                serverCaller: this,
	                reader: {
	                    type: 'json',
	                    rootProperty: 'lines'
	                }
	            },
	            listeners: {
	                'load': {fn: this._onLoad, scope: this}
	            }
	        });
    	}
        
        return this._store;
    },

    getColumns: function()
    {
        return [{
                stateId: 'grid-timestamp',
                header: "{{i18n PLUGINS_CORE_UI_TOOLS_SERVERLOGS_TIMESTAMP_HEADER}}",
                width: 130,
                sortable: false,
                dataIndex: 'timestamp',
                renderer: Ext.bind(this.datetimeRenderer, this)
            },
            {
                stateId: 'grid-thread',
                header: "{{i18n PLUGINS_CORE_UI_TOOLS_SERVERLOGS_THREAD_HEADER}}",
                width: 150,
                sortable: false,
                dataIndex: 'thread',
                hidden: true,
                renderer: Ext.bind(this.defaultRenderer, this),
                filter: {
                    type: 'string'
                }
            },
            {
                stateId: 'grid-level',
                header: "{{i18n PLUGINS_CORE_UI_TOOLS_SERVERLOGS_LEVEL_HEADER}}",
                width: 75,
                sortable: false,
                dataIndex: 'level',
                renderer: Ext.bind(this.defaultRenderer, this),
                filter: {
                    type: 'list',
                    store: Ext.create('Ext.data.Store', {
                        fields: ['id','text'],
                        data: [
                           {id: "DEBUG", text: 'Debug'},
                           {id: "INFO", text: 'Info'},
                           {id: "WARN", text: 'Warn'},
                           {id: "ERROR", text: 'Error'},
                           {id: "FATAL", text: 'Fatal'}
                        ]
                    })
                }
            },
            {
                stateId: 'grid-category',
                header: "{{i18n PLUGINS_CORE_UI_TOOLS_SERVERLOGS_CATEGORY_HEADER}}",
                width: 250,
                flex: 0.25,
                sortable: false,
                dataIndex: 'category',
                renderer: Ext.bind(this.defaultRenderer, this),
                filter: {
                    type: 'string'
                }
            },
            {
                stateId: 'grid-message',
                header: "{{i18n PLUGINS_CORE_UI_TOOLS_SERVERLOGS_MESSAGE_HEADER}}",
                width: 400,
                sortable: false,
                dataIndex: 'message',
                flex: 0.5,
                renderer: Ext.bind(this.defaultRenderer, this),
                filter: {
                    type: 'string'
                }
            },
            {
                stateId: 'grid-callstack',
                header: "{{i18n PLUGINS_CORE_UI_TOOLS_SERVERLOGS_CALLSTACK_HEADER}}",
                width: 100,
                sortable: false,
                dataIndex: 'callstack',
                hidden: true,
                renderer: Ext.bind(this.defaultRenderer, this),
                filter: {
                    type: 'string'
                }
            }];
    },
    
    getDetailsText: function(records)
    {
        var record = records[0];
        
        var data = {
            timestamp: Ext.Date.format(new Date(record.get("timestamp")), "d/m H:i:s.u"),
            level: record.get('level'),
            category: record.get('category'),
            message: Ext.String.htmlEncode(record.get('message')),
            thread: record.get('thread'),
            callstack: record.get('callstack') ? Ext.String.stacktraceJavaToHTML(record.get('callstack')) : null
        };
        
        return this._detailsTpl.applyTemplate(data);
    },

    getDockedItems: function()
    {
        return [{
            dock: 'top',
            xtype: 'component',
            hidden: true,
            itemId: 'moreitems-hint',
            layout: 'fit',
            cls: 'x-component-tool-hintmessage',
            html: Ext.String.format("{{i18n PLUGINS_CORE_UI_TOOLS_ARCHIVEDLOGS_OVER_HINT}}", this.getLimit())
        }];
    },
    
    getRowClass: function(record)
    {
        return "msg-level-" + record.get('levelCode');
    },
    
    /**
     * Default renderer for the columns. Apply the coloration.
     * @param {Number} value The level
     * @param {Object} metadata A collection of metadata about the current cell; can be used or modified by the renderer. Recognized properties are: tdCls, tdAttr, and style
     * @param {Ext.data.Model} record The record for the current row
     * @private
     */
    defaultRenderer: function(value, metadata, record)
    {
        return Ext.String.htmlEncode(value);
    },
    
    /**
     * Datetime renderer for the columns. Format the timestamp into a human readable time.
     * @param {Number} value The level
     * @param {Object} metadata A collection of metadata about the current cell; can be used or modified by the renderer. Recognized properties are: tdCls, tdAttr, and style
     * @param {Ext.data.Model} record The record for the current row
     * @private
     */
    datetimeRenderer: function(value, metadata, record)
    {
        return Ext.Date.format(new Date(value), "d/m H:i:s.u");
    },
    
    /**
     * Function called after loading results
     * @param {Ext.data.Store} store The store
     * @param {Ext.data.Model[]} records An array of records
     * @param {Boolean} successful True if the operation was successful.
     * @private
     */
    _onLoad: function (store, records, successful)
    {
    	var hint = this.grid.getDockedItems("#moreitems-hint")[0];
    	if (hint)
    	{
    		var limit = this.getLimit();
			if (limit >= 0 && records.length >= limit)
			{
				hint.update(Ext.String.format("{{i18n PLUGINS_CORE_UI_TOOLS_ARCHIVEDLOGS_OVER_HINT}}", this.getLimit()));
				hint.show();
			}
			else
			{
				hint.hide();
			}
    	}
    },
    
    /**
     * Function to get the limit of displayed events
     * @private
     */
    getLimit: function ()
    {
    	return this.getParams().limit;
    }
});