// 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.

// This test forks a second vm process that runs a dart script as
// a debug target, single stepping through the entire program, and
// recording each breakpoint. At the end, a coverage map of the source
// is printed.
//
// Usage: dart coverage.dart [--wire] [--verbose] target_script.dart
//
//   --wire      see json messages sent between the processes.
//   --verbose   see the stdout and stderr output of the debug
//               target process.

import "dart:convert";
import "dart:io";
import "dart:utf";
import "dart:json" as JSON;


// Whether or not to print debug target process on the console.
var showDebuggeeOutput = false;

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

var debugger = null;

class Program {
  static int numBps = 0;

  // Maps source code url to source.
  static var sources = new Map<String, Source>();

  // Takes a JSON Debugger response and increments the count for
  // the source position.
  static void recordBp(Map<String,dynamic> msg) {
    // Progress indicator.
    if (++numBps % 1000 == 0) print(numBps);
    var location = msg["params"]["location"];
    if (location == null) return;
    String url = location["url"];
    assert(url != null);
    int libId = location["libraryId"];
    assert(libId != null);
    int tokenPos = location["tokenOffset"];;
    Source s = sources[url];
    if (s == null) {
      debugger.getLineNumberTable(url, libId);
      s = new Source(url);
      sources[url] = s;
    }
    s.recordBp(tokenPos);
  }

  // Prints the annotated source code.
  static void printCoverage() {
    print("Coverage info collected from $numBps breakpoints:");
    for(Source s in sources.values) s.printCoverage();
  }
}


class Source {
  final String url;

  // Maps token position to breakpoint count.
  final tokenCounts = new Map<int,int>();

  // Maps token position to line number.
  final tokenPosToLine = new Map<int,int>();

  Source(this.url);

  void recordBp(int tokenPos) {
    var count = tokenCounts[tokenPos];
    tokenCounts[tokenPos] = count == null ? 1 : count + 1;
  }

  void SetLineInfo(List lineInfoTable) {
    // Each line is encoded as an array with first element being the line
    // number, followed by pairs of (tokenPosition, textOffset).
    lineInfoTable.forEach((List<int> line) {
      int lineNumber = line[0];
      for (int t = 1; t < line.length; t += 2) {
        assert(tokenPosToLine[line[t]] == null);
        tokenPosToLine[line[t]] = lineNumber;
      }
    });
  }

  // Print out the annotated source code. For each line that has seen
  // a breakpoint, print out the maximum breakpoint count for all
  // tokens in the line.
  void printCoverage() {
    var lineCounts = new Map<int,int>();  // BP counts for each line.
    print(url);
    tokenCounts.forEach((tp, bpCount) {
      int lineNumber = tokenPosToLine[tp];
      var lineCount = lineCounts[lineNumber];
      // Remember maximum breakpoint count of all tokens in this line.
      if (lineCount == null || lineCount < bpCount) {
        lineCounts[lineNumber] = bpCount;
      }
    });

    String srcPath = Uri.parse(url).toFilePath();
    List lines = new File(srcPath).readAsLinesSync();
    for (int line = 1; line <= lines.length; line++) {
      String prefix = "      ";
      if (lineCounts.containsKey(line)) {
        prefix = lineCounts[line].toString();
        StringBuffer b = new StringBuffer();
        for (int i = prefix.length; i < 6; i++) b.write(" ");
        b.write(prefix);
        prefix = b.toString();
      }
      print("${prefix}|${lines[line-1]}");
    }
  }
}


class StepCmd {
  Map msg;
  StepCmd(int isolateId) {
    msg = {"id": 0, "command": "stepInto", "params": {"isolateId": isolateId}};
  }
  void handleResponse(Map response) {}
}


class GetLineTableCmd {
  Map msg;
  GetLineTableCmd(int isolateId, int libraryId, String url) {
    msg = { "id": 0,
            "command":  "getLineNumberTable",
            "params": { "isolateId" : isolateId,
                        "libraryId": libraryId,
                        "url": url } };
  }

  void handleResponse(Map response) {
    var url = msg["params"]["url"];
    Source s = Program.sources[url];
    assert(s != null);
    s.SetLineInfo(response["result"]["lines"]);
  }
}


class GetLibrariesCmd {
  Map msg;
  GetLibrariesCmd(int isolateId) {
    msg = { "id": 0,
            "command":  "getLibraries",
            "params": { "isolateId" : isolateId } };
  }

  void handleResponse(Map response) {
    List libs = response["result"]["libraries"];
    for (var lib in libs) {
      String url = lib["url"];
      int libraryId = lib["id"];
      bool enable = !url.startsWith("dart:") && !url.startsWith("package:");
      if (enable) {
        print("Enable stepping for '$url'");
        debugger.enableDebugging(libraryId, true);
      }
    }
  }
}


class SetLibraryPropertiesCmd {
  Map msg;
  SetLibraryPropertiesCmd(int isolateId, int libraryId, bool enableDebugging) {
    // Note that in the debugger protocol, boolean values true and false
    // must be sent as string literals.
    msg = { "id": 0,
            "command":  "setLibraryProperties",
            "params": { "isolateId" : isolateId,
                        "libraryId": libraryId,
                        "debuggingEnabled": "$enableDebugging" } };
  }

  void handleResponse(Map response) {
    // Nothing to do.
  }
}


class Debugger {
  // Debug target process properties.
  Process targetProcess;
  Socket socket;
  bool cleanupDone = false;
  JsonBuffer responses = new JsonBuffer();
  List<String> errors = new List();

