/* Demonstration of embedding CodeMirror in a bigger application. The
 * interface defined here is a mess of prompts and confirms, and
 * should probably not be used in a real project.
 */

function MirrorFrameSharpoid(place, options) {

    this.home = document.createElement("DIV");
    if (place.appendChild)
        place.appendChild(this.home);
    else
        place(this.home);

    var self = this;
    function makeButton(name, action) {
        var button = document.createElement("INPUT");
        button.type = "button";
        button.value = name;
        self.home.appendChild(button);
        button.onclick = function(){self[action].call(self);};
    }  

    function makeDropdown(name, action) {
      var displaymodecombo = document.createElement("select");      
      displaymodecombo.id = "displaymodecombo";
      
      var option0 = document.createElement("option");
      option0.text = "<Select display mode>";      
      option0.value = "none";
      try {
        displaymodecombo.add(option0, null); //Standard
      } catch(error) {
        displaymodecombo.add(option0); // IE only
      }      
            
      var option1 = document.createElement("option");
      option1.text = "Console mode";      
      option1.value = "console";
      try {
        displaymodecombo.add(option1, null); //Standard
      } catch(error) {
        displaymodecombo.add(option1); // IE only
      }      

      var option2 = document.createElement("option");
      option2.text = "Graphics mode";      
      option2.value = "graphics";
      try {
        displaymodecombo.add(option2, null); //Standard
      } catch(error) {
        displaymodecombo.add(option2); // IE only
      }
      
      self.home.appendChild(displaymodecombo);
      displaymodecombo.onchange = function(){       
          self[action].call(self);
      };
    }
    
    // SRDJAN
    if (!options.readOnly)
    {
      //makeButton("LOAD", "importCode");
      //makeButton("CHECK", "checkCode");
      //makeButton("PUBLISH", "publishCode");    
      //makeButton("RUN", "runCode");
      //makeButton("HELP", "helpCode");    
      makeDropdown("displaymode", "onDisplayModeChange");
    }

    //makeButton("Search", "search");
    //makeButton("Replace", "replace");
    //makeButton("Current line", "line");
    //makeButton("Jump to line", "jump");
    //makeButton("Insert constructor", "macro");
    //makeButton("Indent all", "reindent");

    this.mirror = new CodeMirror(this.home, options);
    
    // application name
    this.mirror.appName = "";
    this.mirror.appDisplayMode = "";
}
                 
