// 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.

// @dart = 2.9

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:dev_compiler/dev_compiler.dart';
import 'package:dev_compiler/src/compiler/js_names.dart' as js_ast;
import 'package:dev_compiler/src/compiler/module_builder.dart';
import 'package:dev_compiler/src/js_ast/js_ast.dart' as js_ast;
import 'package:front_end/src/api_unstable/ddc.dart';
import 'package:kernel/ast.dart'
    show
        Block,
        Class,
        Component,
        Constructor,
        DartType,
        Field,
        FunctionNode,
        Library,
        Member,
        Node,
        Procedure,
        RedirectingFactoryConstructor,
        TreeNode,
        TypeParameter,
        VariableDeclaration,
        Visitor,
        VisitorNullMixin,
        VisitorVoidMixin;

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

/// Dart scope
///
/// Provides information about symbols available inside a dart scope.
class DartScope {
  final Library library;
  final Class cls;
  final Member member;
  final bool isStatic;
  final Map<String, DartType> definitions;
  final List<TypeParameter> typeParameters;

  DartScope(this.library, this.cls, this.member, this.definitions,
      this.typeParameters)
      : isStatic = member is Procedure ? member.isStatic : false;

  @override
  String toString() {
    return '''DartScope {
      Library: ${library.importUri},
      Class: ${cls?.name},
      Procedure: $member,
      isStatic: $isStatic,
      Scope: $definitions,
      typeParameters: $typeParameters
    }
    ''';
  }
}

/// DartScopeBuilder finds dart scope information for a location.
///
/// Find all definitions in scope at a given 1-based [line] and [column]:
///
/// - library
/// - class
/// - locals
/// - formals
/// - captured variables (for closures)
class DartScopeBuilder extends Visitor<void> with VisitorVoidMixin {
  final Component _component;
  final int _line;
  final int _column;

  Library _library;
  Class _cls;
  Member _member;
  int _offset;

  DiagnosticMessageHandler onDiagnostic;

  final List<FunctionNode> _functions = [];
  final Map<String, DartType> _definitions = {};
  final List<TypeParameter> _typeParameters = [];

  DartScopeBuilder._(this._component, this._line, this._column);

  static DartScope findScope(Component component, Library library, int line,
      int column, DiagnosticMessageHandler onDiagnostic) {
    var builder = DartScopeBuilder._(component, line, column)
      ..onDiagnostic = onDiagnostic;
    library.accept(builder);
    return builder.build();
  }

  DartScope build() {
    if (_offset == null || _library == null) return null;

    return DartScope(_library, _cls, _member, _definitions, _typeParameters);
  }

  @override
  void defaultTreeNode(Node node) {
    node.visitChildren(this);
  }

  @override
  void visitLibrary(Library library) {
    _library = library;
    _offset = 0;
    if (_line > 0) {
      _offset = _component.getOffset(_library.fileUri, _line, _column);
    }

    // Exit early if the evaluation offset is not found.
    // Note: the complete scope is not found in this case,
    // so the expression compiler will report an error.
    if (_offset >= 0) super.visitLibrary(library);
  }

  @override
  void visitClass(Class cls) {
    if (_scopeContainsOffset(cls.fileOffset, cls.fileEndOffset, _offset)) {
      _cls = cls;
      _typeParameters.addAll(cls.typeParameters);

      super.visitClass(cls);
    }
  }

  @override
  void defaultMember(Member m) {
    if (_scopeContainsOffset(m.fileOffset, m.fileEndOffset, _offset)) {
      _member = m;

      super.defaultMember(m);
    }
  }

  @override
  void visitFunctionNode(FunctionNode fun) {
    if (_scopeContainsOffset(fun.fileOffset, fun.fileEndOffset, _offset)) {
      _functions.add(fun);
      _typeParameters.addAll(fun.typeParameters);

      super.visitFunctionNode(fun);
    }
  }

  @override
  void visitVariableDeclaration(VariableDeclaration decl) {
    // Collect locals and formals appearing before current breakpoint.
    // Note that we include variables with no offset because the offset
    // is not set in many cases in generated code, so omitting them would
    // make expression evaluation fail in too many cases.
    // Issue: https://github.com/dart-lang/sdk/issues/43966
    if (decl.fileOffset < 0 || decl.fileOffset < _offset) {
      _definitions[decl.name] = decl.type;
    }
    super.visitVariableDeclaration(decl);
  }

