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

/**
 * Singleton class defining the file import function.
 * @private
 */
Ext.define('Ametys.plugins.contentio.ConfigureCSVImport', {
    singleton: true,

    /**
     * @cfg {String} [helperServerRole="org.ametys.plugins.contentio.csv.ImportCSVFileHelper"] The role of server component which prepares the import
     */
    
    /**
     * @property {Ext.form.Panel} _formPanel The dialog box form panel.
     * @private
     */
    _formPanel: null,
    
    /**
     * @property {Ametys.window.DialogBox} _box The action dialog box.
     * @private
     */
    _box: null,

    /**
     * @property {Object} _results The results of the previous dialog box.
     * @private
     */
    _results: null,
    
    /**
     * @property {Object} _parameters The default parameters for the dialog box.
     * @private
     */
    _parameters: null,

    /**
     * @property {Object} _grid The content attributes mapping grid.
     * @private
     */
    _grid: null,
    
    /**
     * Open the configuration dialog for CSV import
     * @param {Object} config the configuration object
     */
    open: function(config)
    {
        this.helperServerRole = config.helperServerRole || "org.ametys.plugins.contentio.csv.ImportCSVFileHelper";
    	this._initialize(config)
	    this._box.show();
    },
    
    /**
     * Create the import dialog box.
     * @param {Object} config the configuration object
     * @private
     */
    _initialize: function(config)
    {
        this._formPanel = this._createFormPanel(config);
        
        this._box = Ext.create('Ametys.window.DialogBox', {
            title: "{{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_CONFIG_DIALOG_TITLE}}",
            iconCls: 'ametysicon-gear39',
            layout: {
	            type: 'vbox',
	            align : 'stretch',
	            pack  : 'start'
	        },
            width: 700,
            maxHeight: 800,
            
            items: [this._formPanel],
            
            closeAction: 'destroy',
            buttons: [{
                text: "{{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_DIALOG_OK}}",
                handler: Ext.bind(this._ok, this, [config], 0),
                scope: this
            }, {
                text: "{{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_DIALOG_CANCEL}}",
                handler: Ext.bind(this._cancel, this, [config], 0),
                scope: this
            }]
        });
        
		SolrHint.init();

        return true;
    },
    
    /**
     * Create the upload dialog's form panel.
     * @param {Object} config the configuration object
     * @return {String} The upload dialog's form panel.
     * @private
     */
    _createFormPanel: function(config)
    {
    	var items = [];
    	
    	items.push({
    		fieldLabel: "* {{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_DIALOG_CREATION_LABEL}}",
			ametysDescription: "{{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_DIALOG_CREATION_DESCRIPTION}}",
			hidden: config['create-action'],
			value: (config['create-action'] === undefined) ? 1 : config['create-action'],
			xtype: "numberfield",
			name: 'createAction',
			allowBlank: false
    	});

    	items.push({
    		fieldLabel: "* {{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_DIALOG_EDIT_LABEL}}",
			ametysDescription: "{{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_DIALOG_EDIT_DESCRIPTION}}",
			hidden: config['edit-action'],
			value: (config['edit-action'] === undefined) ? 2 : config['edit-action'],
			xtype: "numberfield",
			name: 'editAction',
			allowBlank: false
    	});
    	
    	items.push({
    		fieldLabel: "* {{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_DIALOG_CYCLE_LABEL}}",
			ametysDescription: "{{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_DIALOG_CYCLE_DESCRIPTION}}",
			hidden: config['workflow-name'],
			value: (config['workflow-name'] === undefined) ? config.defaultWorkflow : config['workflow-name'],
			xtype: "combobox",
            forceSelection: true,
			store: {
				fields: ['label', 'value'],
				data: config.workflows,
				sorters: [{
			         property: 'label',
			         direction: 'ASC'
			     }]
			},
		    queryMode: 'local',
		    displayField: 'label',
		    valueField: 'value',
		    name: 'workflow',
			allowBlank: false
    	});
        
        items.push(Ametys.cms.language.LanguageDAO.createComboBox({
            name: 'language',
            hidden: config['content-language'],
            value: config['content-language'],
            fieldLabel: "{{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_DIALOG_LANGUAGE_LABEL}}",
            ametysDescription: "{{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_DIALOG_LANGUAGE_DESCRIPTION}}"
        }));
        
        items.push({
            value: "CREATE_AND_UPDATE",
            xtype: "combobox",
            forceSelection: true,
            store: {
                fields: ['label', 'value'],
                data: config.synchronizeModes
            },
            fieldLabel: "* {{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_DIALOG_SYNCHRONIZE_MODE_LABEL}}",
            ametysDescription: "{{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_DIALOG_SYNCHRONIZE_MODE_DESCRIPTION}}",
            queryMode: 'local',
            displayField: 'label',
            valueField: 'value',
            name: 'importMode',
            allowBlank: false
        });
    	
    	this._grid = this._getGridMapping(config);
       
        items.push(this._grid)
    	
        return Ext.create('Ext.form.Panel', {
        	flex: 1,
            bodyStyle: 'padding:5px',
            
            defaultType: 'textfield',

            defaults: {
                cls: 'ametys',
                labelSeparator: '',
                labelAlign: 'right',
                labelWidth: 200,
                anchor: '100%'
            },
            items: items,
            border: false,
            scrollable: 'y'
            
        });
    },
    
    _getGridValues: function()
    {
        var me = this,
        value = [];
        this._grid.getStore().getData().each(function(record) {
            var v = me._getValueFromRecord(record);
            if (v != null)
            {
                v.attributePath = v.attributePath.trim()
            	value.push(v);
            }
        }, this);
        return value;
    },
    
    _getGridMapping: function (config)
    {
    	this._store = Ext.create('Ext.data.Store', {
    	    fields:[
    	    	{name: 'header', type: 'string'},
	            {
                    name: 'attributePath',
                    type: 'string',
                    defaultValue: '',
                    convert: function (value) {
                        return value.replace('/', '.');
                    }
                },
	            {name: 'isId', type: 'boolean', defaultValue: false}
            ],
    	    data: config.mapping
    	});

    	var grid = Ext.create('Ext.grid.Panel', {
    		flex: 1,
            fieldLabel: "{{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_DIALOG_CORRESPONDANCE_LABEL}}",
    	    store: this._store,
    	    disableSelection: true,
    	    viewConfig: {
    	    	markDirty: false
    	    },
    	    columns: [
    	    	{
    	    		text: "{{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_DIALOG_HEADER_LABEL}}",
	            	tooltip: "{{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_DIALOG_HEADER_DESCRIPTION}}", 
    	            flex: 0.8,
    	            dataIndex: 'header' 
    	        },
    	        {
    	            text: "{{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_DIALOG_CONTENT_ATTRIBUTE_LABEL}}", 
                    tooltip: "{{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_DIALOG_CONTENT_ATTRIBUTE_DESCRIPTION}}", 
                    dataIndex: 'attributePath',
                    name: 'contentatt',
                    xtype: 'widgetcolumn', 
                    flex: 1,
                    widget: {
                        xtype: 'solr-code',
                        mode: 'solr-ametys-columns',
                        height: 30,
                        
                        listeners: {
                            'blur': Ext.bind(this._onWidgetChange, this, ['attributePath'], 0)
                        },
                        
                        singleLine: true,
                        ctypes: [config.contentType],
                        cmParams: {
	                        extraKeys: {
	                            'Tab': 'autocomplete'
	                          },
                            hintOptions: {
                                allowAllOption: false,
                                allowCommonOption: false
                            }
                        }
                    }
                },
    	        {
    	        	text: "{{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_DIALOG_ID_LABEL}}", 
    	            tooltip: "{{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_DIALOG_ID_DESCRIPTION}}", 
    	            dataIndex: 'isId',
    	            xtype: 'widgetcolumn', 
    	            widget: {
    	                xtype: 'checkbox',
    	                listeners: {
    	                    'change': Ext.bind(this._onWidgetChange, this, ['isId'], 0)
    	                }
    	            }
    	        }
    	    ]
    	});
    	
    	// We have to update the grid manually, as otherwise the size is falsely computed due to code xtype
    	grid.addListener("afterlayout", function() {
            this.update();
        }, grid, {single: true})
    	
    	return grid;
    },
    
    /**
     * Get the values associated to a record
     * @param {Ext.data.Model} record The record to analyser
     * @return {Object} An object of the data of the record
     */
    _getValueFromRecord: function (record)
    {
    	return Ext.clone(record.getData());
    },

    /**
     * @private
     * Listener when a widget value has changed, in order to update the grid store.
     * @param {String} fieldName The name of the field to update in the record
     * @param {Ext.form.field.Field} field The field
     */
    _onWidgetChange: function(fieldName, field)
    {
        if (field.getWidgetRecord)
        {
            var rec = field.getWidgetRecord();
            rec.set(fieldName, field.getValue());
        }
    },
    
    /**
     * Handle the OK button by submitting the form.
     * @param {Object} config the configuration object
     * @private
     */
    _ok: function(config)
    {
        var form = this._formPanel.getForm();

        var gridValues = this._getGridValues();
        var contentAttributeArray = [];
        var contentIdArray = [];
        var noId = true;
        for(var i = 0; i < gridValues.length; i++) {
            var row = gridValues[i]; 
        	
        	var attributePath = row.attributePath;
        	if(attributePath != "")
    		{
        		if(contentAttributeArray.indexOf(attributePath) == -1)
    			{
        			contentAttributeArray.push(attributePath)
    			}
        		else
    			{
                    Ametys.Msg.show ({
            	        title: "{{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_ERROR_TITLE}}",
                        msg: "{{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_ERROR_SAME_CONTENT}}",
                        buttons: Ext.Msg.OK,
                        icon: Ext.MessageBox.ERROR
            	    });
                    return;
    			}
                var index = attributePath.lastIndexOf(".");  // Gets the last index where a dot occurs
        		if(row.isId)
        		{
        			noId = false;
        			contentIdArray.push(attributePath.substring(0, index))
        		}
                
    		}
        };
        var formValues = this._formPanel.getValues();

        if (noId)
        {
            Ametys.Msg.show ({
    	        title: "{{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_ERROR_TITLE}}",
                msg: "{{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_ERROR_MISSING_ID}}",
                buttons: Ext.Msg.OK,
                icon: Ext.MessageBox.ERROR
    	    });
            return;
        }
        if (!form.isValid())
        {
            return;
        }
		Ametys.data.ServerComm.callMethod({
			role: this.helperServerRole,
			methodName: "validateConfiguration",
			parameters: [config.contentType, formValues, gridValues],
			callback: {
				handler: this._validateCB,
				arguments: {
					config: config, 
					formValues: formValues, 
					gridValues: gridValues
				},
	            scope: this
	        },
			errorMessage: {
				category: this.self.getName(),
                msg: Ext.String.format("{{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_ERROR_TEXT}}", config.fileName)
			}
		});
    },

    _validateCB: function(result, args)
    {
    	if(result.error == undefined)
		{

    		Ametys.data.ServerComm.callMethod({
    			role: this.helperServerRole,
    			methodName: "importContents",
    			priority: Ametys.data.ServerComm.PRIORITY_LONG_REQUEST,
    			parameters: [args.config, args.formValues, args.gridValues],
    			callback: {
    				handler: this._importCB,
    				arguments: {
    				},
    	            scope: this
    	        },
    			errorMessage: {
    				category: this.self.getName(),
                    msg: Ext.String.format("{{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_ERROR_TEXT}}", args.config.fileName)
    			}
    		});
            Ametys.notify({
                type: 'info',
                title: "{{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_DIALOG_TITLE}}",
                description: Ext.String.format("{{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_DIALOG_BACKGROUND}}", args.config.fileName, result.contentTypeName)
            });
            this._box.hide();
		}
    	else
		{
			var errorMsg = "";
			var msg = result.error;
			if (msg == 'missing-id')
			{
				errorMsg = Ext.String.format("{{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_ERROR_MISSING_ID}}", result.details);
			}
			else if (msg == 'missing-id-content')
			{
				errorMsg = Ext.String.format("{{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_ERROR_MISSING_ID_CONTENT}}", result.details[0], result.details[1]);
            }
			else if (msg == 'bad-mapping')
			{
				errorMsg = Ext.String.format("{{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_ERROR_MAPPING_DETAILED}}", result.details[0], result.details[1]);
			}
            else if (msg == 'cant-create-view')
            {
                errorMsg = Ext.String.format("{{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_ERROR_CANT_CREATE_VIEW}}", result.details);
            }
			else if (msg == 'unknown-type')
			{
				errorMsg = Ext.String.format("{{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_ERROR_UNKNOWN_TYPE}}", result.details);
			}
			else if (msg == 'string-as-container')
			{
				errorMsg = Ext.String.format("{{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_ERROR_STRING_AS_CONTAINER}}", result.details);
			}
			else if (msg == 'multiple-content-inside-repeater')
			{
				errorMsg = Ext.String.format("{{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_ERROR_MULTIPLE_CONTAINER_INSIDE_REPEATER}}", result.details[0], result.details[1]);
			}
			else
			{
                errorMsg = Ext.String.format("{{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_ERROR_TEXT}}", args.config.fileName);
			}
			
			Ametys.Msg.show({
				title: "{{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_ERROR_TITLE}}",
				msg: errorMsg,
				buttons: Ext.Msg.OK,
				icon: Ext.Msg.ERROR
			});
		}
    },

    _importCB: function(result)
    {
    	if(!result.error)
		{
    		if(result.nbErrors == 0 && result.nbWarnings == 0)
			{
    			Ametys.notify({
    		        type: 'info',
    		        title: "{{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_DIALOG_TITLE}}",
    		        description: Ext.String.format("{{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_SUCCESS}}", result.fileName, result.importedCount)
    		    });
			}
    		else if(result.nbWarnings == 0)
    		{
    			Ametys.notify({
    		        type: 'warn',
    		        title: "{{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_DIALOG_TITLE}}",
    		        description: Ext.String.format("{{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_PARTIAL_SUCCESS_ERRORS}}", result.fileName, result.importedCount, result.nbErrors)
    		    });
    		}
    		else if(result.nbErrors == 0)
    		{
    			Ametys.notify({
    		        type: 'warn',
    		        title: "{{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_DIALOG_TITLE}}",
    		        description: Ext.String.format("{{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_PARTIAL_SUCCESS_WARNINGS}}", result.fileName, result.importedCount, result.nbWarnings)
    		    });
    		}
    		else
    		{
    			Ametys.notify({
    		        type: 'warn',
    		        title: "{{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_DIALOG_TITLE}}",
    		        description: Ext.String.format("{{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_PARTIAL_SUCCESS_ERRORS_AND_WARNINGS}}", result.fileName, result.importedCount, result.nbWarnings, result.nbErrors)
    		    });
    		}
		}
    	else if(result.error == "no-import")
		{
			Ametys.notify({
		        type: 'error',
		        title: "{{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_DIALOG_TITLE}}",
		        description: Ext.String.format("{{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_ERROR_NO_IMPORT}}", result.fileName)
		    });
		}
    	else
    	{
			Ametys.notify({
		        type: 'error',
		        title: "{{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_DIALOG_TITLE}}",
		        description: Ext.String.format("{{i18n PLUGINS_CONTENTIO_CONTENT_IMPORT_ERROR_TEXT}}", result.fileName)
		    });
    	}
    },
    
    /**
     * Handle the cancel button by hiding the dialog box.
     * @param {Object} config the configuration object
     * @private
     */
    _cancel: function(config)
    {
		Ametys.data.ServerComm.callMethod({
			role: this.helperServerRole,
			methodName: "cancelImport",
			parameters: [config.importId],
			errorMessage: false // This calls is to allow server to do some clean up. No impact on user
		});
        this._box.hide();
    }
    
});