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

/**
 * Singleton class to handle the branch action on a survey page.
 * @private
 */
 Ext.define('Ametys.plugins.survey.BranchAction', {
    singleton: true,
    
    /**
     * @private
     * @property {Ametys.window.DialogBox} _branchesDialogBox The dialog box for creating/editing branches.
     */
     
    /**
     * @private
     * @property {Ext.panel.Panel} _rulesPanel The rules panel of the dialog box.
     */
     
    /**
     * @private
     * @property {Boolean} _initialized Indicates if the dialog box is initialized.
     */
    
    /**
     * @private
     * @property {Object} _rulesDataviews A map containing the dataviews of the rules. The key is the question id or page id (for inconditional rule).
     */
    
    /**
     * @private
     * @property {Ext.XTemplate} _questionRuleTpl The template used for the question dataview
     */
    _questionRuleTpl: Ext.create('Ext.XTemplate', [
        '<tpl for=".">',
            '<div class="rule-wrap {cls}" id="rule-{option}">',
                '<button onclick="Ametys.plugins.survey.BranchAction._deleteRule(\'{qId}\', \'{option}\'); return false;" title="{{i18n PLUGINS_SURVEY_BRANCH_DELETE_RULE}}"><span class="ametysicon-delete30"></span></button>',
                '{{i18n PLUGINS_SURVEY_BRANCH_HINT}}<b>{optionLabel}</b>,<br/>',
                '<tpl if="type == \'JUMP\'">',
                    '{{i18n PLUGINS_SURVEY_BRANCH_HINT_JUMP}} <b>{pageLabel}</b><br/>',
                '</tpl>',
                '<tpl if="type == \'FINISH\'">',
                    '{{i18n PLUGINS_SURVEY_BRANCH_HINT_FINISH}}',
                '</tpl>',
            '</div>',
        '</tpl>'
    ]),
    
    /**
     * @private
     * @property {Ext.XTemplate} _pageRuleTpl The template used for the page dataview
     */
    _pageRuleTpl: Ext.create('Ext.XTemplate', [
        '<tpl for=".">',
            '<div class="rule-wrap" id="rule-{pageId}">',
                '<button onclick="Ametys.plugins.survey.BranchAction._deleteInconditionalRule(\'{pageId}\'); return false;" title="{{i18n PLUGINS_SURVEY_BRANCH_DELETE_RULE}}"><span class="ametysicon-delete30"></span></button>',
                '{{i18n PLUGINS_SURVEY_BRANCH_HINT_NO_RULE}},<br/>',
                '<tpl if="type == \'JUMP\'">',
                    '{{i18n PLUGINS_SURVEY_BRANCH_HINT_JUMP}} <b>{pageLabel}</b><br/>',
                '</tpl>',
                '<tpl if="type == \'FINISH\'">',
                    '{{i18n PLUGINS_SURVEY_BRANCH_HINT_FINISH}}',
                '</tpl>',
            '</div>',
        '</tpl>'
    ]),
    
    /**
     * Enables to manage branches on a page through a dilog box.
     * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function.
     */
    act: function(controller)
    {
        var pageTarget = controller.getMatchingTargets()[0];
        this._surveyId = pageTarget.getParameters().surveyId;
        this._pageId = pageTarget.getParameters().id;
        
        Ametys.cms.survey.PageDAO.isLastPage([this._pageId], this._doAct, {scope: this, arguments: [pageTarget]});
    },
    
    /**
     * Shows the branch dialog box, or a message if this is the last page. 
     * @param {Boolean} isLast True if the current page is the last one.
     * @param {Array} args The arguments.
     * @private
     */
    _doAct: function(isLast, args)
    {
        var pageTarget = args[0];
        if (isLast)
        {
            Ametys.Msg.show({
                title: "{{i18n PLUGINS_SURVEY_BRANCH_LABEL}}",
                msg: "{{i18n PLUGINS_SURVEY_BRANCH_LAST_PAGE}}",
                buttons: Ext.Msg.OK,
                icon: Ext.MessageBox.INFO
            });
            return;
        }
        
        this._delayedInitialize();
        
        // Load the branches
        Ametys.cms.survey.PageDAO.getBranches([this._pageId], this._getBranchesCb, {scope: this});
    },
    
    /**
     * Initializes the dialog box. 
     * @private
     */
    _delayedInitialize: function()
    {
        if (!this._initialized)
        {
            this._rulesPanel = Ext.create('Ext.panel.Panel', {
                scrollable: 'vertical',
                layout: 'anchor',
                flex: 1,
                defaults: {
                	anchor: '95%'
                }
            });
            
            this._branchesDialogBox = Ext.create('Ametys.window.DialogBox', {
                title: "{{i18n PLUGINS_SURVEY_BRANCH_LABEL}}",
                iconCls: "ametysicon-turn-right5",
                
                width: 650,
                maxHeight: 600,
                layout: {
		            type: 'vbox',
		            align: 'stretch' 
		        },
		        scrollable: false,
                border: false,
                
                items: [
                    {
                        xtype: 'component',
                        cls: 'a-text',
                        html: "{{i18n PLUGINS_SURVEY_BRANCH_HELP_TEXT}}"
                    },
                    this._rulesPanel
                ],
                
                closeAction: 'hide',
                
                referenceHolder: true,
                defaultButton: 'validate',
                
                buttons: [{
                	reference: 'validate',
                    text: "{{i18n PLUGINS_SURVEY_DIALOG_BUTTON_OK}}",
                    handler: function() {this._branchesDialogBox.close();},
                    scope: this
                }]   
            });
            
            this._initialized = true;
        }
    },
    
    /**
     * Shows the branch dialog box after retrieving the branches from the server.
     * @param {Object} branches The branches retrieved from the server.
     * @private
     */
    _getBranchesCb: function(branches)
    {
        this._rulesDataviews = {};
        this._rulesPanel.removeAll();
        
        var questions = branches.questions;
        
        var hintHtml = "{{i18n PLUGINS_SURVEY_BRANCH_QUESTIONS_LIST_HINT_TEXT}}";
        if (questions.length > 0)
        {
            hintHtml += "{{i18n PLUGINS_SURVEY_BRANCH_QUESTIONS_LIST_NB_HINT_TEXT_1}}" + questions.length + "{{i18n PLUGINS_SURVEY_BRANCH_QUESTIONS_LIST_NB_HINT_TEXT_2}}";
        }
        else
        {
            hintHtml += "{{i18n PLUGINS_SURVEY_BRANCH_NO_QUESTION_LIST_HINT_TEXT}}";
        }
        
        var me = this;
        
        me._rulesPanel.add({
            xtype: 'component',
            cls: 'a-text',
            html: hintHtml
        });
        
        // Add questions
        Ext.Array.each (questions, function (question) {
        	me._rulesPanel.add(me._createQuestionRulePanel(question));
        });
        
        // Inconditional jump
        me._rulesPanel.add({
            xtype: 'component',
            cls: 'a-text',
            html: "{{i18n PLUGINS_SURVEY_BRANCH_UNCONDITIONAL_JUMP_HINT_TEXT}}"
        });
        
        me._rulesPanel.add(me._createInconditionalJumpPanel(branches));
        
        this._branchesDialogBox.show();
    },
    
    /**
     * @private
     * Create a question rules item.
     * @param {Object} question the question
     */
    _createQuestionRulePanel: function (question)
    {
    	var qId = question.id;
        var qNumber = question.number;
        var qTitle = "Q." + qNumber + " - " + question.title;
        
        var rulesStore = Ext.create('Ext.data.Store', {
            fields: ['qId', 'option', 'optionLabel', 'type', 'page', 'pageLabel', 'cls']
        });
        
        Ext.Array.each (question.rules, function (rule, index) {
        	rulesStore.add({
                qId: qId,
                option: rule.option,
                optionLabel: rule.optionLabel,
                type: rule.type,
                page: rule.page,
                pageLabel: rule.pageName,
                cls: index % 2 == 0 ? ' even' : ' odd'
            });
        });
        
        var dataview = Ext.create('Ext.view.View', {
            // title: qTitle,
            store: rulesStore,
            tpl: this._questionRuleTpl,
            height: 'auto',
            overItemCls:'x-view-over',
            itemSelector:'div.rule-wrap'
        });
        
        this._rulesDataviews[qId] = dataview;
        
    	return Ext.create ('Ext.Panel', {
            xtype: 'panel',
            style: {
            	marginBottom: '15px'
            },
            
            header: {
        		titlePosition: 1,
        		title: qTitle,
        		style: "border-width: 1px !important"
        	},
            
            ui: 'light',
            border: true,
            collapsible: true,
            collapsed: false,
            titleCollapse: true,
            
            items: [dataview],
            
            tools: [{
	            type: 'plus',
	            qtip: "{{i18n PLUGINS_SURVEY_ADD_RULE_LABEL}}", 
	            handler: Ext.bind(this._addRule, this, [qId]),
	            scope: this
	        }]
        });
    },
    
    /**
     * @private
     * Create a item for inconditional jump
     * @param {Object} branches the branches
     */
    _createInconditionalJumpPanel: function (branches)
    {
    	 var store = Ext.create('Ext.data.Store', {
             fields: ['pageId', 'type', 'page', 'pageLabel']
         });
         
         if (branches.rule != null)
         {
        	 store.add({
                 pageId: this._pageId,
                 type: branches.rule.type,
                 page: branches.rule.page,
                 pageLabel: branches.rule.pageName
             });
         }
         
         var dataview = Ext.create('Ext.view.View', {
             // title: qTitle,
             store: store,
             tpl: this._pageRuleTpl,
             height: 'auto',
             overItemCls:'x-view-over',
             itemSelector:'div.rule-wrap'
         });
         
         this._rulesDataviews[this._pageId] = dataview;
         
         return Ext.create('Ext.Panel', {
            xtype: 'panel',
            
            header: {
        		titlePosition: 1,
        		title: "{{i18n PLUGINS_SURVEY_BRANCH_INCONDITIONAL_JUMP}}",
        		style: "border-width: 1px !important"
        	},
            
            ui: 'light',
            border: true,
            collapsible: true,
            titleCollapse: true,
            collapsed: false,
            
            items:[dataview],
            
            tools: [{
	            type: 'plus',
	            qtip: "{{i18n PLUGINS_SURVEY_ADD_RULE_LABEL}}", 
	            handler: this._addInconditionalRule,
	            scope: this
	        }]
    	});
    },
    
    /**
     * Opens a dialog box for creating a new rule.
     * @param {String} qId The question id
     * @private
     */
    _addRule: function(qId)
    {
        Ametys.plugins.survey.RulesDialog.open({
            mode: 'newRule',
            surveyId: this._surveyId,
            pageId: this._pageId,
            questionId: qId,
            callback: Ext.bind(this._loadQuestionRules, this, [qId])
        });
    },
    
    /**
     * Deletes the selected option.
     * @param {String} qId The question id
     * @param {String} option The option to delete
     * @private
     */
    _deleteRule: function(qId, option)
    {
        Ext.create('Ext.window.MessageBox', {
            closeAction: 'destroy',
            alwaysOnTop: true
        }).confirm(
                "{{i18n PLUGINS_SURVEY_BRANCH_DELETE_RULE}}",
                "{{i18n PLUGINS_SURVEY_BRANCH_DELETE_RULE_CONFIRM}}",
                Ext.bind(this._doDelete, this, ['question', qId, option], 1),
                this    
        );
    },
    
    /**
     * Opens a dialog box for creating an inconditional rule.
     * @private
     */
    _addInconditionalRule: function()
    {
        Ametys.plugins.survey.RulesDialog.open({
            mode: 'inconditionalJump',
            surveyId: this._surveyId,
            pageId: this._pageId,
            callback: Ext.bind(this._loadPageRule, this, [this._pageId])
        });
    },
    
    /**
     * Deletes the selected inconditional rule.
     * @param {String} pageId The page id
     * @private
     */
    _deleteInconditionalRule: function(pageId)
    {
        Ext.create('Ext.window.MessageBox', {
            closeAction: 'destroy',
            alwaysOnTop: true
        }).confirm("{{i18n PLUGINS_SURVEY_BRANCH_DELETE_RULE}}",
                "{{i18n PLUGINS_SURVEY_BRANCH_DELETE_RULE_CONFIRM}}",
                Ext.bind(this._doDelete, this, ['page', pageId], 1),
                this
        );
    },
    
    /**
     * @private
     * The action to perform when the user clicks on a button from the removing message box.
     * @param {String} btn The pressed button. Can only be 'yes'/'no'
     * @param {String} type The type of deletion. Can only be 'question'/'page'.
     * @param {String} id the question id (for type 'question') or the page id (for type 'page')
     * @param {String} [option] The option to delete
     */
    _doDelete: function(btn, type, id, option)
    {
        if (btn == 'yes')
        {
            if (type == 'question')
            {
                Ametys.cms.survey.QuestionDAO.deleteRule([id, option], this._doDeleteCb, {scope: this, arguments: [type]});
            }
            else if (type == 'page')
            {
                Ametys.cms.survey.PageDAO.deleteRule([id], this._doDeleteCb, {scope: this, arguments: [type]});
            }
        }
    },
    
    /**
     * The callback function after {@link #_doDelete} succeeded.
     * @param {Object} response The server response
     * @param {Array} args The arguments
     * @param {Array} params The callback parameters
     * @private
     */
    _doDeleteCb: function(response, args, params)
    {
        if (args[0] == 'question')
        {
            this._loadQuestionRules(params[0]);
        }
        else
        {
            this._loadPageRule(params[0]);
        }
    },
    
    /**
     * Loads and displays the question rules.
     * @param {String} qId The question id
     * @private
     */
    _loadQuestionRules: function(qId)
    {
        Ametys.cms.survey.QuestionDAO.getRules([qId, 0], this._loadQuestionRulesCb, {scope: this});
    },
    
    /**
     * The callback function after {@link #_loadQuestionRules} succeeded.
     * @param {Object} response The server response
     * @param {Array} args The arguments
     * @param {Array} params The callback parameters
     * @private
     */
    _loadQuestionRulesCb: function(response, args, params)
    {
        var qId = params[0];
        
        var dataview = this._rulesDataviews[qId];
        var store = dataview.getStore();
        store.removeAll();
        
        for (var i = 0; i < response.rules.length; i++) {
            store.add({
                qId: qId,
                option: response.rules[i].option,
                optionLabel: response.rules[i].optionLabel,
                type: response.rules[i].type,
                page: response.rules[i].page,
                pageLabel: response.rules[i].pageName
            });
        }
    },
    
    /**
     * Loads and displays the page rule.
     * @param {String} pageId The page id
     * @private
     */
    _loadPageRule: function(pageId)
    {
        Ametys.cms.survey.PageDAO.getRule([pageId], this._loadPageRuleCb, {scope: this});
    },
    
    /**
     * The callback function after {@link #_loadPageRule} succeeded.
     * @param {Object} response The server response
     * @param {Array} args The arguments
     * @param {Array} params The callback parameters
     * @private
     */
    _loadPageRuleCb: function(response, args, params)
    {
        var pageId = params[0];
        
        var dataview = this._rulesDataviews[pageId];
        var store = dataview.getStore();
        store.removeAll();
        
        if (response != null)
        {
            store.add({
                pageId: pageId,
                type: response.type,
                page: response.page,
                pageLabel: response.pageName
            });
        }
    }
    
 });