// Copyright (c) 2020, 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.

import 'package:dwds/src/config/tool_configuration.dart';
import 'package:dwds/src/debugging/chrome_inspector.dart';
import 'package:dwds/src/debugging/dart_scope.dart';
import 'package:dwds/src/debugging/debugger.dart';
import 'package:dwds/src/debugging/location.dart';
import 'package:dwds/src/debugging/modules.dart';
import 'package:dwds/src/services/expression_compiler.dart';
import 'package:dwds/src/services/javascript_builder.dart';
import 'package:dwds/src/utilities/conversions.dart';
import 'package:dwds/src/utilities/objects.dart' as chrome;
import 'package:logging/logging.dart';
import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart';

class EvaluationErrorKind {
  EvaluationErrorKind._();

  static const compilation = 'CompilationError';
  static const type = 'TypeError';
  static const reference = 'ReferenceError';
  static const internal = 'InternalError';
  static const asyncFrame = 'AsyncFrameError';
  static const invalidInput = 'InvalidInputError';
  static const loadModule = 'LoadModuleError';
}

/// ExpressionEvaluator provides functionality to evaluate dart expressions
/// from text user input in the debugger, using chrome remote debugger to
/// collect context for evaluation (scope, types, modules), and using
/// ExpressionCompilerInterface to compile dart expressions to JavaScript.
class ExpressionEvaluator {
  final String _entrypoint;
  final ChromeAppInspector _inspector;
  final Debugger _debugger;
  final Locations _locations;
  final Modules _modules;
  final ExpressionCompiler _compiler;
  final _logger = Logger('ExpressionEvaluator');
  bool _closed = false;

  /// Strip synthetic library name from compiler error messages.
  static final _syntheticNameFilterRegex = RegExp(
    'org-dartlang-debug:synthetic_debug_expression:.*:.*Error: ',
  );

  /// Find module path from the XHR call network error message received from chrome.
  ///
  /// Example:
  /// NetworkError: Failed to load `http://<hostname>.com/path/to/module.js?<cache_busting_token>`
  static final _loadModuleErrorRegex = RegExp(
    r".*Failed to load '.*\.com/(.*\.js).*",
  );

  ExpressionEvaluator(
    this._entrypoint,
    this._inspector,
    this._debugger,
    this._locations,
    this._modules,
    this._compiler,
  );

  /// Create and error with [severity] and [message]
  ///
  /// [severity] is one of kinds in [EvaluationErrorKind]
  RemoteObject createError(String severity, String message) {
    return RemoteObject(<String, String>{'type': severity, 'value': message});
  }

  void close() {
    _closed = true;
  }

  /// Evaluate dart expression inside a given library.
  ///
  /// Uses ExpressionCompiler interface to compile the expression to
  /// JavaScript and sends evaluate requests to chrome to calculate
  /// the final result.
  ///
  /// Returns remote object containing the result of evaluation or error.
  ///
  /// [isolateId] current isolate ID.
  /// [libraryUri] dart library to evaluate the expression in.
  /// [expression] dart expression to evaluate.
  Future<RemoteObject> evaluateExpression(
    String isolateId,
    String? libraryUri,
    String expression,
    Map<String, String>? scope,
  ) async {
    if (_closed) {
      return createError(
        EvaluationErrorKind.internal,
        'expression evaluator closed.',
      );
    }

    scope ??= {};

    if (expression.isEmpty) {
      return createError(EvaluationErrorKind.invalidInput, expression);
    }

    if (libraryUri == null) {
      return createError(EvaluationErrorKind.invalidInput, 'no library uri');
    }

    final module = await _modules.moduleForLibrary(libraryUri);
    if (module == null) {
      return createError(
        EvaluationErrorKind.internal,
        'no module for $libraryUri',
      );
    }

    // Wrap the expression in a lambda so we can call it as a function.
    expression = _createDartLambda(expression, scope.keys);
    _logger.finest('Evaluating "$expression" at $module');

    // Compile expression using an expression compiler, such as
    // frontend server or expression compiler worker.
    final compilationResult = await _compiler.compileExpressionToJs(
      isolateId,
      libraryUri.toString(),
      // Evaluating at "the library level" (and passing line 0 column 0) we'll
      // also just pass the library uri as the script uri.
      libraryUri.toString(),
      0,
      0,
      {},
      {},
      module,
      expression,
    );

    final isError = compilationResult.isError;
    final jsResult = compilationResult.result;
    if (isError) {
      return _formatCompilationError(jsResult);
    }

    // Strip try/catch incorrectly added by the expression compiler.
    final jsCode = _maybeStripTryCatch(jsResult);

    // Send JS expression to chrome to evaluate.
    var result = await _callJsFunction(jsCode, scope);
    result = await _formatEvaluationError(result);

    _logger.finest('Evaluated "$expression" to "${result.json}"');
    return result;
  }

