// Copyright 2015 Google. All rights reserved. Use of this source code is
// governed by a BSD-style license that can be found in the LICENSE file.

import 'dart:async';
import 'dart:collection';

import '../webkit_inspection_protocol.dart';

class WipDebugger extends WipDomain {
  final _scripts = <String, WipScript>{};

  WipDebugger(WipConnection connection) : super(connection) {
    onScriptParsed.listen((event) {
      _scripts[event.script.scriptId] = event.script;
    });
    onGlobalObjectCleared.listen((_) {
      _scripts.clear();
    });
  }

  Future<WipResponse> enable() => sendCommand('Debugger.enable');

  Future<WipResponse> disable() => sendCommand('Debugger.disable');

  Future<String> getScriptSource(String scriptId) async {
    return (await sendCommand('Debugger.getScriptSource',
            params: {'scriptId': scriptId}))
        .result['scriptSource'] as String;
  }

  Future<WipResponse> pause() => sendCommand('Debugger.pause');

  Future<WipResponse> resume() => sendCommand('Debugger.resume');

  Future<WipResponse> stepInto() => sendCommand('Debugger.stepInto');

  Future<WipResponse> stepOut() => sendCommand('Debugger.stepOut');

  Future<WipResponse> stepOver() => sendCommand('Debugger.stepOver');

  Future<WipResponse> setPauseOnExceptions(PauseState state) {
    return sendCommand('Debugger.setPauseOnExceptions',
        params: {'state': _pauseStateToString(state)});
  }

  /// Sets JavaScript breakpoint at a given location.
  ///
  /// - `location`: Location to set breakpoint in
  /// - `condition`: Expression to use as a breakpoint condition. When
  ///    specified, debugger will only stop on the breakpoint if this expression
  ///    evaluates to true.
  Future<SetBreakpointResponse> setBreakpoint(
    WipLocation location, {
    String condition,
  }) async {
    Map<String, dynamic> params = {
      'location': location.toJsonMap(),
    };
    if (condition != null) {
      params['condition'] = condition;
    }

    final WipResponse response =
        await sendCommand('Debugger.setBreakpoint', params: params);

    if (response.result.containsKey('exceptionDetails')) {
      throw new ExceptionDetails(
          response.result['exceptionDetails'] as Map<String, dynamic>);
    } else {
      return new SetBreakpointResponse(response.json);
    }
  }

  /// Removes JavaScript breakpoint.
  Future<WipResponse> removeBreakpoint(String breakpointId) {
    return sendCommand('Debugger.removeBreakpoint',
        params: {'breakpointId': breakpointId});
  }

  /// Evaluates expression on a given call frame.
  ///
  /// - `callFrameId`: Call frame identifier to evaluate on
  /// - `expression`: Expression to evaluate
  /// - `returnByValue`: Whether the result is expected to be a JSON object that
  ///   should be sent by value
  Future<RemoteObject> evaluateOnCallFrame(
    String callFrameId,
    String expression, {
    bool returnByValue,
  }) async {
    Map<String, dynamic> params = {
      'callFrameId': callFrameId,
      'expression': expression,
    };
    if (returnByValue != null) {
      params['returnByValue'] = returnByValue;
    }

    final WipResponse response =
        await sendCommand('Debugger.evaluateOnCallFrame', params: params);

    if (response.result.containsKey('exceptionDetails')) {
      throw new ExceptionDetails(
          response.result['exceptionDetails'] as Map<String, dynamic>);
    } else {
      return new RemoteObject(
          response.result['result'] as Map<String, dynamic>);
    }
  }

