// 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 'dart:async';

import 'package:_fe_analyzer_shared/src/messages/codes.dart'
    show Code, Message, PlainAndColorizedString;
import 'package:_fe_analyzer_shared/src/messages/diagnostic_message.dart'
    show DiagnosticMessage, DiagnosticMessageHandler;
import 'package:front_end/src/api_unstable/ddc.dart';
import 'package:kernel/ast.dart' show Component, Library;
import 'package:kernel/dart_scope_calculator.dart';

import '../compiler/js_names.dart' as js_ast;
import '../compiler/module_builder.dart';
import '../js_ast/js_ast.dart' as js_ast;
import 'compiler.dart' show Compiler;

DiagnosticMessage _createInternalError(Uri uri, int line, int col, String msg) {
  return Message(Code<String>('Expression Compiler Internal error'),
          problemMessage: msg)
      .withLocation(uri, 0, 0)
      .withFormatting(PlainAndColorizedString.plainOnly('Internal error: $msg'),
          line, col, Severity.internalProblem, []);
}

class ExpressionCompiler {
  static final String debugProcedureName = '\$dartEval';

  final CompilerContext _context;
  final CompilerOptions _options;
  final List<String> errors;
  final IncrementalCompiler _compiler;
  final Compiler _kernel2jsCompiler;
  final Component _component;
  final ModuleFormat _moduleFormat;

  DiagnosticMessageHandler onDiagnostic;

  void _log(String message) {
    if (_options.verbose) {
      _context.options.ticker.logMs(message);
    }
  }

  ExpressionCompiler(
    this._options,
    this._moduleFormat,
    this.errors,
    this._compiler,
    this._kernel2jsCompiler,
    this._component,
  )   : onDiagnostic = _options.onDiagnostic!,
        _context = _compiler.context;

