/**
 Copyright 2014 Gordon Williams (gw@pur3.co.uk)

 This Source Code is subject to the terms of the Mozilla Public
 License, v2.0. If a copy of the MPL was not distributed with this
 file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 ------------------------------------------------------------------
  An Example Plugin
 ------------------------------------------------------------------
**/
"use strict";
(function(){
  
  function init() {
    Espruino.Core.Config.add("RESET_BEFORE_SEND", {
      section : "Communications",
      name : "Reset before Send",
      description : "Reset Espruino before sending code from the editor pane?",
      type : "boolean",
      defaultValue : true
    });
  }

  function writeToEspruino(code) {  
    code = reformatCode(code);
    
    var realSendSerial = function(data) {
      console.log("Sending... "+data);
      Espruino.Core.Serial.write("echo(0);\n" + data + "\necho(1);\n");
    };
    var sendSerial = realSendSerial;
    
    // If we're supposed to reset Espruino before sending...
    if (Espruino.Config.RESET_BEFORE_SEND) {
      sendSerial = function(data) { 
        // reset espruino
        Espruino.Core.Serial.write("reset();\n");
        // wait for the reset
        setTimeout(function() {
          realSendSerial(data);
        }, 200);
      };
    } 
    
    // We want to make sure we've got a prompt before sending. If not,
    // this will issue a Ctrl+C
    var sendSerialAfterPrompt = function(data) {
      Espruino.Core.Utils.getEspruinoPrompt(function() {
        sendSerial(data);
      });
    };
    
    if(Espruino.Config.SEND_MINIFIED === true){
      Espruino.Plugins.Minify.MinifyCode(code,sendSerialAfterPrompt);
    } else {
      sendSerialAfterPrompt(code);
    }      
  };
  
  /// Parse and fix issues like `if (false)\n foo` in the root scope
  function reformatCode(code) {      
    var resultCode = "";
    /** we're looking for:
     *   `a = \n b`
     *   `for (.....) \n X`
     *   `if (.....) \n X`
     *   `while (.....) \n X`
     *   `do \n X`
     *   `function (.....) \n X`   
     *   `function N(.....) \n X`
     *   `var a \n , b`    `var a = 0 \n, b`
     *   `var a, \n b`     `var a = 0, \n b`
     *   
     *   These are divided into two groups - where there are brackets
     *   after the keyword (statementBeforeBrackets) and where there aren't
     *   (statement)
     *   
     *   We fix them by replacing \n with what you get when you press
     *   Alt+Enter (Ctrl + LF). This tells Espruino that it's a newline
     *   but NOT to execute. 
     */ 
    var lex = Espruino.Core.Utils.getLexer(code);
    var brackets = 0;
    var statementBeforeBrackets = false;
    var statement = false;
    var varDeclaration = false;
    var lastIdx = 0;
    var lastTok;
    var tok = lex.next();
    while (tok!==undefined) {
      var previousString = code.substring(lastIdx, tok.startIdx);
      var tokenString = code.substring(tok.startIdx, tok.endIdx);
      //console.log("prev "+JSON.stringify(previousString)+"   next "+tokenString);
      
      if (tok.str=="(" || tok.str=="{" || tok.str=="[") brackets++;
      
      if (brackets>0 || statement || statementBeforeBrackets || varDeclaration) {
        //console.log("Possible"+JSON.stringify(previousString));
        previousString = previousString.replace(/\n/g, "\x1B\x0A");
      }
      
      if (tok.str==")" || tok.str=="}" || tok.str=="]") brackets--;      

      
      
      if (brackets==0) {
        if (tok.str=="for" || tok.str=="if" || tok.str=="while" || tok.str=="function") {
          statementBeforeBrackets = true;
          varDeclaration = false;
        } else if (tok.str=="var") {
          varDeclaration = true;
        } else if (tok.type=="ID" && lastTok!==undefined && lastTok.str=="function") {
          statementBeforeBrackets = true;
        } else if (tok.str==")" && statementBeforeBrackets) {            
          statementBeforeBrackets = false;
          statement = true;
        } else if (tok.str=="=" || tok.str=="do") {
          statement = true;
        } else {            
          if (tok.str==";") varDeclaration = false;
          statement = false;
          statementBeforeBrackets = false;
        }          
      }
      // add our stuff back together
      resultCode += previousString + tokenString;
      // next
      lastIdx = tok.endIdx;
      lastTok = tok;
      tok = lex.next();               
    }
    //console.log(resultCode);
    return resultCode;
  };
  
  Espruino.Core.CodeWriter = {
    init : init,
    writeToEspruino : writeToEspruino,
  };
}());

@@ -2005,32 +2005,73 @@
 f (.....) %5Cn X%60%0A
+     *   %60if (.....) %7B %7D %5Cn else foo%60   %0A
      *   %60while 
@@ -2076,32 +2076,32 @@
 e (.....) %5Cn X%60%0A
-
      *   %60do %5Cn 
@@ -2259,24 +2259,68 @@
  = 0, %5Cn b%60%0A
+     *   %60a %5Cn . b%60%0A     *   %60foo() %5Cn . b%60%0A
      *   %0A  
@@ -3267,62 +3267,548 @@
  %7C%7C 
-statement %7C%7C statementBeforeBrackets %7C%7C varDeclaration
+// we have brackets - sending the special newline means Espruino doesn't have to do a search itself - faster. %0A          statement %7C%7C // statement was before brackets - expecting something else %0A          statementBeforeBrackets %7C%7C  // we have an 'if'/etc%0A          varDeclaration %7C%7C // variable declaration then newline%0A          tok.str==%22,%22 %7C%7C // comma on newline - there was probably something before%0A          tok.str==%22.%22 %7C%7C // dot on newline - there was probably something before%0A          tok.str==%22else%22 // else on newline%0A        
 ) %7B%0A
@@ -4066,24 +4066,24 @@
 ckets==0) %7B%0A
-
         if (
@@ -4148,32 +4148,52 @@
 .str==%22function%22
+ %7C%7C tok.str==%22throw%22
 ) %7B%0A          st

Reformat if...else annd dot on newlines. fix #108