  /// Evaluate dart expression inside a given frame (function).
  ///
  /// Gets necessary context (types, scope, module names) data from chrome,
  /// uses ExpressionCompiler interface to compile the expression to
  /// JavaScript, and sends evaluate requests to chrome to calculate the
  /// final result.
  ///
  /// Returns remote object containing the result of evaluation or error.
  ///
  /// [isolateId] current isolate ID.
  /// [frameIndex] JavaScript frame to evaluate the expression in.
  /// [expression] dart expression to evaluate.
  /// [scope] additional scope to use in the expression as a map from
  ///   variable names to remote object IDs.
  ///
  /////////////////////////////////
  /// **Example - without scope**
  ///
  /// To evaluate a dart expression `e`, we perform the following:
  ///
  /// 1. compile dart expression `e` to JavaScript expression `jsExpr`
  ///    using the expression compiler (i.e. frontend server or expression
  ///    compiler worker).
  ///
  /// 2. create JavaScript wrapper expression, `jsWrapperExpr`, defined as
  ///
  ///    ```JavaScript
  ///    try {
  ///      jsExpr;
  ///    } catch (error) {
  ///      error.name + ": " + error.message;
  ///    }
  ///    ```
  ///
  /// 3. evaluate `JsExpr` using `Debugger.evaluateOnCallFrame` chrome API.
  ///
  /// //////////////////////////
  /// **Example - with scope**
  ///
  /// To evaluate a dart expression
  /// ```dart
  ///   this.t + a + x + y
  /// ```
  /// in a dart scope that defines `a` and `this`, and additional scope
  /// `x, y`, we perform the following:
  ///
  /// 1. compile dart function
  ///
  ///    ```dart
  ///    (x, y, a) { return this.t + a + x + y; }
  ///    ```
  ///
  ///    to JavaScript function
  ///
  ///    ```jsFunc```
  ///
  ///    using the expression compiler (i.e. frontend server or expression
  ///    compiler worker).
  ///
  /// 2. create JavaScript wrapper function, `jsWrapperFunc`, defined as
  ///
  ///    ```JavaScript
  ///    function (x, y, a, __t$this) {
  ///      try {
  ///        return function (x, y, a) {
  ///          return jsFunc(x, y, a);
  ///        }.bind(__t$this)(x, y, a);
  ///      } catch (error) {
  ///        return error.name + ": " + error.message;
  ///      }
  ///    }
  ///    ```
  ///
  /// 3. collect scope variable object IDs for total scope
  ///    (original frame scope from WipCallFrame + additional scope passed
  ///    by the user).
  ///
  /// 4. call `jsWrapperFunc` using `Runtime.callFunctionOn` chrome API
  ///    with scope variable object IDs passed as arguments.
  Future<RemoteObject> evaluateExpressionInFrame(
    String isolateId,
    int frameIndex,
    String expression,
    Map<String, String>? scope,
  ) async {
    scope ??= {};

    if (expression.isEmpty) {
      return createError(EvaluationErrorKind.invalidInput, expression);
    }

    // Get JS scope and current JS location.
    final jsFrame = _debugger.jsFrameForIndex(frameIndex);
    if (jsFrame == null) {
      return createError(
        EvaluationErrorKind.asyncFrame,
        'Expression evaluation in async frames '
        'is not supported. No frame with index $frameIndex.',
      );
    }

    final functionName = jsFrame.functionName;
    final jsLine = jsFrame.location.lineNumber;
    final jsScriptId = jsFrame.location.scriptId;
    final jsColumn = jsFrame.location.columnNumber;
    final frameScope = await _collectLocalFrameScope(jsFrame);

    // Find corresponding dart location and scope.
    final url = _debugger.urlForScriptId(jsScriptId);
    if (url == null) {
      return createError(
        EvaluationErrorKind.internal,
        'Cannot find url for JS script: $jsScriptId',
      );
    }
    final locationMap = await _locations.locationForJs(url, jsLine, jsColumn);
    if (locationMap == null) {
      return createError(
        EvaluationErrorKind.internal,
        'Cannot find Dart location for JS location: '
        'url: $url, '
        'function: $functionName, '
        'line: $jsLine, '
        'column: $jsColumn',
      );
    }

    final dartLocation = locationMap.dartLocation;
    final dartSourcePath = dartLocation.uri.serverPath;
    final libraryUri = await _modules.libraryForSource(dartSourcePath);
    final scriptUri = await _modules.libraryOrPartForSource(dartSourcePath);
    if (libraryUri == null) {
      return createError(
        EvaluationErrorKind.internal,
        'no libraryUri for $dartSourcePath',
      );
    }

    final module = await _modules.moduleForLibrary(libraryUri.toString());
    if (module == null) {
      return createError(
        EvaluationErrorKind.internal,
        'no module for $libraryUri ($dartSourcePath)',
      );
    }

    _logger.finest(
      'Evaluating "$expression" at $module, '
      '$libraryUri:${dartLocation.line}:${dartLocation.column} '
      'or rather $scriptUri:${dartLocation.line}:${dartLocation.column} '
      'with scope: $scope',
    );

    if (scope.isNotEmpty) {
      final totalScope = Map<String, String>.from(scope)..addAll(frameScope);
      expression = _createDartLambda(expression, totalScope.keys);
    }

    _logger.finest('Compiling "$expression"');

    // Compile expression using an expression compiler, such as
    // frontend server or expression compiler worker.
    //
    // TODO(annagrin): map JS locals to dart locals in the expression
    // and JS scope before passing them to the dart expression compiler.
    // Issue:  https://github.com/dart-lang/sdk/issues/40273
    final compilationResult = await _compiler.compileExpressionToJs(
      isolateId,
      libraryUri.toString(),
      scriptUri.toString(),
      dartLocation.line,
      dartLocation.column,
      {},
      frameScope.map((key, value) => MapEntry(key, key)),
      module,
      expression,
    );

    final isError = compilationResult.isError;
    final jsResult = compilationResult.result;
    if (isError) {
      return _formatCompilationError(jsResult);
    }

    // Strip try/catch incorrectly added by the expression compiler.
    final jsCode = _maybeStripTryCatch(jsResult);

    // Send JS expression to chrome to evaluate.
    var result = scope.isEmpty
        ? await _evaluateJsExpressionInFrame(frameIndex, jsCode)
        : await _callJsFunctionInFrame(frameIndex, jsCode, scope, frameScope);

    result = await _formatEvaluationError(result);
    _logger.finest('Evaluated "$expression" to "${result.json}"');
    return result;
  }

