/*
 *  Copyright 2020 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 allows to handle educational booklets for program items.
 */
Ext.define('Ametys.plugins.odf.content.booklet.EducationalBookletAction', {
    singleton: true,
    
    /**
     * Generate an educational booklet for the selected program items.
     * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
     */
    act: function(controller)
    {
        var withPrograms = this._hasProgramInSelection(controller);
        
        if (withPrograms)
        {
            this._createGenerateBox(controller, this._actCB);
        }
        else
        {
            this._generatePDF(controller, {}, this._actCB);
        }
    },
    
    /**
     * @private 
     * Create the box to set the date and archive the educational booklet
     * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
     */
    _createGenerateBox: function(controller, callback, scope)
    {
        if (!this._generateBoxInitialized)
        {
            this._generateFormPanel = Ext.create('Ext.form.Panel', {
                border: false,
                defaults: {
                    cls: 'ametys',
                    labelSeparator: '',
                    labelAlign: 'right',
                    labelWidth: 150,
                    width: '100%',
                    msgTarget: 'side'
                },
                items: [
                    {
                        xtype: 'checkboxfield',
                        name: 'includeSubPrograms',
                        itemId: 'includeSubPrograms',
                        fieldLabel: "{{i18n plugin.odf:PLUGINS_ODF_EDUCATIONAL_BOOKLET_PROGRAMITEM_SCHEDULABLE_INCLUDE_SUBPROGRAMS_LABEL}}",
                        ametysDescription: "{{i18n plugin.odf:PLUGINS_ODF_EDUCATIONAL_BOOKLET_PROGRAMITEM_SCHEDULABLE_INCLUDE_SUBPROGRAMS_DESC}}",
                        inputValue: "true",
                        uncheckedValue: "false"
                    }
                ]
            });

            this._generateBox = Ext.create('Ametys.window.DialogBox', {
                title: "{{i18n plugin.odf:PLUGINS_ODF_EDUCATIONAL_BOOKLET_PROGRAMITEM_GENERATE_BOX_LABEL}}",
                iconCls: "ametysicon-interface decorator-ametysicon-sign-raw-check",
                
                width: 470, 
                scrollable: false,
                
                items: [{
                        xtype: 'component',
                        cls: 'a-text',
                        html: "{{i18n plugin.odf:PLUGINS_ODF_EDUCATIONAL_BOOKLET_PROGRAMITEM_GENERATE_BOX_HINT}}"
                    },
                    this._generateFormPanel
                ],
                
                referenceHolder: true,
                defaultButton: 'validate',
                closeAction: 'hide',
                
                buttons: [{
                    reference: 'validate',
                    text: "{{i18n plugin.odf:PLUGINS_ODF_EDUCATIONAL_BOOKLET_PROGRAMITEM_GENERATE_BOX_OK}}",
                    handler: function () { 
                    
                        var form = this._generateFormPanel.getForm();
				        if (!form.isValid())
				        {
				            return;
				        }
				        
				        var values = form.getValues();
                        
                        var schedulable = controller.schedulable;
                        var params = {};
                        params[schedulable + "$includeSubPrograms"] = values.includeSubPrograms;
        
				        this._generatePDF(controller, params, Ext.bind(callback, scope || this));
                    
                    },
                    scope: this
                }, {
                    text: "{{i18n plugin.odf:PLUGINS_ODF_EDUCATIONAL_BOOKLET_PROGRAMITEM_GENERATE_BOX_CANCEL}}",
                    handler : function () { this._generateBox.close()},
                    scope: this
                }]    
            });
        }
            
        this._generateBoxInitialized = true;    
        this._generateBox.show();
    },
    
    /**
     * @private
     */
    _hasProgramInSelection: function(controller)
    {
        var hasProgram = false;
        Ext.Array.forEach (controller.getMatchingTargets(), function (target) {
            if (Ext.Array.contains(target.getParameters().types, "org.ametys.plugins.odf.Content.program"))
            {
                hasProgram = true;
            }
        });
        return hasProgram;
    },
    
    /**
     * @private
     * Generate the pdf
     * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
     * @param {Object} params The params send to the schedulable
     * @param {Function} callback The callback calling after the PDF generation is done
     */
    _generatePDF: function(controller, params, callback)
    {
        var schedulable = controller.schedulable;
        
        var programItemIds = [];
        var programItemTitles = [];
        Ext.Array.forEach (controller.getMatchingTargets(), function (target) {
            programItemIds.push(target.getParameters().id);
            programItemTitles.push(target.getParameters().title);
        });
        
        params[schedulable + "$programItemIds"] = programItemIds.join();
        params[schedulable + "$includeSubPrograms"] = params[schedulable + "$includeSubPrograms"] || 'false';
        
        var appParams = Ametys.getAppParameters();
        for (var key in appParams)
        {
            params[schedulable + "$" + key] = appParams[key];
        }
        
        controller.serverCall(
            "add",
            [controller.taskLabel || controller.label, controller.taskDescription || controller.description, "NOW", controller.cron, schedulable, params],
            Ext.bind(callback, this),
            {
                scope: this,
                errorMessage: true,
                arguments: {
                    taskLabel: controller.taskLabel || controller.label,
                    programItemTitles: programItemTitles,
                    programItemIds: programItemIds
                }
            }
        );
    },
    
    /**
     * @private
     * Callback invoked after lauching the expoert
     * @param {Object} response The server response
     * @param {Object} args The callback arguments
     * @param {Object[]} params The scheduler parameters
     */
    _actCB: function(response, args, params)
    {
        if (this._generateBox)
        {
	        this._generateBox.close();
        }
        
        if (!response.error)
        {
            Ametys.Msg.show({
                title: "{{i18n PLUGINS_ODF_EDUCATIONAL_BOOKLET_PROGRAMITEM_LAUNCH_GENERATION_TITLE}}",
                msg: "{{i18n PLUGINS_ODF_EDUCATIONAL_BOOKLET_PROGRAMITEM_LAUNCH_GENERATION_MESSAGE}}",
                buttons: Ext.Msg.OK,
                icon: Ext.MessageBox.INFO
            });
            
            this._checkTaskState(response.id, args)
        }
        else
        {
            Ametys.Msg.show({
                title: "{{i18n PLUGINS_ODF_EDUCATIONAL_BOOKLET_PROGRAMITEM_LAUNCH_GENERATION_TITLE}}",
                msg: "{{i18n PLUGINS_ODF_EDUCATIONAL_BOOKLET_PROGRAMITEM_LAUNCH_GENERATION_ERROR}}",
                buttons: Ext.Msg.OK,
                icon: Ext.MessageBox.ERROR
            });
        }
    },
    
    /**
     * @private
     */
    _checkTaskState: function(taskId, args)
    {
        Ametys.plugins.core.schedule.Scheduler.getTasksInformation(
            [[taskId]], 
            this._checkTaskStateCb, 
            {
                errorMessage: Ext.String.format("{{i18n plugin.core-ui:PLUGINS_CORE_UI_TASKS_ADD_TASK_BUTTON_CONTROLLER_CHECK_STATE_ERROR}}", args.taskLabel),
                scope: this, 
                arguments: args
            }
        );
    },
    
    /**
     * @private
     */
    _checkTaskStateCb: function(response, args)
    {
        if (response.length > 0)
        {
            var task = response[0];
            if (task.getState() == "running")
            {
                Ext.defer(this._checkTaskState, 1000, this, [task.getId(), args]);
            }
            else if (task.getState() == "success")
            {
               Ametys.notify({
	                type: 'info',
	                title: args.taskLabel,
	                description: Ext.String.format("{{i18n PLUGINS_ODF_EDUCATIONAL_BOOKLET_PROGRAMITEM_SCHEDULABLE_ENDED_SUCCESS}}", args.programItemTitles.join(", "))
	            });
            }
            else if (task.getState() == "failure")
            {
               Ametys.notify({
                    type: 'error',
                    title: args.taskLabel,
                    description: Ext.String.format("{{i18n PLUGINS_ODF_EDUCATIONAL_BOOKLET_PROGRAMITEM_SCHEDULABLE_ENDED_FAILURE}}", args.programItemTitles.join(", "))
                });
            }
        }
    },
        
    /**
     * Generate and archive an educational booklet for the selected program items.
     * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
     */
    archive: function(controller)
    {
        var withPrograms = this._hasProgramInSelection(controller);
        
        this._createArchiveBox(controller);
        
        var form = this._archiveFormPanel.getForm();
        form.findField('date').setValue(new Date());
        form.findField('includeSubPrograms').setValue(false);
        form.findField('includeSubPrograms').setVisible(withPrograms);
    },
    
    /**
     * @private 
     * Create the box to set the date and archive the educational booklet
     * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
     */
    _createArchiveBox: function(controller)
    {
        if (!this._initialized)
        {
            this._archiveFormPanel = Ext.create('Ext.form.Panel', {
	            border: false,
	            defaults: {
	                cls: 'ametys',
	                labelSeparator: '',
	                labelAlign: 'right',
	                labelWidth: 150,
	                width: '100%',
	                msgTarget: 'side'
	            },
	            items: [
	                {
	                    xtype: 'datetimefield',
	                    name: 'date',
	                    itemId: 'date',
	                    allowBlank: false,
	                    submitFormat: Ext.Date.patterns.ISO8601DateTime,
	                    fieldLabel: "{{i18n plugin.odf:PLUGINS_ODF_EDUCATIONAL_BOOKLET_PROGRAMITEM_ARCHIVE_BOX_DATE_LABEL}}",
	                    ametysDescription: "{{i18n plugin.odf:PLUGINS_ODF_EDUCATIONAL_BOOKLET_PROGRAMITEM_ARCHIVE_BOX_DATE_DESC}}"
	                },
	                {
		                xtype: 'checkboxfield',
		                name: 'includeSubPrograms',
		                itemId: 'includeSubPrograms',
		                fieldLabel: "{{i18n plugin.odf:PLUGINS_ODF_EDUCATIONAL_BOOKLET_PROGRAMITEM_SCHEDULABLE_INCLUDE_SUBPROGRAMS_LABEL}}",
		                ametysDescription: "{{i18n plugin.odf:PLUGINS_ODF_EDUCATIONAL_BOOKLET_PROGRAMITEM_SCHEDULABLE_INCLUDE_SUBPROGRAMS_DESC}}",
		                inputValue: "true",
		                uncheckedValue: "false"
		            }
	            ]
            });

	        this._archiveBox = Ext.create('Ametys.window.DialogBox', {
	            title: "{{i18n plugin.odf:PLUGINS_ODF_EDUCATIONAL_BOOKLET_PROGRAMITEM_ARCHIVE_BOX_LABEL}}",
	            iconCls: "ametysicon-interface decorator-ametysicon-sign-raw-check",
	            
	            width: 470, 
	            scrollable: false,
	            
	            items: [{
	                    xtype: 'component',
	                    cls: 'a-text',
	                    html: "{{i18n PLUGINS_ODF_EDUCATIONAL_BOOKLET_PROGRAMITEM_ARCHIVE_BOX_HINT}}"
	                },
	                this._archiveFormPanel
	            ],
	            
	            defaultFocus: 'date',
	            referenceHolder: true,
	            defaultButton: 'validate',
	            closeAction: 'hide',
	            
	            buttons: [{
	                reference: 'validate',
	                text: "{{i18n plugin.odf:PLUGINS_ODF_EDUCATIONAL_BOOKLET_PROGRAMITEM_ARCHIVE_BOX_OK}}",
	                handler: function () { this._validate(controller)},
	                scope: this
	            }, {
	                text: "{{i18n plugin.odf:PLUGINS_ODF_EDUCATIONAL_BOOKLET_PROGRAMITEM_ARCHIVE_BOX_CANCEL}}",
	                handler : function () { this._archiveBox.close()},
	                scope: this
	            }]    
	        });
	    }
	        
	    this._initialized = true;    
	    this._archiveBox.show();
    },
    
    /**
     * @private
     * Do the archive of the educational booklet for the selected program items.
     * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
     */
    _validate: function(controller)
    {
        var form = this._archiveFormPanel.getForm();
        if (!form.isValid())
        {
            return;
        }
        
        var params = {};
        
        var schedulable = controller.schedulable;
        var values = form.getValues();
        params[schedulable + "$archiveDate"] = values.date;
        params[schedulable + "$workflowActionId"] = controller.getInitialConfig('worflowActionId') || "2222";
        params[schedulable + "$includeSubPrograms"] = values.includeSubPrograms;
        
        this._generatePDF(controller, params, Ext.bind(this._archiveCB, this));
    },
    
    /**
     * Callback to tell that the archive has been launched
     * @param {Object} response The server response
     * @param {Object} args The callback arguments
     * @param {Object[]} params The scheduler parameters
     */
    _archiveCB: function(response, args, params)
    {
        this._archiveBox.close();
    
        if (!response.error)
        {
            Ametys.Msg.show({
                title: "{{i18n PLUGINS_ODF_EDUCATIONAL_BOOKLET_PROGRAMITEM_LAUNCH_ARCHIVE_TITLE}}",
                msg: "{{i18n PLUGINS_ODF_EDUCATIONAL_BOOKLET_PROGRAMITEM_LAUNCH_ARCHIVE_MESSAGE}}",
                buttons: Ext.Msg.OK,
                icon: Ext.MessageBox.INFO
            });
            
            this._checkTaskState(response.id, args)
        }
        else
        {
            Ametys.Msg.show({
                title: "{{i18n PLUGINS_ODF_EDUCATIONAL_BOOKLET_PROGRAMITEM_LAUNCH_ARCHIVE_TITLE}}",
                msg: "{{i18n PLUGINS_ODF_EDUCATIONAL_BOOKLET_PROGRAMITEM_LAUNCH_ARCHIVE_ERROR}}",
                buttons: Ext.Msg.OK,
                icon: Ext.MessageBox.ERROR
            });
        }
    },
    
    /**
	 * Action function to be called by the controller.
	 * Will open the dialog box to edit educational booklets
	 * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
	 */
	edit: function (controller)
	{
        var config = controller.initialConfig;
        var viewName = config.viewName || "educational-booklet";
        // We only edit this to delete educational booklets
        var editWorkflowActionId = config.editWorkflowActionId || 2227;
        
        var target = controller.getMatchingTargets()[0];
		if (target != null)
		{
            var rights = target.getParameters().rights || [];
            var disallowEdition = !Ext.Array.contains(rights, "ODF_Rights_Educational_Booklet_Delete");
			var contentId = target.getParameters().id;
			Ametys.cms.content.ContentDAO.getContent(contentId, Ext.bind(this._editEducationalBooklet, this, [viewName, editWorkflowActionId, disallowEdition], 1));
		}
	},
	
	/**
	 * Open the dialog box to edit educational booklets
	 * @param {Ametys.cms.content.Content} content The content to modify
	 * @param {String} viewName The view name
	 * @param {String} editWorkflowActionId The id of the edit function for educational booklets
	 * @param {Boolean} disallowEdition true if the right to delete educational booklet is not active
     */
	_editEducationalBooklet: function(content, viewName, editWorkflowActionId, disallowEdition)
	{
		var openParams = {
                content: content,
                editWorkflowActionId: editWorkflowActionId,
                iconCls: 'ametysicon-interface decorator-ametysicon-body-part-eye',
                viewName: viewName,
                width: 800,
                labelAlign: 'right',
                title: "{{i18n plugin.odf:PLUGINS_ODF_EDUCATIONAL_BOOKLET_PROGRAMITEM_EDIT_BOX_TITLE}} \""  + content.getTitle() + "\"",
                disallowEdition: disallowEdition
            }
		
		Ametys.cms.uihelper.EditContent.open(openParams, null, this);
	}
});