/*
 *  Copyright 2021 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 tool displays a preview of a form.
 * @private
 */
 Ext.define('Ametys.plugins.forms.tool.FormsPreviewTool', {
    extend: 'Ametys.tool.Tool',
    
    /**
     * @private
     * @property {String} _formId The id of the form displayed.
     */
    
    /**
     * @private
     * @property {String} _currentPageId The id of the current page in the form displayed.
     */
    
    /**
     * @private
     * @property {String} _currentQuestionId The id of the current question in the page displayed.
     */
    
    /**
     * @private
     * @property {String} _mainPanel The main panel of this tool.
     */
    
    statics:
    {
        /**
         * @readonly
         * @property {String} SELECTION_PREVIEW_CHANGED Event when the selection on preview has changed. 
         * The target and subtarget is the new element selected and can be of any type.
         */
        SELECTION_PREVIEW_CHANGED: "selectionPreviewChanged",
    },
    
    constructor: function(config)
    {
        this.callParent(arguments);
        
        Ametys.message.MessageBus.on(Ametys.message.Message.CREATED, this._onMessageCreated, this);
        Ametys.message.MessageBus.on(Ametys.message.Message.MODIFIED, this._onMessageModifiedOrMoved, this);
        Ametys.message.MessageBus.on(Ametys.message.Message.DELETED, this._onMessageDeleted, this);
        Ametys.message.MessageBus.on(Ametys.message.Message.SELECTION_CHANGED, this._onMessageSelectionChanged, this);
        Ametys.message.MessageBus.on(Ametys.message.Message.MOVED, this._onMessageModifiedOrMoved, this);
    },
    
    createPanel: function()
    {
        this.setIconDecorator(null);
        
        this._iframe = Ext.create("Ext.ux.IFrame", {}); 
        
        return Ext.create('Ext.Panel', { 
            cls: 'form-preview-tool',
            border: false,
            layout: 'border',
            scrollable: false,
            
            dockedItems: [{
                dock: 'top',
                xtype: 'container',
                layout: {
                    type: 'vbox',
                    align: 'stretch'
                },
                border: false,
                cls: 'hint',
                
                defaults : {
                    cls: 'ametys',
                },
                
                items: [
                    {
                      xtype: 'container',
                      layout: {
                          type: 'hbox',
                          align: 'stretch'
                      },
                      items: [
                        {
                            xtype: 'component',
                            style: {
                                lineHeight: '25px'
                            },
                            html: "{{i18n PLUGINS_FORMS_PREVIEW_TOOL_INTRO_PART1}}",
                        },
                        this._createServiceViewComboBox()
                      ]
                    },
                    {
                        xtype: 'component',
                        html: "{{i18n PLUGINS_FORMS_PREVIEW_TOOL_INTRO_PART2}}",
                    }
                ]
            }],
            
            items: [
                this._iframe
            ]
        });
    },
    
    /**
     * Create a service view combo box
     * @private
     */
    _createServiceViewComboBox: function()
    {
        this._serviceViewStore = Ext.create('Ext.data.Store', {
            proxy: {
                type: 'ametys',
                role: 'org.ametys.plugins.forms.dao.FormDAO',
                methodName: 'getFormDisplayViews',
                methodArguments: ['formId', 'siteName', 'language'],
                reader: {
                    type: 'json'
                }
            },
            
            autoLoad: true,
            sortOnLoad: true,
            sorters: [{property: 'label', direction:'ASC'}],
            
            listeners: {
                load: {fn: this._onLoad, scope: this}
            }
        });
        
        this._combo = Ext.create('Ext.form.field.ComboBox', {
            cls: 'ametys',
            forceSelection: true,
            editable: false,
            queryMode: 'local',
            allowBlank: false,
            
            store: this._serviceViewStore,
            
            hidden: true,
            valueField: 'id',
            displayField: 'label',
            fieldLabel:"{{i18n PLUGINS_FORMS_PREVIEW_TOOL_SELECT_VIEW_LABEL}}",
            labelWidth: 267,
            labelAlign: "right",
            listeners: {
                change: {fn: this.refresh, scope: this}
            }
        });

        return this._combo;
    },

    /**
     * Listener called after load form display view combo box
     * @param {Object} [store] The store
     * @param {Object[]} [viewNames] The viewNames
     * @private
     */
    _onLoad: function(store, viewNames)
    {
        if (viewNames == null) // there is no view in service
        {
            this.close();
            return;
        }
        if (viewNames.length > 0)
        {
            var defaultViewName = viewNames[0];
            for (var i in viewNames)
            {
                if (viewNames[i].get("isDefault"))
                {
                    defaultViewName = viewNames[i];
                }
            }
            this._combo.setValue(defaultViewName);
        }
        
        if (viewNames.length > 1)
        {
            this._combo.show();
        }
    },
    
    setParams: function(params)
    {
        this.callParent(arguments);
        
        this._formId = params.id;
        this._currentPageId = params.pageId; 
        this._currentQuestionId = params.questionId;
        //Ext.bind(this._goToPage, this, [params.pageId, params.questionId])
        this._refreshWithCallback(Ext.emptyFn);
        
        this._serviceViewStore.getProxy().setExtraParams({
            formId: this._formId, 
            siteName: Ametys.getAppParameter('siteName'),
            language: Ametys.getAppParameter('user').locale
        });
    },
    
    refresh: function()
    {
        this._refreshWithCallback(Ext.emptyFn);
    },
    
    /**
     * Refreshes this tool, and eventually calls a callback function then.
     * @param {Function} [callBackFn] The callback function.
     * @private
     */
    _refreshWithCallback: function(callBackFn)
    {
        var xsltValue = this._combo.getValue();
        if (!xsltValue)
        {
            // Just return, refresh will be called again after the loading of the xslt store
            return;
        }
        
        this.showRefreshing();

        var params = {
            "xslt": xsltValue,
            "formId": this._formId
        }
        var args = '?serviceId=org.ametys.forms.service.Display';
        args += '&lang=' + encodeURIComponent(Ametys.getAppParameter('user').locale);
        args += '&siteName=' + encodeURIComponent(Ametys.getAppParameter('siteName'));
        args += '&serviceParams=' + encodeURIComponent(Ext.JSON.encode(params));
        args += '&preview=true'
        if (this._currentPageId)
        {
            args += '&currentPageId=' + this._currentPageId
        }
        if (this._currentQuestionId)
        {
            args += '&currentQuestionId=' + this._currentQuestionId
        }

        this._iframe.load(Ametys.CONTEXT_PATH + '/_wrapped-service.html' + args)
        
        this.showRefreshed();
        
        Ametys.plugins.forms.dao.FormDAO.getFormTitle([this._formId], Ext.bind(this._finishRefresh, this, [callBackFn], 1));
    },
    
    /**
     * Callback function called after retrieving information about the current form. Updates the title.
     * @param {String} formTitle The form title
     * @param {Function} callBackFn The callback function
     * @private
     */
    _finishRefresh: function(formTitle, callBackFn)
    {
        this.setTitle(formTitle);
        
        // Register the tool on the history tool
        var toolId = this.getFactory().getId();
        var toolParams = this.getParams();

        Ametys.navhistory.HistoryDAO.addEntry({
            id: this.getId(),
            objectId: this.getId(),
            label: this.getTitle(),
            description: this.getDescription(),
            iconSmall: this.getSmallIcon(),
            iconMedium: this.getMediumIcon(),
            iconLarge: this.getLargeIcon(),
            type: Ametys.navhistory.HistoryDAO.TOOL_TYPE,
            action: Ext.bind(Ametys.tool.ToolsManager.openTool, Ametys.tool.ToolsManager, [toolId, toolParams], false)
        });
        
        callBackFn();
    },
    
    /**
     * Shows the given page and even, if provided, the given question in this tool.
     * @param {String} pageId The page id.
     * @param {String} questionId The question id.
     * @private
     */
    _goToPage: function(pageId, questionId)
    {
        if (this._iframe.iframeEl.dom.contentWindow.previewGotoPage)
        {
            this._currentPageId = pageId;
            this._currentQuestionId = questionId;
            this._iframe.iframeEl.dom.contentWindow.previewGotoPage (pageId, questionId);
        }
    },
    
    getMBSelectionInteraction: function()
    {
        return Ametys.tool.Tool.MB_TYPE_ACTIVE;
    },
    
    sendCurrentSelection: function()
    {
        if (this._currentQuestionId)
        {
            var questionSubtarget = {
                id: Ametys.message.MessageTarget.FORM_QUESTION,
                parameters: {
                    id: this._currentQuestionId,
                    pageId: this._currentPageId,
                    formId: this._formId
                }
            }
        }
        if (this._currentPageId)
        {
            var pageSubtarget = {
                id: Ametys.message.MessageTarget.FORM_PAGE,
                parameters: {
                    id: this._currentPageId,
                    formId: this._formId
                },
                subtargets: questionSubtarget || []
            }
        }
        Ext.create('Ametys.message.Message', {
            type: Ametys.message.Message.SELECTION_CHANGED,
            targets: {
                id: Ametys.message.MessageTarget.FORM_TARGET,
                parameters: {
                    id: this._formId
                },
                subtargets: pageSubtarget || []
            }
        });
    },
    
    /**
     * Listener on creation message. Refresh the tree.
     * @param {Ametys.message.Message} message The creation message.
     * @private
     */
    _onMessageCreated: function(message)
    {
        var pageTarget = message.getTarget(Ametys.message.MessageTarget.FORM_PAGE);
        if (pageTarget && pageTarget.getParameters().formId == this._formId)
        {
            this._refreshWithCallback(Ext.bind(this._goToPage, this, [pageTarget.getParameters().id, null]));
            return;
        }
        
        var questionTarget = message.getTarget(Ametys.message.MessageTarget.FORM_QUESTION);
        if (questionTarget && questionTarget.getParameters().formId == this._formId)
        {
            this._refreshWithCallback(Ext.bind(this._goToPage, this, [questionTarget.getParameters().pageId, questionTarget.getParameters().id]));
            return;
        }
    },
    
    /**
     * Listener on edition message. Refresh the tree.
     * @param {Ametys.message.Message} message The edition message.
     * @private
     */
    _onMessageModifiedOrMoved: function(message)
    {
        var formTarget = message.getTarget(Ametys.message.MessageTarget.FORM_TARGET);
        if (formTarget && formTarget.getParameters().id == this._formId)
        {
            this.showOutOfDate();
            return;
        }
        var pageTarget = message.getTarget(Ametys.message.MessageTarget.FORM_PAGE);
        if (pageTarget && pageTarget.getParameters().formId == this._formId)
        {
            this._refreshWithCallback(Ext.bind(this._goToPage, this, [pageTarget.getParameters().id, null]));
            return;
        }
        
        var questionTarget = message.getTarget(Ametys.message.MessageTarget.FORM_QUESTION);
        if (questionTarget && questionTarget.getParameters().formId == this._formId)
        {
            this._refreshWithCallback(Ext.bind(this._goToPage, this, [questionTarget.getParameters().pageId, questionTarget.getParameters().id]));
            return;
        }
    },
    
    /**
     * Listener on deletion message. Refresh the tree.
     * @param {Ametys.message.Message} message The deletion message.
     * @private
     */
    _onMessageDeleted: function(message)
    {
        var formTarget = message.getTarget(Ametys.message.MessageTarget.FORM_TARGET);
        if (formTarget && formTarget.getParameters().id == this._formId)
        {
            this.close();
            
            // Remove the deleted form from the navigation history
            Ametys.navhistory.HistoryDAO.removeEntry (this.getId());
            return;
        }
        
        var pageTarget = message.getTarget(Ametys.message.MessageTarget.FORM_PAGE);
        if (pageTarget && pageTarget.getParameters().formId == this._formId)
        {
            this.showOutOfDate();
            return;
        }
        
        var questionTarget = message.getTarget(Ametys.message.MessageTarget.FORM_QUESTION);
        if (questionTarget && questionTarget.getParameters().formId == this._formId)
        {
            this._refreshWithCallback(Ext.bind(this._goToPage, this, [questionTarget.getParameters().pageId, null]));
            return;
        }
    },
    
    /**
     * Listener on selection changed message.
     * @param {Ametys.message.Message} message The selection changed message.
     * @private
     */
    _onMessageSelectionChanged: function(message)
    {
        var formTarget = message.getTarget(Ametys.message.MessageTarget.FORM_TARGET);
        if (formTarget && formTarget.getParameters().id == this._formId)
        {
            var pageTarget = message.getTarget(Ametys.message.MessageTarget.FORM_PAGE);
            if (pageTarget)
            {
                var questionTarget = message.getTarget(Ametys.message.MessageTarget.FORM_QUESTION);
                if (questionTarget)
                {
                    if (questionTarget && this._currentQuestionId != questionTarget.getParameters().id)
                    {
                        this._goToPage(pageTarget.getParameters().id, questionTarget.getParameters().id);
                    }
                }
                else
                {
                    this._goToPage(pageTarget.getParameters().id, null);
                }
            }
        }
    }
 });