// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

// Library used by debugger wire protocol tests (standalone VM debugging).

library DartDebugger;

import "dart:async";
import "dart:io";
import "dart:math";
import "dart:utf";
import "dart:json" as JSON;

// Whether or not to print the debugger wire messages on the console.
var verboseWire = false;

// The number of attempts made to find an unused debugger port.
var retries = 0;

// Class to buffer wire protocol data from debug target and
// break it down to individual json messages.
class JsonBuffer {
  String buffer = null;

  append(String s) {
    if (buffer == null || buffer.length == 0) {
      buffer = s;
    } else {
      buffer += s;
    }
  }

  String getNextMessage() {
    if (buffer == null) return null;
    int msgLen = objectLength();
    if (msgLen == 0) return null;
    String msg = null;
    if (msgLen == buffer.length) {
      msg = buffer;
      buffer = null;
    } else {
      assert(msgLen < buffer.length);
      msg = buffer.substring(0, msgLen);
      buffer = buffer.substring(msgLen);
    }
    return msg;
  }

  bool haveGarbage() {
    if (buffer == null || buffer.length == 0) return false;
    var i = 0, char = " ";
    while (i < buffer.length) {
      char = buffer[i];
      if (char != " " && char != "\n" && char != "\r" && char != "\t") break;
      i++;
    }
    if (i >= buffer.length) {
      return false;
    } else { 
      return char != "{";
    }
  }

  // Returns the character length of the next json message in the
  // buffer, or 0 if there is only a partial message in the buffer.
  // The object value must start with '{' and continues to the
  // matching '}'. No attempt is made to otherwise validate the contents
  // as JSON. If it is invalid, a later JSON.parse() will fail.
  int objectLength() {
    int skipWhitespace(int index) {
      while (index < buffer.length) {
        String char = buffer[index];
        if (char != " " && char != "\n" && char != "\r" && char != "\t") break;
        index++;
      }
      return index;
    }
    int skipString(int index) {
      assert(buffer[index - 1] == '"');
      while (index < buffer.length) {
        String char = buffer[index];
        if (char == '"') return index + 1;
        if (char == r'\') index++;
        if (index == buffer.length) return index;
        index++;
      }
      return index;
    }
    int index = 0;
    index = skipWhitespace(index);
    // Bail out if the first non-whitespace character isn't '{'.
    if (index == buffer.length || buffer[index] != '{') return 0;
    int nesting = 0;
    while (index < buffer.length) {
      String char = buffer[index++];
      if (char == '{') {
        nesting++;
      } else if (char == '}') {
        nesting--;
        if (nesting == 0) return index;
      } else if (char == '"') {
        // Strings can contain braces. Skip their content.
        index = skipString(index);
      }
    }
    return 0;
  }
}


getJsonValue(Map jsonMsg, String path) {
  List properties = path.split(new RegExp(":"));
  assert(properties.length >= 1);
  var node = jsonMsg;
  for (int i = 0; i < properties.length; i++) {
    if (node == null) return null;
    String property = properties[i];
    var index = null;
    if (property.endsWith("]")) {
      var bracketPos = property.lastIndexOf("[");
      if (bracketPos <= 0) return null;
      var indexStr = property.substring(bracketPos + 1, property.length - 1);
      try {
        index = int.parse(indexStr);
      } on FormatException {
        print("$indexStr is not a valid array index");
        return null;
      }
      property = property.substring(0, bracketPos);
    }
    if (node is Map) {
      node = node[property];
    } else {
      return null;
    }
    if (index != null) {
      if (node is List && node.length > index) {
        node = node[index];
      } else {
        return null;
      }
    }
  }
  return node;
}


// Returns true if [template] is a subset of [map].
bool matchMaps(Map template, Map msg) {
  bool isMatch = true;
  template.forEach((k, v) {
    if (msg.containsKey(k)) {
      var receivedValue = msg[k];
      if ((v is Map) && (receivedValue is Map)) {
        if (!matchMaps(v, receivedValue)) isMatch = false;
      } else if (v == null) {
        // null in the template matches everything.
      } else if (v != receivedValue) {
        isMatch = false;
      }
    } else {
      isMatch = false;
    }
  });
  return isMatch;
}


class Command {
  var template;

  void send(Debugger debugger) {
    debugger.sendMessage(template);
  }

  void matchResponse(Debugger debugger) {
    Map response = debugger.currentMessage;
    var id = template["id"];
    assert(id != null && id >= 0);
    if (response["id"] != id) {
      debugger.error("Expected messaged id $id but got ${response["id"]}.");
    }
  }
}


class FrameMatcher extends Command {
  int frameIndex;
  List<String> functionNames;

  FrameMatcher(this.frameIndex, this.functionNames) {
    template = {"id": 0, "command": "getStackTrace", "params": {"isolateId": 0}};
  }