MirrorFrameSharpoid.prototype = {

    onDisplayModeChange: function ()    
    {     
      //jQuery.facebox(combo.value);
    },

    htmlEnterCodePrompt: function ()    
    {
      var s = "";
      s += "<html>";      
      s += "<body>";      

      s += "<form action=\"\">";  
          
      s += "Application name<br/>";
      s += "<input type=\"text\" name=\"appcode\">";
      s += "<br/>";
                  
      //s += "Način rada<br/>";            
      //s += "<select name=\"displaymode\">";            
      //s += "<option value=\"graphics\">Grafički mod</option>";      
      //s += "<option value=\"console\">Konzolni mod</option>";
      
      //s += "</select>";       

      s += "<input type=\"button\" onclick=\"callImportCode();\" value=\"LOAD\">";      

      s += "</form>";       

      s += "<script type=\"text/javascript\">";      
      s += "function callImportCode() { return ; }";
      s += "</script>";      
                                               
      s += "</body>";
      s += "</html>";
      
      return s;
    },
  
    importCodeEntry: function() {
      jQuery.facebox(this.htmlEnterCodePrompt());
    },            

    // called by <button onclick="btnLoad();">
    importCode: function() {
    
        var thisMirror = this.mirror;        

        var code = prompt("Enter application name:", "");
        if (!code) return;        
        code = this.trim(code);
        if (code.length == 0) return;        
        code = code.toUpperCase();
        xmlhttp = new XMLHttpRequest();       
        xmlhttp.open("GET", "gate_import.php?target=webeditor&ver=1.0.0&code=" + code, true);
        xmlhttp.onreadystatechange=function() {           
            if (xmlhttp.readyState==4) {
                if (xmlhttp.status==200)
                {                        
                    if (xmlhttp.responseText.length == 0)                    
                    {
                      jQuery.facebox("<strong>WARNING</strong><br/><hr>Application <b>" + code + "</b> not found, please check the name.");
                    }                    
                    else                    
                    {
                      /*                    
                      var mode = xmlhttp.getResponseHeader("X-SHARPOID-DISPLAYMODE");
                      //jQuery.facebox(mode);
                      
                      var combo = document.getElementById('displaymodecombo'); 
                      combo.value = mode;                    
                      
                      thisMirror.setCode(xmlhttp.responseText);
                      
                      // store app name and other info
                      thisMirror.appName = code; 
                      thisMirror.appDisplayMode = mode;
                      */
                      
                      // load entire page 
                      // in order to update title and other data
                      var url = "http://sharpoid.com/index.php?id=editor&code=" + code;
                      window.location = url;                     
                    }
                }
                else
                {               
                    jQuery.facebox("<strong>ERROR</strong><br/><hr>Unable to load application <b>" + code + "</b>.");
                }
            }
        }
        xmlhttp.send(null);
    },
    
    getDoc: function() {
      return document;
    },
      
    trim: function(string) {     
      return string.replace(/^\s+|\s+$/g, "");
    },

    
    _utf8_encode : function (string) {
      string = string.replace(/\r\n/g,"\n");
      var utftext = "";

      for (var n = 0; n < string.length; n++) {

        var c = string.charCodeAt(n);

        if (c < 128) {
          utftext += String.fromCharCode(c);
        }
        else if((c > 127) && (c < 2048)) {
          utftext += String.fromCharCode((c >> 6) | 192);
          utftext += String.fromCharCode((c & 63) | 128);
        }
        else {
          utftext += String.fromCharCode((c >> 12) | 224);
          utftext += String.fromCharCode(((c >> 6) & 63) | 128);
          utftext += String.fromCharCode((c & 63) | 128);
        }

      }

      return utftext;
    },

    // public method for encoding
    Base64encode : function (input) {
      
      // private property
      var _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
      var output = "";
      var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
      var i = 0;

      input = this._utf8_encode(input);

      while (i < input.length) {

        chr1 = input.charCodeAt(i++);
        chr2 = input.charCodeAt(i++);
        chr3 = input.charCodeAt(i++);

        enc1 = chr1 >> 2;
        enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
        enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
        enc4 = chr3 & 63;

        if (isNaN(chr2)) {
          enc3 = enc4 = 64;
        } else if (isNaN(chr3)) {
          enc4 = 64;
        }

        output = output +
        _keyStr.charAt(enc1) + _keyStr.charAt(enc2) +
        _keyStr.charAt(enc3) + _keyStr.charAt(enc4);
      }
      return output;
    },
    
    // called by <button onclick="btnSaveAs();">   
    saveAsCode: function() {
    
        var thisMirror = this.mirror;           
    
        var sourceCode = thisMirror.getCode();        
        sourceCode = this.trim(sourceCode);
        if (sourceCode.length == 0)
        {   
          jQuery.facebox("<strong>ERROR</strong><br/><hr>Editor is empty.");
          return;
        }           

        var combo = document.getElementById('displaymodecombo'); 
        var displayMode = combo.value;        
        if (displayMode == "none")        
        {
          jQuery.facebox("<strong>ERROR</strong><br/><hr>Before saving you have to select display mode: graphics or console.");
          return;
        }
        
        var defaultName = thisMirror.appName;
        
        var code = prompt("Enter application name:", defaultName);
        if (!code) return;        
        code = this.trim(code);
        if (code.length == 0) return;        
        code = code.toUpperCase();
        
        // TODO: add some comments at start 
        // sourceCode = "// code length=" + sourceCode.length + "\n" + sourceCode;
        
        xmlhttp = new XMLHttpRequest();
        xmlhttp.open("POST", "gate_publish.php?code=" + code + "&mode=" + displayMode, true);
        xmlhttp.setRequestHeader("Content-Type", "text/plain;charset=UTF-8");        
        xmlhttp.setRequestHeader("Connection", "close");

        var sourceB64 = this.Base64encode(sourceCode);        
        xmlhttp.send(sourceB64);
              
        xmlhttp.onreadystatechange=function() {
            if (xmlhttp.readyState==4) {
                if (xmlhttp.status==200)
                {                
                  if (xmlhttp.responseText == "OK")                    
                  {
                    thisMirror.appName = code;
                    
                    // invoke page refresh after close 
                    //jQuery.facebox.settings.callback = 'location.reload(true); $.facebox.settings.callback=null;';
                    var url = "http://sharpoid.com/index.php?id=editor&code=" + code;
                    jQuery.facebox.settings.callback = 'window.location = "' + url + '"; $.facebox.settings.callback=null;';
                                        
                    jQuery.facebox("<strong>INFO</strong><br/><hr>Application <b>" + code + "</b> is successfully saved.");
                  }                    
                  else                    
                  {                  
                    jQuery.facebox(xmlhttp.responseText); 
                  }
                }
                else
                {     
                    jQuery.facebox("<strong>ERROR</strong><br/><hr>Unable to save application <b>" + code + "</b>.");
                }
            }
        }
    },
    
    // called by <button onclick="btnSave();">   
    saveCode: function() {
    
        var thisMirror = this.mirror;           
    
        var sourceCode = thisMirror.getCode();        
        sourceCode = this.trim(sourceCode);
        if (sourceCode.length == 0)
        {   
          jQuery.facebox("<strong>ERROR</strong><br/><hr>Editor is empty.");
          return;
        }           

        var combo = document.getElementById('displaymodecombo'); 
        var displayMode = combo.value;        
        if (displayMode == "none")        
        {
          jQuery.facebox("<strong>ERROR</strong><br/><hr>Before saving you have to select display mode: graphics or console.");
          return;
        }
        
        var defaultName = thisMirror.appName;
        
        //!!var code = prompt("Enter application name:", defaultName);        
        var code = defaultName;
        
        if (!code) return;        
        code = this.trim(code);
        if (code.length == 0) return;        
        code = code.toUpperCase();
        
        // TODO: add some comments at start 
        // sourceCode = "// code length=" + sourceCode.length + "\n" + sourceCode;
        
        xmlhttp = new XMLHttpRequest();
        xmlhttp.open("POST", "gate_publish.php?code=" + code + "&mode=" + displayMode, true);
        xmlhttp.setRequestHeader("Content-Type", "text/plain;charset=UTF-8");        
        xmlhttp.setRequestHeader("Connection", "close");

        var sourceB64 = this.Base64encode(sourceCode);        
        xmlhttp.send(sourceB64);
              
        xmlhttp.onreadystatechange=function() {
            if (xmlhttp.readyState==4) {
                if (xmlhttp.status==200)
                {                
                  if (xmlhttp.responseText == "OK")                    
                  {                  
                    jQuery.facebox("<strong>INFO</strong><br/><hr>Application <b>" + code + "</b> is successfully saved.");
                    thisMirror.appName = code; 
                  }                    
                  else                    
                  {                  
                    jQuery.facebox(xmlhttp.responseText); 
                  }
                }
                else
                {     
                    jQuery.facebox("<strong>ERROR</strong><br/><hr>Unable to save application <b>" + code + "</b>.");
                }
            }
        }
    },

    // called by <button onclick="btnCheck();">    
    checkCode: function() {
        var sourceCode = this.mirror.getCode();              
        sourceCode = this.trim(sourceCode);
        if (sourceCode.length == 0)
        {   
          jQuery.facebox("<strong>ERROR</strong><br/><hr>Editor is empty.");
          return;
        }
        
        var sourceB64 = this.Base64encode(sourceCode);

        var appletHtml = "<strong>APP CHECK</strong><br/><hr>";         
        appletHtml += "<applet code=\"com.sharpoid.web.CompilerJApplet\" archive=\"SharpoidApplet.jar\" width=\"400\" height=\"200\">";
        appletHtml += "<param name=\"source\" value=\"" + sourceB64 +"\">";
        appletHtml += "SHARPOID needs Java.<br/>You can install it for free at following link:<br/><br/><a href=\"http://java.com/getjava\" target=\"_blank\" alt=\"Click to install Java\">http://java.com/getjava</a><br/><br/>";
        appletHtml += "</applet>";       
        
        jQuery.facebox(appletHtml);
    },

    // called by <button onclick="btnRun();">    
    runCode: function() {    
        var thisMirror = this.mirror;
        var defaultName = thisMirror.appName;
        
        var code;
        if (defaultName.length == 0)
        {
          jQuery.facebox("<strong>ERROR</strong><br/><hr>Application must be saved first.<br/><br/>Click the <strong>SAVE AS</strong> button and give your app a name.");
          return;
          /*              
          code = prompt("Enter application name:", defaultName);
          if (!code) return;
          code = this.trim(code);
          if (code.length == 0) return;        
          code = code.toUpperCase();*/
        }
        else
        {
          code = defaultName;
        }
        
        /*myRef = window.open(''+self.location,'mywin','left=20,top=20,width=500,height=500,toolbar=1,resizable=0');*/
        window.open("http://sharpoid.com/index.php?id=app&code=" + code);        
    },   

    // called by <button onclick="btnHelp();">   
    helpCode: function() {
        var sourceCode = this.mirror.getCode();        
        sourceCode = this.trim(sourceCode);
        if (sourceCode.length == 0)
        {   
          jQuery.facebox("<strong>ERROR</strong><br/><hr>Editor is empty.");
          return;
        }           

        var text = this.mirror.selection();        
        text = this.trim(text);
        if (text.length == 0)
        {           
            jQuery(document).ready(function($) 
            {
              $.facebox("<strong>INFO</strong><br/><hr>You have to select keyword in editor.<br/><br/>For example, to show help on function <strong>console.writeLine</strong> select text in editor like as on the following picture and click the <strong>HELP</strong> button.<br/><br/><img src=\"/data/uploads/help_example.png\" /><br/><br/><hr>Tip: open <strong><a href=\"api\" target=\"_blank\">SHARPOID API</a></strong> list in the other window or tab.");
              //setTimeout( function() { jQuery(document).trigger('close.facebox'); }, 4000);
            });
            return;
        }

        text = this._utf8_encode(text);
        xmlhttp = new XMLHttpRequest();
        xmlhttp.open("GET", "gate_help.php?lang=EN&keyword=" + text, true);
        xmlhttp.onreadystatechange=function() {
            if (xmlhttp.readyState==4) {
                if (xmlhttp.status==200)
                {
                    if (xmlhttp.responseText.length == 0)
                    {
                      jQuery.facebox("<strong>WARNING</strong><br/><hr>Unable to find help for keyword <b>" + text + "</b>.");
                    }
                    else
                    {
                      // help is already formatted in gate_help.php
                      jQuery.facebox(xmlhttp.responseText);
                    }
                }
                else
                {                
                    jQuery.facebox("<strong>ERROR</strong><br/><hr>Unable to display help.");
                }
            }
        }
        xmlhttp.send(null);
    },

    search: function() {
        var text = prompt("Enter search term:", "");
        if (!text) return;

        var first = true;
        do {
            var cursor = this.mirror.getSearchCursor(text, first);
            first = false;
            while (cursor.findNext()) {
                cursor.select();
                if (!confirm("Search again?"))
                    return;
            }
        } while (confirm("End of document reached. Start over?"));
    },

    replace: function() {
        // This is a replace-all, but it is possible to implement a
        // prompting replace.
        var from = prompt("Enter search string:", ""), to;
        if (from) to = prompt("What should it be replaced with?", "");
        if (to == null) return;

        var cursor = this.mirror.getSearchCursor(from, false);
        while (cursor.findNext())
            cursor.replace(to);
    },

    jump: function() {
        var line = prompt("Jump to line:", "");
        if (line && !isNaN(Number(line)))
            this.mirror.jumpToLine(Number(line));
    },

    line: function() {
        alert("The cursor is currently at line " + this.mirror.currentLine());
        this.mirror.focus();
    },

    macro: function() {
        var name = prompt("Name your constructor:", "");
        if (name)
            this.mirror.replaceSelection("function " + name + "() {\n  \n}\n\n" + name + ".prototype = {\n  \n};\n");
    },

    reindent: function() {
        this.mirror.reindent();
    }
};