  /// Call JavaScript [function] with [scope] on frame [frameIndex].
  ///
  /// Wrap the [function] in a lambda that takes scope variables as parameters.
  /// Send JS expression to chrome to evaluate in frame with [frameIndex]
  /// with the provided [scope].
  ///
  /// [frameIndex] is the index of the frame to call the function in.
  /// [function] is the JS function to evaluate.
  /// [scope] is the additional scope as a map from scope variables to
  ///   remote object IDs.
  /// [frameScope] is the original scope as a map from scope variables
  ///   to remote object IDs.
  Future<RemoteObject> _callJsFunctionInFrame(
    int frameIndex,
    String function,
    Map<String, String> scope,
    Map<String, String> frameScope,
  ) async {
    final totalScope = Map<String, String>.from(scope)..addAll(frameScope);
    final thisObject = await _debugger.evaluateJsOnCallFrameIndex(
      frameIndex,
      'this',
    );

    final thisObjectId = thisObject.objectId;
    if (thisObjectId != null) {
      totalScope['this'] = thisObjectId;
    }

    return _callJsFunction(function, totalScope);
  }

  /// Call the [function] with [scope] as arguments.
  ///
  /// Wrap the [function] in a lambda that takes scope variables as parameters.
  /// Send JS expression to chrome to evaluate with the provided [scope].
  ///
  /// [function] is the JS function to evaluate.
  /// [scope] is a map from scope variables to remote object IDs.
  Future<RemoteObject> _callJsFunction(
    String function,
    Map<String, String> scope,
  ) {
    final jsCode = _createEvalFunction(function, scope.keys);

    _logger.finest('Evaluating JS: "$jsCode" with scope: $scope');
    return _inspector.callFunction(jsCode, scope.values);
  }

  /// Evaluate JavaScript [expression] on frame [frameIndex].
  ///
  /// Wrap the [expression] in a try/catch expression to catch errors.
  /// Send JS expression to chrome to evaluate on frame [frameIndex].
  ///
  /// [frameIndex] is the index of the frame to call the function in.
  /// [expression] is the JS function to evaluate.
  Future<RemoteObject> _evaluateJsExpressionInFrame(
    int frameIndex,
    String expression,
  ) {
    final jsCode = _createEvalExpression(expression);

    _logger.finest('Evaluating JS: "$jsCode"');
    return _debugger.evaluateJsOnCallFrameIndex(frameIndex, jsCode);
  }

  static String? _getObjectId(RemoteObject? object) =>
      object?.objectId ?? dartIdFor(object?.value);