  @override
  void visitBlock(Block block) {
    var fileEndOffset = FileEndOffsetCalculator.calculateEndOffset(block);
    if (_scopeContainsOffset(block.fileOffset, fileEndOffset, _offset)) {
      super.visitBlock(block);
    }
  }

  bool _scopeContainsOffset(int startOffset, int endOffset, int offset) {
    if (offset < 0 || startOffset < 0 || endOffset < 0) {
      return false;
    }
    return startOffset <= offset && offset <= endOffset;
  }
}

/// File end offset calculator.
///
/// Helps calculate file end offsets for nodes with internal scope
/// that do not have .fileEndOffset field.
///
/// For example - [Block]
class FileEndOffsetCalculator extends Visitor<int> with VisitorNullMixin<int> {
  static const int noOffset = -1;

  final int _startOffset;
  final TreeNode _root;

  int _endOffset = noOffset;

  /// Create calculator for a scoping node with no .fileEndOffset.
  ///
  /// [_root] is the parent of the scoping node.
  /// [_startOffset] is the start offset of the scoping node.
  FileEndOffsetCalculator._(this._root, this._startOffset);

  /// Calculate file end offset for a scoping node.
  ///
  /// This calculator finds the first node in the ancestor chain that
  /// can give such information for a given [node], i.e. satisfies one
  /// of the following conditions:
  ///
  /// - a node with with a greater start offset that is a child of the
  ///   closest ancestor. The start offset of this child is used as a
  ///   file end offset of the [node].
  ///
  /// - the closest ancestor with .fileEndOffset information. The file
  ///   end offset of the ancestor is used as the file end offset of
  ///   the [node.]
  ///
  /// If none found, return [noOffset].
  static int calculateEndOffset(TreeNode node) {
    for (var n = node.parent; n != null; n = n.parent) {
      var calculator = FileEndOffsetCalculator._(n, node.fileOffset);
      var offset = n.accept(calculator);
      if (offset != noOffset) return offset;
    }
    return noOffset;
  }

  @override
  int defaultTreeNode(TreeNode node) {
    if (node == _root) {
      node.visitChildren(this);
      if (_endOffset != noOffset) return _endOffset;
      return _endOffsetForNode(node);
    }
    if (_endOffset == noOffset && node.fileOffset > _startOffset) {
      _endOffset = node.fileOffset;
    }
    return _endOffset;
  }

  static int _endOffsetForNode(TreeNode node) {
    if (node is Class) return node.fileEndOffset;
    if (node is Constructor) return node.fileEndOffset;
    if (node is Procedure) return node.fileEndOffset;
    if (node is Field) return node.fileEndOffset;
    if (node is RedirectingFactoryConstructor) return node.fileEndOffset;
    if (node is FunctionNode) return node.fileEndOffset;
    return noOffset;
  }
}

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

  final CompilerContext _context;
  final CompilerOptions _options;
  final List<String> errors;
  final IncrementalCompiler _compiler;
  final ProgramCompiler _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 [libraryUri] at [line]:[column] to JavaScript
  /// in [moduleName].
  ///
  /// [line] and [column] are 1-based.
  ///
  /// 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, 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 = await _findScopeAt(Uri.parse(libraryUri), 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)

      // remove undefined js variables (this allows us to get a reference error
      // from chrome on evaluation)
      dartScope.definitions
          .removeWhere((variable, type) => !jsScope.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) => jsScope[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  ');
      var callExpression = '\ntry {'
          '\n  ($jsExpression('
          '\n    $args'
          '\n  ))'
          '\n} catch (error) {'
          '\n  error.name + ": " + error.message;'
          '\n}';

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

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

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

    var scope = DartScopeBuilder.findScope(
        _component, library, line, column, onDiagnostic);
    if (scope == null) {
      onDiagnostic(_createInternalError(
          libraryUri, line, column, 'Dart scope not found for location'));
      return null;
    }

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

  Future<Library> _getLibrary(Uri libraryUri) async {
    return await _compiler.context.runInContext((_) async {
      var builder = _compiler.userCode.loader.builders[libraryUri];
      if (builder != null) {
        var library =
            _compiler.userCode.loader.read(libraryUri, -1, accessor: builder);

        return library.library;
      }

      _log('Loaded library for expression');
      return null;
    });
  }

  /// 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 procedure = await _compiler.compileExpression(
        expression,
        scope.definitions,
        scope.typeParameters,
        debugProcedureName,
        scope.library.importUri,
        scope.cls?.name,
        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.TemporaryNamer(tree)));

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

    return context.getText();
  }
}