  /// Returns possible locations for breakpoint. scriptId in start and end range
  /// locations should be the same.
  ///
  /// - `start`: Start of range to search possible breakpoint locations in
  /// - `end`: End of range to search possible breakpoint locations in
  ///   (excluding). When not specified, end of scripts is used as end of range.
  /// - `restrictToFunction`: Only consider locations which are in the same
  ///   (non-nested) function as start.
  Future<List<WipBreakLocation>> getPossibleBreakpoints(
    WipLocation start, {
    WipLocation end,
    bool restrictToFunction,
  }) async {
    Map<String, dynamic> params = {
      'start': start.toJsonMap(),
    };
    if (end != null) {
      params['end'] = end.toJsonMap();
    }
    if (restrictToFunction != null) {
      params['restrictToFunction'] = restrictToFunction;
    }

    final WipResponse response =
        await sendCommand('Debugger.getPossibleBreakpoints', params: params);

    if (response.result.containsKey('exceptionDetails')) {
      throw new ExceptionDetails(
          response.result['exceptionDetails'] as Map<String, dynamic>);
    } else {
      List locations = response.result['locations'];
      return List.from(locations.map((map) => WipBreakLocation(map)));
    }
  }

  /// Enables or disables async call stacks tracking.
  ///
  /// maxDepth - Maximum depth of async call stacks. Setting to 0 will
  /// effectively disable collecting async call stacks (default).
  Future<WipResponse> setAsyncCallStackDepth(int maxDepth) {
    return sendCommand('Debugger.setAsyncCallStackDepth', params: {
      'maxDepth': maxDepth,
    });
  }

  Stream<DebuggerPausedEvent> get onPaused => eventStream('Debugger.paused',
      (WipEvent event) => new DebuggerPausedEvent(event.json));

  Stream<GlobalObjectClearedEvent> get onGlobalObjectCleared => eventStream(
      'Debugger.globalObjectCleared',
      (WipEvent event) => new GlobalObjectClearedEvent(event.json));

  Stream<DebuggerResumedEvent> get onResumed => eventStream('Debugger.resumed',
      (WipEvent event) => new DebuggerResumedEvent(event.json));

  Stream<ScriptParsedEvent> get onScriptParsed => eventStream(
      'Debugger.scriptParsed',
      (WipEvent event) => new ScriptParsedEvent(event.json));

  Map<String, WipScript> get scripts => new UnmodifiableMapView(_scripts);
}

String _pauseStateToString(PauseState state) {
  switch (state) {
    case PauseState.all:
      return 'all';
    case PauseState.none:
      return 'none';
    case PauseState.uncaught:
      return 'uncaught';
    default:
      throw new ArgumentError('unknown state: $state');
  }
}

enum PauseState { all, none, uncaught }

class ScriptParsedEvent extends WipEvent {
  ScriptParsedEvent(Map<String, dynamic> json) : super(json);

  WipScript get script => new WipScript(params);

  String toString() => script.toString();
}

class GlobalObjectClearedEvent extends WipEvent {
  GlobalObjectClearedEvent(Map<String, dynamic> json) : super(json);
}

class DebuggerResumedEvent extends WipEvent {
  DebuggerResumedEvent(Map<String, dynamic> json) : super(json);
}

/// Fired when the virtual machine stopped on breakpoint or exception or any
/// other stop criteria.
class DebuggerPausedEvent extends WipEvent {
  DebuggerPausedEvent(Map<String, dynamic> json) : super(json);

  /// Call stack the virtual machine stopped on.
  List<WipCallFrame> getCallFrames() => (params['callFrames'] as List)
      .map((frame) => new WipCallFrame(frame as Map<String, dynamic>))
      .toList();

  /// Pause reason.
  ///
  /// Allowed Values: ambiguous, assert, debugCommand, DOM, EventListener,
  /// exception, instrumentation, OOM, other, promiseRejection, XHR.
  String get reason => params['reason'] as String;

  /// Object containing break-specific auxiliary properties.
  Object get data => params['data'];

  /// Hit breakpoints IDs (optional).
  List<String> get hitBreakpoints {
    if (params['hitBreakpoints'] == null) return null;
    return (params['hitBreakpoints'] as List).cast<String>();
  }