  void matchResponse(Debugger debugger) {
    super.matchResponse(debugger);
    var msg = debugger.currentMessage;
    List frames = getJsonValue(msg, "result:callFrames");
    assert(frames != null);
    if (debugger.scriptUrl == null) {
      var name = frames[0]["functionName"];
      if (name == "main") {
        // Extract script url of debugged script.
        debugger.scriptUrl = frames[0]["location"]["url"];
        assert(debugger.scriptUrl != null);
      }
    }
    if (frames.length < functionNames.length) {
      debugger.error("stack trace not long enough "
                     "to match ${functionNames.length} frames");
      return;
    }
    for (int i = 0; i < functionNames.length; i++) {
      var idx = i + frameIndex;
      var name = frames[idx]["functionName"];
      assert(name != null);
      if (name != functionNames[i]) {
        debugger.error("call frame $idx: "
          "expected function name '${functionNames[i]}' but found '$name'");
        return;
      }
    }
  }
}


MatchFrame(int frameIndex, String functionName) {
  return new FrameMatcher(frameIndex, [ functionName ]);
}

MatchFrames(List<String> functionNames) {
  return new FrameMatcher(0, functionNames);
}


class RunCommand extends Command {
  RunCommand.resume() {
    template = {"id": 0, "command": "resume", "params": {"isolateId": 0}};
  }
  RunCommand.step() {
    template = {"id": 0, "command": "stepOver", "params": {"isolateId": 0}};
  }
  void send(Debugger debugger) {
    debugger.sendMessage(template);
    debugger.isPaused = false;
  }
}


Resume() => new RunCommand.resume();
Step() => new RunCommand.step();


class SetBreakpointCommand extends Command {
  int line;
  SetBreakpointCommand(int this.line) {
    template = {"id": 0,
                "command": "setBreakpoint",
                "params": { "isolateId": 0,
                            "url": null,
                            "line": null }};
  }

  void send(Debugger debugger) {
    assert(debugger.scriptUrl != null);
    template["params"]["url"] = debugger.scriptUrl;
    template["params"]["line"] = line;
    debugger.sendMessage(template);
  }
}

SetBreakpoint(int line) => new SetBreakpointCommand(line);


// A debug script is a list of Command objects.
class DebugScript {
  List entries;
  DebugScript(List scriptEntries) {
    entries = new List.from(scriptEntries.reversed);
    entries.add(MatchFrame(0, "main"));
  }
  bool get isEmpty => entries.isEmpty;
  get currentEntry => entries.last;
  advance() => entries.removeLast();
  add(entry) => entries.add(entry);
}


class Debugger {
  // Debug target process properties.
  Process targetProcess;
  int portNumber;
  Socket socket;
  JsonBuffer responses = new JsonBuffer();

  DebugScript script;
  int seqNr = 0;  // Sequence number of next debugger command message.
  Command lastCommand = null;  // Most recent command sent to target.
  List<String> errors = new List();

  // Data collected from debug target.
  Map currentMessage = null;  // Currently handled message sent by target.
  String scriptUrl = null;
  bool shutdownEventSeen = false;
  int isolateId = 0;
  bool isPaused = false;

  Debugger(this.targetProcess, this.portNumber, this.script) {
    stdin.listen((_) {});
    var stdoutStringStream = targetProcess.stdout
        .transform(new StringDecoder())
        .transform(new LineTransformer());
    stdoutStringStream.listen((line) {
      if (line == "Debugger initialized") {
        openConnection();
      }
      print("TARG: $line");
    });

    var stderrStringStream = targetProcess.stderr
        .transform(new StringDecoder())
        .transform(new LineTransformer());
    stderrStringStream.listen((line) {
      print("TARG: $line");
    });
  }

  // Handle debugger events, updating the debugger state.
  void handleEvent(Map<String,dynamic> msg) {
    if (msg["event"] == "isolate") {
      if (msg["params"]["reason"] == "created") {
        isolateId = msg["params"]["id"];
        assert(isolateId != null);
        print("Debuggee isolate id $isolateId created.");
      } else if (msg["params"]["reason"] == "shutdown") {
        print("Debuggee isolate id ${msg["params"]["id"]} shut down.");
        shutdownEventSeen = true;
        if (!script.isEmpty) {
          error("Premature isolate shutdown event seen.");
        }
      }
    } else if (msg["event"] == "breakpointResolved") {
      // Ignore the event. We may want to maintain a table of
      // breakpoints in the future.
    } else if (msg["event"] == "paused") {
      isPaused = true;
    } else {
      error("unknown debugger event received");
    }
  }

  // Handle one JSON message object and match it to the
  // expected events and responses in the debugging script.
  void handleMessage(Map<String,dynamic> receivedMsg) {
    currentMessage = receivedMsg;
    if (receivedMsg["event"] != null) {
      handleEvent(receivedMsg);
      if (errorsDetected) {
        error("Error while handling debugger event");
        error("Event received from debug target: $receivedMsg");
      }
    } else if (receivedMsg["id"] != null) {
      // This is a response to the last command we sent.
      assert(lastCommand != null);
      lastCommand.matchResponse(this);
      lastCommand = null;
      if (errorsDetected) {
        error("Error while matching response to debugger command");
        error("Response received from debug target: $receivedMsg");
      }
    }
  }

