var app;

var monacoEditor = {
  id: "com.thoriumbuilder.monaco",
  jsinstance: null,
  cssinstance: null,
  code: null,
  dirtyread: false,
  changestatus: function() {
    monacoEditor.dirtyread=false;
    document.title="false";
    document.status="false";
  },
  create: function () {
    monacoEditor.dirtyread=false;
    document.title="false";
    document.status="false";
    const jsEfditor=document.getElementById('monaco_editor');
    if (jsEfditor) {
      monacoEditor.jsinstance = monaco.editor.create(jsEfditor, {
        value: ['', '//*-- Add your Custom code Here -- *//', '', 'function x() {', '\tconsole.log("Hello world!");', '}'].join('\n'),
        language: 'javascript',
        theme: 'vs-dark',
        automaticLayout: true,
        fontSize: "14.5px",
      });
      if (monacoEditor.jsinstance) {
        monacoEditor.jsinstance.onDidChangeModelContent(e => {
          monacoEditor.dirtyread=true;
          document.title="true";
          document.status="true";
          // console.log(monacoEditor.jsinstance.getValue());
        });
      }
    };
    const cssEditor=document.getElementById('monaco_editor_css');
    if(cssEditor) {
      monacoEditor.cssinstance = monaco.editor.create(cssEditor, {
        value: ['', '/* -- Add your Custom Css Here -- */', '', 'body {', '\t/* --background-color:black; --*/', '}'].join('\n'),
        language: 'css',
        theme: 'vs-dark',
        automaticLayout: true,
        fontSize: "14.5px",
      });
      if (monacoEditor.cssinstance) {
        monacoEditor.cssinstance.onDidChangeModelContent(e => {
          monacoEditor.dirtyread=true;
          document.title="true";
          document.status="true";
        });
      }
    }
    monacoEditor.addAutoCompleteObjects();
  },
  isJSInstanceReady: function() {
    if (monacoEditor.jsinstance) {
      return true
    } else {
      return false
    }
  },
  isCssInstanceReady: function() {
    if (monacoEditor.cssinstance) {
      return true
    } else {
      return false
    }
  },
  getJSlinecount: function() {
    if ((monacoEditor) && (monacoEditor.jsinstance) ) {
      var r=monacoEditor.jsinstance.getModel().getLineCount();
      if (r) {return parseInt(r)} else {return 0}
    }
  },
  getCSSlinecount: function() {
    if ((monacoEditor) && (monacoEditor.cssinstance) ) {
      var r=monacoEditor.cssinstance.getModel().getLineCount();
      if (r) {return parseInt(r)} else {return 0}
    }
  },
  gotoEndOfFile: function() {
    if (monacoEditor.jsinstance) {
      var pos=monacoEditor.getJSlinecount();
      monacoEditor.jsinstance.revealLineInCenter(pos);
      monacoEditor.jsinstance.setPosition({lineNumber:pos, column:1}); 
      monacoEditor.jsinstance.focus(); 
    }
    if ( monacoEditor.cssinstance) {
      var pos=monacoEditor.getCSSlinecount();
      monacoEditor.cssinstance.revealLineInCenter(pos);
      monacoEditor.cssinstance.setPosition({lineNumber:pos, column:1}); 
      monacoEditor.cssinstance.focus(); 
    }
  },
  setfocus: function() {
    if ( monacoEditor.jsinstance) {
      monacoEditor.jsinstance.focus(); 
    }
    if ( monacoEditor.cssinstance) {
      monacoEditor.cssinstance.focus(); 
    }
  },
  jumpToLastJSLine: function() {
    if ( monacoEditor.jsinstance) {
      var pos=monacoEditor.getJSlinecount();
      monacoEditor.jsinstance.revealLineInCenter(pos);
      var curpos=pos-1;
      monacoEditor.jsinstance.setPosition({lineNumber:curpos, column:2}); 
      monacoEditor.jsinstance.focus(); 
    }
  },
  getJSContent: function() {
    if ((monacoEditor) && (monacoEditor.jsinstance) ) {
      var value = monacoEditor.jsinstance.getValue();
      return value;
    }
  },
  getCSSContent: function() {
    if ((monacoEditor) && (monacoEditor.cssinstance) ) {
      var value = monacoEditor.cssinstance.getValue();
      return value;
    }
  },
  getRange: function() {
    var r="";
    if ((monacoEditor) && (monacoEditor.jsinstance) ) {
      r=monacoEditor.jsinstance.getModel().getValueInRange(monacoEditor.jsinstance.getSelection()); // //   window.editor.getModel().getValueInRange(window.editor.getSelection())
    }
    if ((monacoEditor) && (monacoEditor.cssinstance) ) {
      r=monacoEditor.cssinstance.getModel().getValueInRange(monacoEditor.cssinstance.getSelection());
    }
    return r;
  },
  findInJSCode: function(value) {
    //Example: [{"range":{"startLineNumber":4,"startColumn":14,"endLineNumber":4,"endColumn":19},"matches":null},{"range":{"startLineNumber":7,"startColumn":12,"endLineNumber":7,"endColumn":17},"matches":null}]
    if ((monacoEditor) && (monacoEditor.jsinstance) ) {
      var r=monacoEditor.jsinstance.getModel().findMatches(value);
      if ((r) && (r.length>0) ) {
        var line= r[0].range.startLineNumber;
        if (line)  {
         monacoEditor.jsinstance.revealLineInCenter(line);
         monacoEditor.jsinstance.setPosition({lineNumber:(line+1), column:2}); 
         monacoEditor.jsinstance.focus(); 
          return JSON.stringify(r);
        } else {
          return "false";
        }
      } else {
        return "false";
      }
    }
  },
  setJSContent: function() {
    if ((monacoEditor) && (monacoEditor.jsinstance) ) {
      monacoEditor.jsinstance.setValue(monacoEditor.code);
      monacoEditor.jsinstance.setScrollPosition({scrollTop: 0});
      document.title="false";
      document.status="false";
      return "true";
    }
  },
  setCssContent: function() {
    if ((monacoEditor) && (monacoEditor.cssinstance) ) {
        monacoEditor.cssinstance.setValue(monacoEditor.code);
        monacoEditor.cssinstance.setScrollPosition({scrollTop: 0});
        document.title="false";
        document.status="false";
        return "true";
    }
  },
  changeTheme: function(theme) {
    monaco.editor.setTheme(theme);
  },
  setFontSize: function(size) {
    let options = {
      "fontSize": size,
      "glyphMargin": false
    }
    if ( monacoEditor.jsinstance) {
      monacoEditor.jsinstance.updateOptions(options);
    }
    if ( monacoEditor.cssinstance) {
      monacoEditor.cssinstance.updateOptions(options);
    }
  },
  getType: function (thing, isMember) {
    isMember = (isMember == undefined) ? (typeof isMember == "boolean") ? isMember : false : false; // Give isMember a default value of false

    switch ((typeof thing).toLowerCase()) {
      case "object":
        return monaco.languages.CompletionItemKind.Class;

      case "function":
        return (isMember) ? monaco.languages.CompletionItemKind.Method : monaco.languages.CompletionItemKind.Function;

      default:
        return (isMember) ? monaco.languages.CompletionItemKind.Property : monaco.languages.CompletionItemKind.Variable;
    }
  },
  _addAutoCompleteForObject: function (obj) {
    // Disable default autocompletion for javascript
    //monaco.languages.typescript.javascriptDefaults.setCompilerOptions({ noLib: true  });

    // Helper function to return the monaco completion item type of a thing

    // Register object that will return autocomplete items 
    monaco.languages.registerCompletionItemProvider('javascript', {
      // Run this function when the period or open parenthesis is typed (and anything after a space)
      triggerCharacters: ['.', '('],

      // Function to generate autocompletion results
      provideCompletionItems: function (model, position, token) {
        // Split everything the user has typed on the current line up at each space, and only look at the last word
        var last_chars = model.getValueInRange({ startLineNumber: position.lineNumber, startColumn: 0, endLineNumber: position.lineNumber, endColumn: position.column });
        var words = last_chars.replace("\t", "").split(" ");
        var active_typing = words[words.length - 1]; // What the user is currently typing (everything after the last space)

        // If the last character typed is a period then we need to look at member objects of the obj object 
        var is_member = active_typing.charAt(active_typing.length - 1) == ".";

        // Array of autocompletion results
        var result = [];

        // Used for generic handling between member and non-member objects
        var last_token = obj;
        var prefix = '';

        if (is_member) {
          // Is a member, get a list of all members, and the prefix
          var parents = active_typing.substring(0, active_typing.length - 1).split(".");
          last_token = obj[parents[0]];
          prefix = parents[0];

          // Loop through all the parents the current one will have (to generate prefix)
          for (var i = 1; i < parents.length; i++) {
            if (last_token.hasOwnProperty(parents[i])) {
              prefix += '.' + parents[i];
              last_token = last_token[parents[i]];
            } else {
              // Not valid
              return result;
            }
          }

          prefix += '.';
        }

        // Get all the child properties of the last token
        for (var prop in last_token) {
          // Do not show properites that begin with "__"
          if (last_token.hasOwnProperty(prop) && !prop.startsWith("__")) {
            // Get the detail type (try-catch) incase object does not have prototype 
            var details = '';
            try {
              details = last_token[prop].__proto__.constructor.name;
            } catch (e) {
              details = typeof last_token[prop];
            }

            // Create completion object
            var to_push = {
              label: prop, // prefix + prop
              kind: monacoEditor.getType(last_token[prop], is_member),
              detail: details,
              insertText: prop,
            };

            // Change insertText and documentation for functions
            if (to_push.detail.toLowerCase() == 'function') {
              to_push.insertText += "(";
              to_push.documentation = (last_token[prop].toString()).split("{")[0]; // Show function prototype in the documentation popup
            }

            // Add to final results
            result.push(to_push);
          }
        }

        return {
          suggestions: result
        };
      }
    });
  },
  addAutoCompleteObjects: function () {
    //Add F7 and Thorium AutoComplete Classes
    if ( monacoEditor.jsinstance) {
      app=new Framework7({});
      monacoEditor._addAutoCompleteForObject({ app });
      monacoEditor._addAutoCompleteForObject({ thoriumapi });
    }
  },
  openFindDialog : function(e) {
    if ( monacoEditor.cssinstance) {
      monacoEditor.cssinstance.trigger("find", "editor.actions.findWithArgs", { searchString: "" });
    }
    if ( monacoEditor.jsinstance) {
      monacoEditor.jsinstance.trigger("find", "editor.actions.findWithArgs", { searchString: "" });
    }
  },
  sendTab : function(e) {
    var code={};
    code.text=String.fromCharCode(9);
    if ( monacoEditor.cssinstance) {
      monacoEditor.jsinstance.trigger("keyboard", "type",code);
    }
    if ( monacoEditor.jsinstance) {
      monacoEditor.jsinstance.trigger("keyboard", "type",code);
    }
  },
  gotoLine: function(line)  {
    monaco.editor.revealLine(4);
  },
  insertCodeAtCurrentPos: function(text) {
    if ( monacoEditor.jsinstance) {
      var code={};
      code.text=text;
      monacoEditor.jsinstance.trigger("keyboard", "type",code);
    }
  }


 }


 window.onerror = function myErrorHandler(errorMsg, url, lineNumber, ColumnNumber) {
  console.log(errorMsg+" ("+url+")");
  return false;
}



document.addEventListener("DOMContentLoaded", monacoEditor.create);

 


