var convert = require('./convert');

/**
 * @param {Object} config
 * @param {DebuggerClient} debuggerClient
 * @param {FrontendClient} frontendClient
 * @param {InjectorClient} injectorClient
 * @param {ConsoleClient} consoleClient
 * @constructor
 */
function ConsoleAgent(config, session) {
  this._noInject = config.inject === false;
  this._injected = false;
  this._debuggerClient = session.debuggerClient;
  this._frontendClient = session.frontendClient;
  this._injectorClient = session.injectorClient;
  this._consoleClient = session.consoleClient;
  this._translateCommandToInjection(
    'clearMessages'
  );

  if (!this._noInject) this._injectorClient.on('inject', this._inject.bind(this));
}

ConsoleAgent.prototype._inject = function(injected) {
  if (!injected) return;

  this._translateEventToFrontend(
    'messageAdded',
    'messagesCleared'
  );

  this._injectorClient.injection(
    this.injection,
    {},
    function(error, result) {
      this._injected = !error;

      if (error) return this._frontendClient.sendLogToConsole('error', error.message || error);
    }.bind(this)
  );
};

/**
 * @param {...string} eventNames
*/
ConsoleAgent.prototype._translateEventToFrontend = function(eventNames) {
  Array.prototype.forEach.call(arguments, function(event) {
    event = 'Console.' + event;
    this._debuggerClient.registerDebuggerEventHandlers(event);
    this._debuggerClient.on(event, function(message) {
      if (event == 'Console.messageAdded') {
        message.message.parameters = message.message.parameters.map(function(ref) {
          this._consoleClient.convertHandleToConsoleHandle(ref, message.message.id);
          return convert.v8ResultToInspectorResult(ref);
        }, this);
      }
      this._frontendClient.sendEvent(event, message);
    }.bind(this));
  }, this);
};

/**
 * @param {...string} commandNames
*/
ConsoleAgent.prototype._translateCommandToInjection = function(commandNames) {
  Array.prototype.forEach.call(arguments, function(command) {
    this[command] = function(params, done) {
      this._debuggerClient.request('Console.' + command, params, done);
    };
  }, this);
};

ConsoleAgent.prototype.injection = function(require, debug, options) {
  var consoleIsWrapped = false,
      nextMessageId = 0,
      messagesCache = {};

  var makeMirror = debug.get('MakeMirror');

  function ConsoleMessage(fn, wrapper, args) {
    var location = getCallerFuncLocation(wrapper);

    this.id = nextMessageId++;
    this.source = 'console-api';
    this.level = getLevel(fn);
    this.type = this.level == 'log' ? fn : undefined;
    this.line = location.line;
    this.column = location.column;
    this.url = location.url;
    this.repeatCount = 0;
    this.timestamp = Date.now();
    this.parameters = args;
  }

  function getLevel(fn) {
    return ['warning', 'error', 'debug', 'log'].indexOf(fn) > -1 ? fn : 'log';
  }

  function getCallerFuncLocation(wrapper) {
    var oldPrepareStackTrace = Error.prepareStackTrace,
        error = new Error(),
        callerFrame;

    Error.prepareStackTrace = function(error, stack) { return stack; };

    Error.captureStackTrace(error, wrapper);
    callerFrame = error.stack[0];

    Error.prepareStackTrace = oldPrepareStackTrace;

    var fileName = callerFrame.getFileName();

    // v8NameToInspectorUrl
    if (/^\//.test(fileName)) {
      fileName = 'file://' + fileName;
    } else if (/^[a-zA-Z]:\\/.test(fileName)) {
      fileName = 'file:///' + fileName.replace(/\\/g, '/');
    } else if (/^\\\\/.test(fileName)) {
      fileName = 'file://' + fileName.substring(2).replace(/\\/g, '/');
    }

    var url = fileName || callerFrame.getEvalOrigin();

    return {
      url: callerFrame.getFileName() || callerFrame.getEvalOrigin(),
      line: callerFrame.getLineNumber(),
      column: callerFrame.getColumnNumber()
    };
  }

  function clearMessages() {
    messagesCache = {};
  }

  function wrapConsole() {
    if (consoleIsWrapped) return;

    var specials = ['assert'];

    Object.keys(console).forEach(function(fn) {
      if (/^_/.test(fn)) return;
      if (specials.indexOf(fn) > -1) return;

      console['_'+fn] = console[fn];
      console[fn] = wrapFunction(fn, console[fn]);
    });

    console.assert = wrapAssertFunction('assert', console.assert);

    consoleIsWrapped = true;
  }

  function unwrapConsole() {
    if (!consoleIsWrapped) return;

    clearMessages();
    Object.keys(console).forEach(function(fn) {
      if (!/^_/.test(fn)) {
        console[fn] = console['_' + fn];
        delete console['_' + fn];
      }
    });
    consoleIsWrapped = false;
  }

  function wrapFunction(fn, func) {
    return function wrapper() {
      var args = [];
      Array.prototype.push.apply(args, arguments);

      sendMessageToInspector(fn, wrapper, args);

      return func.apply(console, args);
    };
  }

  function wrapAssertFunction(fn, func) {
    return function wrapper(condition) {
      var args = [];
      Array.prototype.push.apply(args, arguments);

      if (!condition)
        sendMessageToInspector(fn, wrapper, args);

      return func.apply(console, args);
    };
  }

  function sendMessageToInspector(fn, wrapper, args) {
    var message = new ConsoleMessage(fn, wrapper, args);

    var cache = messagesCache[message.id] = {};
    message.parameters = message.parameters.map(function(arg) {
      return debug.serializeAndCacheMirror(cache, makeMirror(arg));
    });

    debug.command('Console.messageAdded', { message: message });
  }

  debug.register('Console.messageAdded', debug.commandToEvent);
  debug.register('Console.messagesCleared', debug.commandToEvent);
  debug.register('Console.messageRepeatCountUpdated', debug.commandToEvent);

  debug.register('Console.clearMessages', function(request, response) {
    clearMessages();
    debug.command('Console.messagesCleared');
  });

  debug.register('Console._lookupConsoleId', function(request, response) {
    var messageId = request.arguments.messageId;
    var objectId = request.arguments.objectId;

    var cache = messagesCache[messageId];
    if (!cache)
      return response.failed('Console message #' + messageId + '# not found');

    var mirror = cache[objectId];
    if (!mirror)
      return response.failed('Object #' + objectId + '# not found');

    //serialize body and append serialized refs to response
    response.body = debug.serializeAndCacheMirror(cache, mirror, response);
  });

  debug.on('close', unwrapConsole);

  wrapConsole();
};

module.exports.ConsoleAgent = ConsoleAgent;

@@ -3298,329 +3298,64 @@
     
-// v8NameToInspectorUrl%0A    if (/%5E%5C//.test(fileName)) %7B%0A      fileName = 'file://' + fileName;%0A    %7D else if (/%5E%5Ba-zA-Z%5D:%5C%5C/.test(fileName)) %7B%0A      fileName = 'file:///' + fileName.replace(/%5C%5C/g, '/');%0A    %7D else if (/%5E%5C%5C%5C%5C/.test(fileName)) %7B%0A      fileName = 'file://' + fileName.substring(2).replace(/%5C%5C/g, '/');%0A    %7D
+fileName = debug.convert.v8NameToInspectorUrl(fileName);
 %0A%0A  
@@ -3436,64 +3436,11 @@
 rl: 
-callerFrame.getFileName() %7C%7C callerFrame.getEvalOrigin()
+url
 ,%0A  

Fix Console.message url