  // Send next debugger command in the script, if a response
  // form the last command has been received and processed.
  void sendNextCommand() {
    if (lastCommand == null) {
      if (script.currentEntry is Command) {
        script.currentEntry.send(this);
        lastCommand = script.currentEntry;
        seqNr++;
        script.advance();
      }
    }
  }

  // Handle data received over the wire from the debug target
  // process. Split input from JSON wire format into individual
  // message objects (maps).
  void handleMessages() {
    var msg = responses.getNextMessage();
    while (msg != null) {
      if (verboseWire) print("RECV: $msg");
      if (responses.haveGarbage()) {
        error("Error: leftover text after message: '${responses.buffer}'");
        error("Previous message may be malformed, was: '$msg'");
        close(killDebugee: true);
        return;
      }
      var msgObj = JSON.parse(msg);
      handleMessage(msgObj);
      if (errorsDetected) {
        error("Error while handling script entry");
        error("Message received from debug target: $msg");
        close(killDebugee: true);
        return;
      }
      if (shutdownEventSeen) {
        close();
        return;
      }
      if (isPaused) sendNextCommand();
      msg = responses.getNextMessage();
    }
  }

  runScript(List entries) {
    script = new DebugScript(entries);
    openConnection();
  }

  // Send a debugger command to the target VM.
  void sendMessage(Map<String,dynamic> msg) {
    if (msg["id"] != null) {
      msg["id"] = seqNr;
    }
    if (msg["params"] != null && msg["params"]["isolateId"] != null) {
      msg["params"]["isolateId"] = isolateId;
    }
    String jsonMsg = JSON.stringify(msg);
    if (verboseWire) print("SEND: $jsonMsg");
    socket.write(jsonMsg);
  }

  bool get errorsDetected => errors.length > 0;

  // Record error message.
  void error(String s) {
    errors.add(s);
  }

  void openConnection() {
    Socket.connect("127.0.0.1", portNumber).then((s) {
        this.socket = s;
        var stringStream = socket.transform(new StringDecoder());
        stringStream.listen((str) {
            try {
              responses.append(str);
              handleMessages();
            } catch(e, trace) {
              print("Unexpected exception:\n$e\n$trace");
              close(killDebugee: true);
            }
          },
          onDone: () {
            print("Connection closed by debug target");
            close(killDebugee: true);
          },
          onError: (e) {
            print("Error '$e' detected in input stream from debug target");
            var trace = getAttachedStackTrace(e);
            if (trace != null) print("StackTrace: $trace");
            close(killDebugee: true);
          });
      },
      onError: (e) {
        String msg = "Error while connecting to debugee: $e";
        var trace = getAttachedStackTrace(e);
        if (trace != null) msg += "\nStackTrace: $trace";
        error(msg);
        close(killDebugee: true);
      });
  }

  void close({killDebugee: false}) {
    if (errorsDetected) {
      for (int i = 0; i < errors.length; i++) print(errors[i]);
    }
    if (socket != null) socket.close();
    if (killDebugee) {
      targetProcess.kill();
      print("Target process killed");
    }
    if (errorsDetected) throw "Errors detected";
    exit(errors.length);
  }
}


bool RunScript(List script) {
  var options = new Options();
  if (options.arguments.contains("--debuggee")) {
    return false;
  }
  verboseWire = options.arguments.contains("--wire");
  
  // Pick a port in the upper half of the port number range.
  var seed = new DateTime.now().millisecondsSinceEpoch;
  Random random = new Random(seed);
  var debugPort = random.nextInt(32000) + 32000;
  print('using debug port $debugPort ...');
  ServerSocket.bind('127.0.0.1', debugPort).then((ServerSocket s) {
      s.close();
      var targetOpts = [ "--debug:$debugPort" ];
      // --verbose_debug is necessary so the test knows when the debuggee
      // is initialized.
      targetOpts.add("--verbose_debug");
      targetOpts.add(options.script);
      targetOpts.add("--debuggee");
      print('args: ${targetOpts.join(" ")}');

      Process.start(options.executable, targetOpts).then((Process process) {
        print("Debug target process started");
        process.stdin.close();
        process.exitCode.then((int exitCode) {
          if (exitCode != 0) throw "bad exit code: $exitCode";
          print("Debug target process exited with exit code $exitCode");
        });
        var debugger =
            new Debugger(process, debugPort, new DebugScript(script));
      });
    },
    onError: (e) {
      if (++retries >= 3) { 
        print('unable to find unused port: $e');
        var trace = getAttachedStackTrace(e);
        if (trace != null) print("StackTrace: $trace");
        return -1; 
      } else {
        // Retry with another random port.
        RunScript(script);
      }
    });
  return true;
}
