// Copyright 2015 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

function DebuggerClient() {
  this.DEBUGGER_DETACHED = 0;
  this.DEBUGGER_ATTACHING = 1;
  this.DEBUGGER_ATTACHED = 2;
  this.DEBUGGER_DISABLED = 3;
  this.scripts = [];
  this.attachState = this.DEBUGGER_DETACHED;
  this.onAttachCallback = this.onAttach.bind(this);
  this.onEventCallback = this.onEvent.bind(this);
  this.executionContext = undefined;
}

// Attaches to the debugger and listens for debug events.
// Enables the domains we care about here.
DebuggerClient.prototype.attach = function () {
  if (this.attachState == this.DEBUGGER_DETACHED) {
    this.attachState = this.DEBUGGER_ATTACHING;
    printToMessageLog(MessageLog.INTERACTIVE,
      'Attempting to attach to debugger...');
    this.scripts = [];
    debugHub.onEvent.addListener(this.onEventCallback);
    debugHub.attach(this.onAttachCallback);
    this.sendCommand('Console.enable');
    this.sendCommand('Log.enable');
    this.sendCommand('Runtime.enable');
  } else if (this.attachState == this.DEBUGGER_ATTACHING) {
    printToMessageLog(MessageLog.INTERACTIVE,
      'Still attempting to attach to debugger...');
  }
}

// Local method to list the parsed scripts the client has been notified of
// via the |Debugger.scriptParsed| event. Maps the possibly very long script id
// from the debug dispatcher to a more human-readable 0-based index.
DebuggerClient.prototype.getScripts = function (scriptId) {
  for (var i in this.scripts) {
    var index = this.pad(i, 3);
    var scriptUrl = this.scripts[i].url;
    printToMessageLog(MessageLog.INTERACTIVE, index + ': ' + scriptUrl);
  }
}

//--- Commands.

// Each debugger command has an associated callback to get the result.

DebuggerClient.prototype.getScriptSource = function (scriptId) {
  // If the id looks like an index into the local script array, look it up there.
  if (scriptId >= 0 && scriptId < this.scripts.length) {
    scriptId = this.scripts[scriptId].scriptId;
  }

  var method = 'Debugger.getScriptSource';
  var params = { 'scriptId': scriptId.toString() };
  var callback = this.getScriptSourceCallback.bind(this);
  this.sendCommand(method, params, callback);
}

DebuggerClient.prototype.getScriptSourceCallback = function (result) {
  var scriptSource = result.scriptSource;
  var lines = scriptSource.split('\n');
  for (var i = 0; i < lines.length; i++) {
    var index = this.pad(i + 1, 4);
    printToMessageLog(MessageLog.INFO, index + ': ' + lines[i]);
  }
}

DebuggerClient.prototype.evaluate = function (expression, callback) {
  var method = 'Runtime.evaluate';
  var params = {};
  params.contextId = this.executionContext;
  params.expression = expression;
  params.generatePreview = true;
  params.includeCommandLineAPI = true;
  params.objectGroup = 'console';
  params.returnByValue = false;
  this.sendCommand(method, params, callback);
}

// All debugger commands are routed through this method. Converts the command
// parameters into a JSON string to pass to the debug dispatcher.
DebuggerClient.prototype.sendCommand = function (method, commandParams,
  callback) {
  var jsonParams = JSON.stringify(commandParams);
  var responseCallback = this.responseCallback.bind(this, method, callback);
  debugHub.sendCommand(method, jsonParams, responseCallback);
}

// All command responses are routed through this method. Parses the JSON
// response from the debug dispatcher, checks for errors and passes on to the
// command-specific callback to handle the result.
DebuggerClient.prototype.responseCallback = function (method, callback,
  responseString) {
  var response = JSON.parse(responseString);

  if (response && response.error) {
    printToMessageLog(
      MessageLog.ERROR,
      '[ERROR(' + response.error.code + '):' + method + '] ' +
      response.error.message);
  } else if (callback) {
    if (response) {
      callback(response.result);
    } else {
      callback(null);
    }
  }
}

//-- Events.

DebuggerClient.prototype.onAttach = function () {
  if (debugHub.lastError) {
    printToMessageLog(MessageLog.WARNING, 'Could not attach to debugger.');
    this.attachState = this.DEBUGGER_DISABLED;
  } else {
    printToMessageLog(MessageLog.INTERACTIVE, 'Debugger attached.');
    this.attachState = this.DEBUGGER_ATTACHED;
  }
}

// All events generated by the debug dispatcher are routed through this method.
// Parses the JSON string and passes on to the appropriate handler according to
// the method name.
DebuggerClient.prototype.onEvent = function (method, paramString) {
  var params = JSON.parse(paramString);
  if (method == 'Console.messageAdded') {
    this.onConsoleMessageAdded(params)
  } else if (method == 'Debugger.scriptParsed') {
    this.onScriptParsed(params);
  } else if (method == 'Inspector.detached') {
    this.onDetached(params);
  } else if (method == 'Log.browserEntryAdded' || method == 'Log.entryAdded') {
    this.onLogEntryAdded(params);
  } else if (method == 'Runtime.consoleAPICalled') {
    this.onConsoleApiCalled(params);
  } else if (method == 'Runtime.executionContextCreated') {
    this.onExecutionContextCreated(params);
  }
}

DebuggerClient.prototype.onDetached = function () {
  printToMessageLog(MessageLog.INTERACTIVE, 'Debugger detached.');
  this.attachState = this.DEBUGGER_DETACHED;
}

DebuggerClient.prototype.onExecutionContextCreated = function (params) {
  this.executionContext = params.context.id;
  printToMessageLog(MessageLog.INFO,
    'Execution context created: ' + this.executionContext);
}

DebuggerClient.prototype.onLogEntryAdded = function (params) {
  printToMessageLog(params.entry.level, params.entry.text);
}


DebuggerClient.prototype.onConsoleMessageAdded = function (params) {
  // Translate Console.messageAdded params to Runtime.consoleAPICalled params.
  var consoleApiParams = {
    type: params.message.level,
    args: [{ type: 'string', value: params.message.text }]
  };
  this.onConsoleApiCalled(consoleApiParams);
}

DebuggerClient.prototype.onConsoleApiCalled = function (params) {
  var severity = params.type;
  if (severity === "assert") {
    severity = MessageLog.ERROR;
  } else if (severity === "log") {
    severity = MessageLog.INFO;
  }

  var message = '';
  if (params.args.length) {
    var arg = params.args[0];
    if (arg.unserializableValue) {
      message = arg.unserializableValue;
    } else if (typeof arg.value !== 'object' || arg.value === null) {
      message = arg.value + '';
    } else if (arg.description) {
      message = arg.description;
    }
  }

  printToMessageLog(MessageLog.CONSOLE + severity, message);
}

DebuggerClient.prototype.onScriptParsed = function (params) {
  this.scripts.push(params);
}

//--- Utils.

DebuggerClient.prototype.pad = function (number, minLength) {
  var result = number.toString();
  while (result.length < minLength) {
    result = ' ' + result;
  }
  return result;
}