  // Data collected from debug target.
  Map currentMessage = null;  // Currently handled message sent by target.
  var outstandingCommand = null;
  var queuedCommands = new List();
  String scriptUrl = null;
  bool shutdownEventSeen = false;
  int isolateId = 0;
  int libraryId = null;

  int nextMessageId = 0;
  bool isPaused = false;
  bool pendingAck = false;

  Debugger(this.targetProcess) {
    var stdoutStringStream = targetProcess.stdout
        .transform(new StringDecoder())
        .transform(new LineSplitter());
    stdoutStringStream.listen((line) {
      if (showDebuggeeOutput) {
        print("TARG: $line");
      }
      if (line.startsWith("Debugger listening")) {
        RegExp portExpr = new RegExp(r"\d+");
        var port = portExpr.stringMatch(line);
        var pid = targetProcess.pid;
        print("Coverage target process (pid $pid) found "
              "listening on port $port.");
        openConnection(int.parse(port));
      }
    });

    var stderrStringStream = targetProcess.stderr
        .transform(new StringDecoder())
        .transform(new LineSplitter());
    stderrStringStream.listen((line) {
      if (showDebuggeeOutput) {
        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;
      }
    } else if (msg["event"] == "breakpointResolved") {
      var bpId = msg["params"]["breakpointId"];
      assert(bpId != null);
      var isolateId = msg["params"]["isolateId"];
      assert(isolateId != null);
      var location = msg["params"]["location"];
      assert(location != null);
      print("Isolate $isolateId: breakpoint $bpId resolved"
            " at location $location");
      // We may want to maintain a table of breakpoints in the future.
    } else if (msg["event"] == "paused") {
      isPaused = true;
      if (libraryId == null) {
        libraryId = msg["params"]["location"]["libraryId"];
        assert(libraryId != null);
        // This is the first paused event we got. Get all libraries from
        // the debugger so we can turn on debugging events for them.
        getLibraries();
      }
      if (msg["params"]["reason"] == "breakpoint") {
        Program.recordBp(msg);
      }
    } else {
      error("Error: unknown debugger event received");
    }
  }

  // Handle one JSON message object.
  void handleMessage(Map<String,dynamic> receivedMsg) {
    currentMessage = receivedMsg;
    if (receivedMsg["event"] != null) {
      handleEvent(receivedMsg);
      if (errorsDetected) {
        error("Error while handling event message");
        error("Event received from coverage target: $receivedMsg");
      }
    } else if (receivedMsg["id"] != null) {
      // This is a response to the last command we sent.
      int id = receivedMsg["id"];
      assert(outstandingCommand != null);
      assert(outstandingCommand.msg["id"] == id);
      outstandingCommand.handleResponse(receivedMsg);
      outstandingCommand = null;
    } else {
      error("Unexpected message from target");
    }
  }

  // Handle data received over the wire from the coverage 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'");
        cleanup();
        return;
      }
      var msgObj = JSON.parse(msg);
      handleMessage(msgObj);
      if (errorsDetected) {
        error("Error while handling message from coverage target");
        error("Message received from coverage target: $msg");
        cleanup();
        return;
      }
      if (shutdownEventSeen) {
        if (outstandingCommand != null) {
          error("Error: outstanding command when shutdown received");
        }
        cleanup();
        return;
      }
      if (isPaused && (outstandingCommand == null)) {
        var cmd = queuedCommands.length > 0 ? queuedCommands.removeAt(0) : null;
        if (cmd == null) {
          cmd = new StepCmd(isolateId);
          isPaused = false;
        }
        sendMessage(cmd.msg);
        outstandingCommand = cmd;
      }
      msg = responses.getNextMessage();
    }
  }

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

  void getLineNumberTable(String url, int libId) {
    queuedCommands.add(new GetLineTableCmd(isolateId, libId, url));
  }

  void getLibraries() {
    queuedCommands.add(new GetLibrariesCmd(isolateId));
  }
  
  void enableDebugging(libraryId, enable) {
    queuedCommands.add(new SetLibraryPropertiesCmd(isolateId, libraryId, enable));
  }

  bool get errorsDetected => errors.length > 0;

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

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

  void cleanup() {
    if (cleanupDone) return;
    if (socket != null) {
      socket.close().catchError((error) {
        // Print this directly in addition to adding it to the
        // error message queue, in case the error message queue
        // gets printed before this error handler is called.
        print("Error occurred while closing socket: $error");
        error("Error while closing socket: $error");
      });
    }
    var targetPid = targetProcess.pid;
    print("Sending kill signal to process $targetPid.");
    targetProcess.kill();
    // If the process was already dead exitCode is already
    // available and we call exit() in the next event loop cycle.
    // Otherwise this will wait for the process to exit.

    targetProcess.exitCode.then((exitCode) {
      print("Process $targetPid terminated with exit code $exitCode.");
      if (errorsDetected) {
        print("\n===== Errors detected: =====");
        for (int i = 0; i < errors.length; i++) print(errors[i]);
        print("============================\n");
      }
      Program.printCoverage();
      exit(errors.length);
    });
    cleanupDone = true;
  }
}


// Class to buffer wire protocol data from coverage 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 = buffer.concat(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;
  }
}


void main() {
  var options = new Options();
  var targetOpts = [ "--debug:0" ];
  for (String str in options.arguments) {
    switch (str) {
      case "--verbose":
        showDebuggeeOutput = true;
        break;
      case "--wire":
        verboseWire = true;
        break;
      default:
        targetOpts.add(str);
        break;
    }
  }

  Process.start(options.executable, targetOpts).then((Process process) {
    process.stdin.close();
    debugger = new Debugger(process);
  });
}
