/*
 *  Copyright 2019 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 is a common class for tools displaying comments and reports on contents
 * @private
 */
Ext.define('Ametys.plugins.cms.content.tool.CommonCommentsAndReportsTool', {
    
    /**
     * Initialize the tool. This function has to be called in the constructor.
     * @protected
     */
    _initialize: function()
    {
        Ametys.message.MessageBus.on(Ametys.message.Message.MODIFIED, this._onReportedObjectModified, this);
        Ametys.message.MessageBus.on(Ametys.message.Message.DELETED, this._onReportedObjectDeleted, this);
    },
    
    /**
     * Get the tree panel
     * @param {Object} specificConfig The panel specific configuration. store is mandatory
     * @return {Ext.tree.Panel} the created tree panel
     * @protected
     */
    _getTreePanel: function(specificConfig)
    {
        var config = { 
            rootVisible: false,
            scrollable: true,
            border: false,
            multiSelect: true,
            stateful: true,
            stateId: this.self.getName() + "$tree",
            
            flex: 1,
            
            columns: [
                 {xtype: 'treecolumn', stateId: 'grid-text', header: "{{i18n PLUGINS_CMS_CONTENT_COMMENTS_AND_REPORTS_VIEW_COLUMN_CONTENT}}", width: 320, sortable: true, dataIndex: 'text'},
                 {stateId: 'grid-contentTitle', header: "{{i18n PLUGINS_CMS_CONTENT_COMMENTS_AND_REPORTS_VIEW_COLUMN_TITLE}}", sortable: true, dataIndex: 'contentTitle', hidden: true},
                 {stateId: 'grid-creationDate', header: "{{i18n PLUGINS_CMS_CONTENT_COMMENTS_AND_REPORTS_VIEW_COLUMN_DATE}}", width: 140, sortable: true, dataIndex: 'creationDate', renderer: Ext.util.Format.dateRenderer(Ext.Date.patterns.FriendlyDateTime)},
                 {stateId: 'grid-validated', header: "{{i18n PLUGINS_CMS_CONTENT_COMMENTS_AND_REPORTS_VIEW_COLUMN_STATE}}", width: 50, sortable: true, dataIndex: 'validated', renderer: this._renderValidated},
                 {stateId: 'grid-nb-reporters', header: "{{i18n PLUGINS_CMS_CONTENT_COMMENTS_AND_REPORTS_VIEW_COLUMN_REPORTED}}", width: 110, sortable: true, dataIndex: 'reportsCount'},
                 {stateId: 'grid-authorName', header: "{{i18n PLUGINS_CMS_CONTENT_COMMENTS_AND_REPORTS_VIEW_COLUMN_AUTHOR}}", width: 170, sortable: true, dataIndex: 'authorName'},
                 {stateId: 'grid-authorEmail', header: "{{i18n PLUGINS_CMS_CONTENT_COMMENTS_AND_REPORTS_VIEW_COLUMN_AUTHOR_EMAIL}}", width: 170, sortable: true, dataIndex: 'authorEmail', hidden: true}
            ],
            
            listeners: {
                selectionchange: this.onSelectComment,
                load: this._onLoad,
                scope: this
            }
        };
        
        Ext.Object.merge(config, specificConfig);
        return Ext.create("Ext.tree.Panel", config);
    },
    
    /**
     * Get the tree store
     * @param {Object} specificConfig the store specific configuration. proxy.methodName and proxy.methodArguments are mandatory.
     * @return {Ext.data.TreeStore} the created tree store
     * @protected
     */
    _getTreeStore: function(specificConfig)
    {
        var config = {
            model: 'Ametys.plugins.cms.content.tool.CommonCommentsAndReportsTool.CommentEntry',
            proxy: {
                type: 'ametys',
                plugin: 'cms',
                role: 'org.ametys.cms.repository.comment.ui.CommentsAndReportsTreeComponent',
                reader: {
                    type: 'json',
                    rootProperty: 'comments'
                }
             },
             multiSelect: true,
                
             root: {
                    allowDrag: false,
                    expanded: true,
                    valid: true,
                    id: 'root',
                    name: 'ametys:comments'
             },
             
             sortOnLoad: true,
             sorters: [{property: 'contentName', direction:'DESC'}, {property: 'creationDate', direction:'DESC'}],
             
             listeners: {
                 beforeload: this._onBeforeLoad,
                 scope: this
             }
        };
        
        Ext.Object.merge(config, specificConfig);
        return Ext.create('Ext.data.TreeStore', config);
    },
    
    /**
     * Send the current comments selection on message bus.
     * @protected
     */
    onSelectComment: function ()
    {
        var targets = [];
        var records = this._treePanel.getSelectionModel().getSelection();

        Ext.Array.each (records, function(record) {
            if (!record.isRoot())
            {
                var contentId = record.get('contentId');
                var commentId = record.get('commentId');
                var reportsCount = record.get('reportsCount');
            
                if (Ext.isEmpty(commentId))
                {
                    targets.push({
                        id: Ametys.message.MessageTarget.CONTENT,
                        parameters: {
                            ids: [contentId]
                        }
                    });
                }
                else
                {
                    targets.push({
                        id: Ametys.message.MessageTarget.COMMENT,
                        parameters: { 
                            id: commentId,
                            content: contentId,
                            reportsCount: reportsCount
                        }
                    });
                }
            }
        });
        
        if (!Ext.isEmpty(targets))
        {
            Ext.create("Ametys.message.Message", {
                type: Ametys.message.Message.SELECTION_CHANGED,
                targets: targets
            });
        }
    },
    
    /**
     * Renderer method to transform records' validated state
     * @param {Object} value The data value
     * @param {Object} metaData A collection of metadata about the current cell
     * @param {Ext.data.Model} record The record for the current row
     * @private
     */
    _renderValidated: function (value, metaData, record)
    {
        if (record.get("commentId") != "")
        {
            if (!value)
            {
                return '<span class="a-grid-glyph ametysicon-forbidden1 not-validated"></span>';
            }
            else if (record.get("reportsCount") > 0)
            {
                return '<span class="a-grid-glyph ametysicon-sign-caution reported"></span>';
            }
            else
            {
                return '<span class="a-grid-glyph ametysicon-check34 validated"></span>';
            }
        }
        else if (record.get("reportsCount") > 0)
        {
            return '<span class="a-grid-glyph ametysicon-sign-caution reported"></span>';
        }
    },
    
    /**
     * Listener when a content or a comment has been modified.
     * @param {Ametys.message.Message} message The modified message.
     * @private
     */
    _onReportedObjectModified: function (message)
    {
        var targets = message.getTargets(function(target) {
            return target.getId() == Ametys.message.MessageTarget.CONTENT
                || target.getId() == Ametys.message.MessageTarget.COMMENT;
        });
        
        if (targets.length > 0)
        {
            this.showOutOfDate();
        }
    },
    
    /**
     * Listener when a content or a comment has been deleted.
     * @param {Ametys.message.Message} message The deletion message.
     * @private
     */
    _onReportedObjectDeleted: function (message)
    {
        var targets = message.getTargets(function(target) {
            return target.getId() == Ametys.message.MessageTarget.CONTENT
                || target.getId() == Ametys.message.MessageTarget.COMMENT;
        });
        
        if (targets.length > 0)
        {
            var me = this;
            Ext.Array.forEach(targets, function(target) {
                
                var nodeId = me._getNodeIdFromTarget(target);
                var node = me._store.getNodeById(nodeId);

                if (node != null)
                {
                    var parentNode = node.parentNode;
                    me._treePanel.getSelectionModel().select([parentNode]);
                    node.remove();
                }
            });
        }
    },
    
    /**
     * Retrieves the node identifier corresponding to the given target
     * @param {Ametys.message.MessageTarget} target the target
     * @return {String} the node identifier
     */
    _getNodeIdFromTarget: function(target)
    {
        var targetParameters = target.getParameters();
        
        var contentId = targetParameters.id;
        var commentId = "";
        if (target.getId() == Ametys.message.MessageTarget.COMMENT)
        {
            contentId = targetParameters.content;
            commentId = targetParameters.id;
        }
        
        return contentId + ";" + commentId;
    }
});

/**
 * This class is the model for entries in the grid of the comments tool
 * @private
 */
Ext.define("Ametys.plugins.cms.content.tool.CommonCommentsAndReportsTool.CommentEntry", {
    extend: 'Ext.data.TreeModel',
    
    fields: [
        {name: 'commentId', type: 'string' }, 
        {name: 'contentId', type: 'string' }, 
        {name: 'reportsCount', type: 'int' },
        {name: 'validated', type: 'boolean'},
        {name: 'creationDate', type: 'date', dateFormat: 'c'},
        {name: 'authorName', type: 'string'},
        {name: 'authorEmail', type: 'string'},
        {name: 'contentTitle', type: 'string'},
        {name: 'authorUrl', type: 'string'},
        {name: 'authorIsEmailHidden', type: 'boolean'},
        {
           name: 'iconCls',
           depends: ['commentId'],
           calculate: function (data)
           {
               if (!Ext.isEmpty(data.commentId))
               {
                   return 'ametysicon-interface-1';
               }
               else
               {
                   return 'ametysicon-text70';
               }
           }
        },
        {name: 'text'},
        {
            name: 'id', 
            calculate: function (data) {
                return data.contentId + ';' + data.commentId
            }
        }
    ]
});