  /// Compiles [expression] in library [libraryUri] and file [scriptUri]
  /// at [line]:[column] to JavaScript in [moduleName].
  ///
  /// [libraryUri] and [scriptUri] can be the same, but if for instance
  /// evaluating expressions in a part file the [libraryUri] will be the uri of
  /// the "part of" file whereas [scriptUri] will be the uri of the part.
  ///
  /// [line] and [column] are 1-based. Library level expressions typically use
  /// [line] and [column] 1 as an indicator that there is no relevant location.
  /// For flexibility, a value of 0 is also accepted and recognized
  /// in the same way.
  ///
  /// Values listed in [jsFrameValues] are substituted for their names in the
  /// [expression].
  ///
  /// Returns expression compiled to JavaScript or null on error.
  /// Errors are reported using onDiagnostic function.
  ///
  /// [jsFrameValues] is a map from js variable name to its primitive value
  /// or another variable name, for example
  /// { 'x': '1', 'y': 'y', 'o': 'null' }
  Future<String?> compileExpressionToJs(
      String libraryUri,
      String? scriptUri,
      int line,
      int column,
      Map<String, String> jsScope,
      String expression) async {
    try {
      // 1. find dart scope where debugger is paused

      _log('Compiling expression \n$expression');

      var dartScope = _findScopeAt(Uri.parse(libraryUri),
          scriptUri == null ? null : Uri.parse(scriptUri), line, column);
      if (dartScope == null) {
        _log('Scope not found at $libraryUri:$line:$column');
        return null;
      }
      _log('DartScope: $dartScope');

      // 2. perform necessary variable substitutions

      // TODO(annagrin): we only substitute for the same name or a value
      // currently, need to extend to cases where js variable names are
      // different from dart.
      // See [issue 40273](https://github.com/dart-lang/sdk/issues/40273)

      // Work around mismatched names and lowered representation for late local
      // variables.
      // Replace the existing entries with a name that matches the named
      // extracted from the lowering.
      // See https://github.com/dart-lang/sdk/issues/55918
      var dartLateLocals = [
        for (var name in dartScope.definitions.keys)
          if (isLateLoweredLocalName(name)) name,
      ];
      for (var localName in dartLateLocals) {
        dartScope.definitions[extractLocalName(localName)] =
            dartScope.definitions.remove(localName)!;
      }

      // Create a mapping from Dart variable names in scope to the corresponding
      // JS values. The Dart variable may have had a suffix of the
      // form '$N' added to it where N is either the empty string or an
      // integer >= 0.
      final dartNameToJsValue = <String, String>{};

      int nameCompare(String a, String b) {
        final lengthCmp = b.length.compareTo(a.length);
        if (lengthCmp != 0) return lengthCmp;
        return b.compareTo(a);
      }

      // Sort Dart names in case a user-defined name includes a '$'. The
      // resulting normalized JS name might seem like a suffixed version of a
      // shorter Dart name. Since longer Dart names can't incorrectly match a
      // shorter JS name (JS names are always at least as long as the Dart
      // name), we process them from longest to shortest.
      final dartNames = [...dartScope.definitions.keys]..sort(nameCompare);

      // Sort JS names so that the highest suffix value gets assigned to the
      // corresponding Dart name first. Since names are suffixed in ascending
      // order as inner scopes are visited, the highest suffix value will be
      // the one that matches the visible Dart name in a given scope.
      final jsNames = [...jsScope.keys]..sort(nameCompare);

      const removedSentinel = '';
      const thisJsName = r'$this';

      // Get the available async scopes.
      final asyncScopeRegexp = RegExp(r'^asyncScope(\$[0-9]*)?$');
      final asyncScopes = [
        ...jsNames.where((e) => asyncScopeRegexp.hasMatch(e))
      ];

      for (final dartName in dartNames) {
        if (isExtensionThisName(dartName)) {
          if (jsScope.containsKey(thisJsName)) {
            dartNameToJsValue[dartName] = jsScope[thisJsName]!;
          }
          continue;
        }
        // Any name containing a '$' symbol will have that symbol expanded to
        // '$36' in JS. We do a similar expansion here to normalize the names.
        final jsNamePrefix =
            js_ast.toJSIdentifier(dartName).replaceAll('\$', '\\\$');
        final regexp = RegExp(r'^' + jsNamePrefix + r'(\$[0-9]*)?$');
        for (var i = 0; i < jsNames.length; i++) {
          final jsName = jsNames[i];
          if (jsName == removedSentinel) continue;
          if (jsName.length < dartName.length) break;
          if (regexp.hasMatch(jsName)) {
            dartNameToJsValue[dartName] = jsScope[jsName]!;
            jsNames[i] = removedSentinel;

            // Remove any additional JS names that match this name as these will
            // correspond to shadowed Dart variables that are not visible in the
            // current scope.
            //
            // Note: In some extreme cases this can match the wrong variable.
            // This would require a combination of 36 nested variables with the
            // same name and a similarly named variable with a $ in its name.
            for (var j = i; j < jsNames.length; j++) {
              final jsName = jsNames[j];
              if (jsName == removedSentinel) continue;
              if (jsName.length < dartName.length) break;
              if (regexp.hasMatch(jsNames[j])) {
                jsNames[j] = removedSentinel;
              }
            }
            break;
          }
        }

        if (asyncScopes.isNotEmpty) {
          // Look up the value in the available async scopes.
          //
          // Creates an expression of the form:
          // "<dartName>" in asyncScope
          //   ? asyncScope["<dartName>"]
          //   : ("<dartName>" in asyncScope1
          //        ? asyncScope1["<dartName>"]
          //        : (...))
          //
          // Each 'asyncScope' variable represents a single Dart scope and the
          // keys in it match the names of the available Dart variables.
          // Each scope object is declared up front but values are not inserted
          // into it until the Dart scope is actually entered. So only "live"
          // scopes will contain keys.
          //
          // This expression will start at the innermost available scope and
          // and work its way out until it finds the first live scope that has
          // a value for the given Dart variable name.
          //
          // If the value is not found in any async scope then it defaults to
          // the nearest matching js value calculated above (which may be
          // captured from an outer scope).
          //
          // If there was no value found then this means that the variable does
          // not exist in any scope. This can occur if the browser detects the
          // JS variable is unused and so the browser doesn't capture it. In
          // this case return a special sentinel value that we can detect and
          // throw on.
          final defaultValue = dartNameToJsValue[dartName] ?? 'sentinel';
          dartNameToJsValue[dartName] = asyncScopes.fold(defaultValue,
              (p, e) => '"$dartName" in $e ? $e["$dartName"] : ($p)');
        }
      }

      // remove undefined js variables (this allows us to get a reference error
      // from chrome on evaluation)
      dartScope.definitions.removeWhere(
          (variable, type) => !dartNameToJsValue.containsKey(variable));

      dartScope.typeParameters
          .removeWhere((parameter) => !jsScope.containsKey(parameter.name));

      // map from values from the stack when available (this allows to evaluate
      // captured variables optimized away in chrome)
      var localJsScope = [
        ...dartScope.typeParameters.map((parameter) => jsScope[parameter.name]),
        ...dartScope.definitions.keys
            .map((variable) => dartNameToJsValue[variable])
      ];

      _log('Performed scope substitutions for expression');

      // 3. compile dart expression to JS

      var jsExpression = await _compileExpression(dartScope, expression);

      if (jsExpression == null) {
        _log('Failed to compile expression: \n$expression');
        return null;
      }

      // some adjustments to get proper binding to 'this',
      // making closure variables available, and catching errors

      // TODO(annagrin): make compiler produce correct expression:
      // See [issue 40277](https://github.com/dart-lang/sdk/issues/40277)
      // - evaluate to an expression in function and class context
      // - allow setting values
      // See [issue 40273](https://github.com/dart-lang/sdk/issues/40273)
      // - bind to proper 'this'
      // - map to correct js names for dart symbols

      // 4. create call the expression

      if (dartScope.cls != null && !dartScope.isStatic) {
        // bind to correct 'this' instead of 'globalThis'
        jsExpression = '$jsExpression.bind(this)';
      }

      // 5. wrap in a try/catch to catch errors

      var args = localJsScope.join(',\n    ');
      jsExpression = jsExpression.split('\n').join('\n  ');
      // We check for '_boundMethod' in case tearoffs are returned.
      var callExpression =
          '((() => {var sentinel = {}; var output = $jsExpression($args); '
          'if (output === sentinel) throw Error("Value not found in scope");'
          'return output?._boundMethod || output;})())';

      _log('Compiled expression \n$expression to $callExpression');
      return callExpression;
    } catch (e, s) {
      onDiagnostic(
          _createInternalError(Uri.parse(libraryUri), line, column, '$e:$s'));
      return null;
    }
  }

