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

/**
 * Tool showing the script text input to type into.
 * @private
 */
Ext.define('Ametys.plugins.coreui.script.ScriptTool',
{
    extend: 'Ametys.tool.Tool',
    
    /**
     * The number of lines in the editor footer, currently forced at 3. 
     * @private
     */
    _footerLineCount: 3,

    /**
     * Toggle the edition of the header and footer of the editor
     * @private
     */
    _allowHeaderFooterEdit: false,
    
    createPanel: function()
    {
        var footerLine1 = "{{i18n PLUGINS_CORE_UI_TOOLS_SCRIPT_FOOTER_HINT_LINE1}}".replace(/\r\n|\r|\n/, "");
        var footerLine2 = "{{i18n PLUGINS_CORE_UI_TOOLS_SCRIPT_FOOTER_HINT_LINE2}}".replace(/\r\n|\r|\n/, "");
        
        this.scriptEditor = Ext.create('Ametys.form.field.CodeAdvanced', {
            mode: 'typescript',
            stateful: true,
            stateId: this.getId() + "$code",
            cls: "uitool-script-editor",
            
            value: "function main() {\n    \n    \n    \n    \n}\n" + footerLine1 + "\n" + footerLine2,
            
            listeners: {
                beforechange: {
                    fn: function (editor, newValue, oldValue, event) {
                        if (!this._allowHeaderFooterEdit 
                            && event.changes.filter(change => change.range.startLineNumber == 1 || change.range.endLineNumber > oldValue.split("\n").length - this._footerLineCount).length > 0)
                        {
                            let me = this;
                            window.setTimeout(function() { me._updateDecorations(editor); }, 1); // Depending on the modification we refuse, the decoration may be destroyed... (select a few line including the last ones, and type one character for example)
                            return false;
                        }
                    },
                    scope: this
                },
                change: {
                    fn: function (editor, newValue, oldValue) {
                        this._updateDecorations(editor);
                    },
                    scope: this
                },
                initialize: {
                    fn: function (editor) {
                        let me = this;
                        window.setTimeout(function() { me._updateDecorations(editor); }, 0);

                        let ed = editor._monaco;
                        
                        // Replace the default Ctrl+A
                        ed.addAction({
                            id: 'custom-select-all',
                            label: 'Select All Editable',
                            keybindings: [
                                monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyA
                            ],
                            precondition: null,
                            keybindingContext: null,
                            run: function(ed) { me._selectAll(); }
                        });
                        
                        // load definition for Ametys API
                        Ametys.data.ServerComm.send({
                            plugin: 'core-ui',
                            url: 'script/typescript-definitions.d.ts',
                            callback: { 
                                handler: function(response) 
                                {
                                    monaco.languages.typescript.javascriptDefaults.addExtraLib(response.textContent, 'ts:ametys.d.ts');
                                    monaco.languages.typescript.typescriptDefaults.addExtraLib(response.textContent, 'ts:ametys.d.ts');
                                },
                                scope: this
                            },
                            responseType: 'text',
                            waitMessage: { target: me.getContentPanel() },
                            errorMessage: true
                        });
                    },
                    scope: this
                }
            }
        });
        
        this._panel = Ext.create('Ext.panel.Panel', {
            layout: 'fit',
            scrollable: false,
            cls: 'uitool-script',
            
            items: this.scriptEditor
        });
        
        return this._panel;
    },
    
    getMBSelectionInteraction: function() 
    {
        return Ametys.tool.Tool.MB_TYPE_NOSELECTION;
    },
    
    getType: function()
    {
        return Ametys.tool.Tool.TYPE_SCRIPT;  
    },
    
    /**
     * Called by the key binding Ctrl-A, overrides the default selection to only the editable lines.
     * @private
     */
    _selectAll: function(cm)
    {
        if (this.scriptEditor)
        {
            let ed = this.scriptEditor._monaco;
            
            var model = ed.getModel();
            var totalLines = model.getLineCount();
            var startLine = 2; // Ligne après le header
            var endLine = totalLines - this._footerLineCount; // Ligne avant le footer
    
            if (endLine >= startLine) {
                var endColumn = model.getLineMaxColumn(endLine);
                ed.setSelection(new monaco.Range(startLine, 1, endLine, endColumn));
                ed.revealLineInCenter(startLine);
            }
        }
    },
        
    _updateDecorations: function(editor)
    {
        let model = editor._monaco.getModel();
        
        let totalLines = model.getLineCount();
        let decorations = [];
      
        // Décoration pour la première ligne
        decorations.push({
            range: new monaco.Range(1, 1, 1, model.getLineMaxColumn(1)),
            options: {
                isWholeLine: true,
                className: 'code-readonly-line',
                glyphMarginClassName: 'code-readonly-glyph'
            }
        });
      
        // Décoration pour les dernières lignes (footer)
        for (var i = 0; i < this._footerLineCount; i++)
        {
            var lineNumber = totalLines - this._footerLineCount + i + 1;
            decorations.push({
                range: new monaco.Range(lineNumber, 1, lineNumber, model.getLineMaxColumn(lineNumber)),
                options: {
                    isWholeLine: true,
                    className: 'code-readonly-line',
                    glyphMarginClassName: 'code-readonly-glyph'
                }
            });
        }
      
        // Appliquer les décorations
        this._decorationIds = model.deltaDecorations(this._decorationIds || [], decorations);
    }
});