  /// Async stack trace, if any.
  StackTrace get asyncStackTrace => params['asyncStackTrace'] == null
      ? null
      : StackTrace(params['asyncStackTrace']);

  String toString() => 'paused: ${reason}';
}

/// A debugger call frame.
///
/// This class is for the 'debugger' domain.
class WipCallFrame {
  final Map<String, dynamic> json;

  WipCallFrame(this.json);

  /// Call frame identifier.
  ///
  /// This identifier is only valid while the virtual machine is paused.
  String get callFrameId => json['callFrameId'] as String;

  /// Name of the JavaScript function called on this call frame.
  String get functionName => json['functionName'] as String;

  /// Location in the source code.
  WipLocation get location =>
      new WipLocation(json['location'] as Map<String, dynamic>);

  /// JavaScript script name or url.
  String get url => json['url'] as String;

  /// Scope chain for this call frame.
  Iterable<WipScope> getScopeChain() => (json['scopeChain'] as List)
      .map((scope) => new WipScope(scope as Map<String, dynamic>));

  /// `this` object for this call frame.
  RemoteObject get thisObject =>
      new RemoteObject(json['this'] as Map<String, dynamic>);

  /// The value being returned, if the function is at return point.
  ///
  /// (optional)
  RemoteObject get returnValue {
    return json.containsKey('returnValue')
        ? new RemoteObject(json['returnValue'] as Map<String, dynamic>)
        : null;
  }

  String toString() => '[${functionName}]';
}

class WipLocation {
  final Map<String, dynamic> json;

  WipLocation(this.json);

  WipLocation.fromValues(String scriptId, int lineNumber, {int columnNumber})
      : json = {} {
    json['scriptId'] = scriptId;
    json['lineNumber'] = lineNumber;
    if (columnNumber != null) {
      json['columnNumber'] = columnNumber;
    }
  }

  String get scriptId => json['scriptId'];

  int get lineNumber => json['lineNumber'];

  int get columnNumber => json['columnNumber'];

  Map<String, dynamic> toJsonMap() {
    return json;
  }

  String toString() => '[${scriptId}:${lineNumber}:${columnNumber}]';
}

class WipScript {
  final Map<String, dynamic> json;

  WipScript(this.json);

  String get scriptId => json['scriptId'] as String;

  String get url => json['url'] as String;

  int get startLine => json['startLine'] as int;

  int get startColumn => json['startColumn'] as int;

  int get endLine => json['endLine'] as int;

  int get endColumn => json['endColumn'] as int;

  bool get isContentScript => json['isContentScript'] as bool;

  String get sourceMapURL => json['sourceMapURL'] as String;

  String toString() => '[script ${scriptId}: ${url}]';
}

class WipScope {
  final Map<String, dynamic> json;

  WipScope(this.json);

  // "catch", "closure", "global", "local", "with"
  String get scope => json['type'] as String;

  /// Name of the scope, null if unnamed closure or global scope
  String get name => json['name'] as String;

  /// Object representing the scope. For global and with scopes it represents
  /// the actual object; for the rest of the scopes, it is artificial transient
  /// object enumerating scope variables as its properties.
  RemoteObject get object =>
      new RemoteObject(json['object'] as Map<String, dynamic>);
}

class WipBreakLocation extends WipLocation {
  WipBreakLocation(Map<String, dynamic> json) : super(json);

  WipBreakLocation.fromValues(String scriptId, int lineNumber,
      {int columnNumber, String type})
      : super.fromValues(scriptId, lineNumber, columnNumber: columnNumber) {
    if (type != null) {
      json['type'] = type;
    }
  }

  /// Allowed Values: `debuggerStatement`, `call`, `return`.
  String get type => json['type'];
}

/// The response from [WipDebugger.setBreakpoint].
class SetBreakpointResponse extends WipResponse {
  SetBreakpointResponse(Map<String, dynamic> json) : super(json);

  String get breakpointId => result['breakpointId'];

  WipLocation get actualLocation => WipLocation(result['actualLocation']);
}