  DartScope? _findScopeAt(
      Uri libraryUri, Uri? scriptFileUri, int line, int column) {
    if (line < 0) {
      onDiagnostic(_createInternalError(
          libraryUri, line, column, 'Invalid source location'));
      return null;
    }

    var library = _getLibrary(libraryUri);
    if (library == null) {
      onDiagnostic(_createInternalError(
          libraryUri, line, column, 'Dart library not found for location'));
      return null;
    }

    // TODO(jensj): Eventually make the scriptUri required and always use this,
    // but for now use the old mechanism when no script is provided.
    if (scriptFileUri != null) {
      final offset = _component.getOffset(library.fileUri, line, column);
      final scope2 =
          DartScopeBuilder2.findScopeFromOffset(library, scriptFileUri, offset);
      return scope2;
    }

    var scope = DartScopeBuilder.findScope(_component, library, line, column);
    if (scope == null) {
      // Fallback mechanism to allow a evaluation of an expression at the
      // library level within the Dart SDK.
      //
      // Currently we lack the full dill and metadata for the Dart SDK module to
      // be able to use the same mechanism of expression evaluation as the rest
      // of a program. Because of that, expression evaluation at arbitrary
      // scopes is not supported in the Dart SDK. However, we can still support
      // compiling expressions that will be evaluated at the library level. We
      // determine if that's the case by recognizing that all such requests use
      // line 1 and column 1.
      if (line <= 1 && column <= 1 && library.importUri.isScheme('dart')) {
        _log('Fallback: use library scope for the Dart SDK');
        scope = DartScope(library, null, null, {}, []);
      } else {
        onDiagnostic(_createInternalError(
            libraryUri, line, column, 'Dart scope not found for location'));
        return null;
      }
    }

    _log('Detected expression compilation scope');
    return scope;
  }

  Library? _getLibrary(Uri libraryUri) {
    return _compiler.lookupLibrary(libraryUri);
  }

  /// Return a JS function that returns the evaluated results when called.
  ///
  /// [scope] current dart scope information.
  /// [expression] expression to compile in given [scope].
  Future<String?> _compileExpression(DartScope scope, String expression) async {
    var methodName = scope.member?.name.text;
    var member = scope.member;
    if (member != null) {
      if (member.isExtensionMember || member.isExtensionTypeMember) {
        methodName = extractQualifiedNameFromExtensionMethodName(methodName);
      }
    }
    var procedure = await _compiler.compileExpression(
        expression,
        scope.definitions,
        scope.typeParameters,
        debugProcedureName,
        scope.library.importUri,
        methodName: methodName,
        className: scope.cls?.name,
        isStatic: scope.isStatic);

    _log('Compiled expression to kernel');

    // TODO: make this code clear and assumptions enforceable
    // https://github.com/dart-lang/sdk/issues/43273
    if (errors.isNotEmpty) {
      return null;
    }

    var imports = <js_ast.ModuleItem>[];
    var jsFun = _kernel2jsCompiler.emitFunctionIncremental(imports,
        scope.library, scope.cls, procedure!.function, debugProcedureName);

    _log('Generated JavaScript for expression');

    // print JS ast to string for evaluation
    var context = js_ast.SimpleJavaScriptPrintingContext();
    var opts =
        js_ast.JavaScriptPrintingOptions(allowKeywordsInProperties: true);

    var tree = transformFunctionModuleFormat(imports, jsFun, _moduleFormat);
    tree.accept(
        js_ast.Printer(opts, context, localNamer: js_ast.ScopedNamer(tree)));

    _log('Added imports and renamed variables for expression');

    return context.getText();
  }
}