  RemoteObject _formatCompilationError(String error) {
    // Frontend currently gives a text message including library name
    // and function name on compilation error. Strip this information
    // since it shows synthetic names that are only used for temporary
    // debug library during expression evaluation.
    //
    // TODO(annagrin): modify frontend to avoid stripping dummy names
    // [issue 40449](https://github.com/dart-lang/sdk/issues/40449)
    if (error.startsWith('[')) {
      error = error.substring(1);
    }
    if (error.endsWith(']')) {
      error = error.substring(0, error.lastIndexOf(']'));
    }
    if (error.contains('InternalError: ')) {
      error = error.replaceAll('InternalError: ', '');
      return createError(EvaluationErrorKind.internal, error);
    }
    error = error.replaceAll(_syntheticNameFilterRegex, '');
    return createError(EvaluationErrorKind.compilation, error);
  }

  Future<RemoteObject> _formatEvaluationError(RemoteObject result) async {
    if (result.type == 'string') {
      var error = '${result.value}';
      if (error.startsWith('ReferenceError: ')) {
        error = error.replaceFirst('ReferenceError: ', '');
        return createError(EvaluationErrorKind.reference, error);
      } else if (error.startsWith('TypeError: ')) {
        error = error.replaceFirst('TypeError: ', '');
        return createError(EvaluationErrorKind.type, error);
      } else if (error.startsWith('NetworkError: ')) {
        var modulePath = _loadModuleErrorRegex.firstMatch(error)?.group(1);
        final module = modulePath != null
            ? await globalToolConfiguration.loadStrategy.moduleForServerPath(
                _entrypoint,
                modulePath,
              )
            : 'unknown';
        modulePath ??= 'unknown';
        error =
            'Module is not loaded : $module (path: $modulePath). '
            'Accessing libraries that have not yet been used in the '
            'application is not supported during expression evaluation.';
        return createError(EvaluationErrorKind.loadModule, error);
      }
    }
    return result;
  }

  /// Return local scope as a map from variable names to remote object IDs.
  ///
  /// [frame] is the current frame index.
  Future<Map<String, String>> _collectLocalFrameScope(
    WipCallFrame frame,
  ) async {
    final scope = <String, String>{};

    void collectVariables(Iterable<chrome.Property> variables) {
      for (final p in variables) {
        final name = p.name;
        final value = p.value;
        // TODO: null values represent variables optimized by v8.
        // Show that to the user.
        if (name != null && value != null && !_isUndefined(value)) {
          final objectId = _getObjectId(p.value);
          if (objectId != null) {
            scope[name] = objectId;
          }
        }
      }
    }

    // skip library and main scope
    final scopeChain = filterScopes(frame).reversed;
    for (final scope in scopeChain) {
      final objectId = scope.object.objectId;
      if (objectId != null) {
        final scopeProperties = await _inspector.getProperties(objectId);
        collectVariables(scopeProperties);
      }
    }

    return scope;
  }

  bool _isUndefined(RemoteObject value) => value.type == 'undefined';

  static String _createDartLambda(String expression, Iterable<String> params) =>
      '(${params.join(', ')}) { return $expression; }';

  /// Strip try/catch incorrectly added by the expression compiler.
  /// TODO: remove adding try/catch block in expression compiler.
  /// https://github.com/dart-lang/webdev/issues/1341, then remove
  /// this stripping code.
  static String _maybeStripTryCatch(String jsCode) {
    // Match the wrapping generated by the expression compiler exactly
    // so the matching does not succeed naturally after the wrapping is
    // removed:
    //
    // Expression compiler's wrapping:
    //
    // '\ntry {'
    // '\n  ($jsExpression('
    // '\n    $args'
    // '\n  ))'
    // '\n} catch (error) {'
    // '\n  error.name + ": " + error.message;'
    // '\n}';
    //
    final lines = jsCode.split('\n');
    if (lines.length > 5) {
      final tryLines = lines.getRange(0, 2).toList();
      final bodyLines = lines.getRange(2, lines.length - 3);
      final catchLines = lines
          .getRange(lines.length - 3, lines.length)
          .toList();
      if (tryLines[0].isEmpty &&
          tryLines[1] == 'try {' &&
          catchLines[0] == '} catch (error) {' &&
          catchLines[1] == '  error.name + ": " + error.message;' &&
          catchLines[2] == '}') {
        return bodyLines.join('\n');
      }
    }
    return jsCode;
  }

  /// Create JS expression to pass to `Debugger.evaluateOnCallFrame`.
  static String _createEvalExpression(String expression) {
    final body = expression.split('\n').where((e) => e.isNotEmpty);

    return JsBuilder.createEvalExpression(body);
  }

  /// Create JS function  to invoke in `Runtime.callFunctionOn`.
  static String _createEvalFunction(String function, Iterable<String> params) {
    final body = function.split('\n').where((e) => e.isNotEmpty);

    return params.contains('this')
        ? JsBuilder.createEvalBoundFunction(body, params)
        : JsBuilder.createEvalStaticFunction(body, params);
  }
}
