// 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/diagnostic_message.dart'
    show DiagnosticMessage, DiagnosticMessageHandler;

import 'package:_fe_analyzer_shared/src/messages/codes.dart' show Message, Code;

import 'package:dev_compiler/dev_compiler.dart';
import 'package:dev_compiler/src/js_ast/js_ast.dart' as js_ast;
import 'package:dev_compiler/src/kernel/compiler.dart';

import 'package:front_end/src/api_prototype/compiler_options.dart';
import 'package:front_end/src/api_unstable/ddc.dart';

import 'package:kernel/ast.dart'
    show
        Block,
        Class,
        Component,
        DartType,
        Field,
        FunctionNode,
        Library,
        Node,
        Procedure,
        PropertyGet,
        PropertySet,
        TypeParameter,
        VariableDeclaration,
        Visitor;

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

  DartScope(this.library, this.cls, this.procedure, this.definitions,
      this.typeParameters);

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

/// DartScopeBuilder finds dart scope information in
/// [component] on a given 1-based [line]:
/// library, class, locals, formals, and any other
/// avaiable symbols at that location.
/// TODO(annagrin): Refine scope detection
/// See [issue 40278](https://github.com/dart-lang/sdk/issues/40278)
class DartScopeBuilder extends Visitor<void> {
  final Component _component;
  Library _library;
  Class _cls;
  Procedure _procedure;
  final List<FunctionNode> _functions = [];
  final int _line;
  final int _column;
  int _offset;
  final Map<String, DartType> _definitions = {};
  final List<TypeParameter> _typeParameters = [];

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

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

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

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

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

    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 visitProcedure(Procedure p) {
    if (_scopeContainsOffset(p.fileOffset, p.fileEndOffset, _offset)) {
      _procedure = p;

      super.visitProcedure(p);
    }
  }

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

      super.visitFunctionNode(fun);
    }
  }

  void _collectDefinitions(FunctionNode fun) {
    _functions.add(fun);

    // add formals
    for (var formal in fun.namedParameters) {
      _definitions[formal.name] = formal.type;
    }

    for (var formal in fun.positionalParameters) {
      _definitions[formal.name] = formal.type;
    }

    // add locals
    var body = fun.body;
    if (body is VariableDeclaration) {
      // local
      _definitions[body.name] = body.type;
    }
    if (body is Block) {
      for (var stmt in body.statements) {
        if (stmt is VariableDeclaration) {
          // local
          _definitions[stmt.name] = stmt.type;
        }
      }
    }
  }

  static bool _scopeContainsOffset(int startOffset, int endOffset, int offset) {
    if (offset < 0) return false;
    if (startOffset < 0) return false;
    if (endOffset < 0) return false;

    return startOffset <= offset && offset <= endOffset;
  }
}

class PrivateFieldsVisitor extends Visitor<void> {
  final Map<String, String> privateFields = {};

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

  @override
  void visitFieldReference(Field node) {
    if (node.name.isPrivate) {
      privateFields[node.name.text] = node.name.library.importUri.toString();
    }
  }

  @override
  void visitField(Field node) {
    if (node.name.isPrivate) {
      privateFields[node.name.text] = node.name.library.importUri.toString();
    }
  }

  @override
  void visitPropertyGet(PropertyGet node) {
    if (node.name.isPrivate) {
      privateFields[node.name.text] = node.name.library.importUri.toString();
    }
  }

  @override
  void visitPropertySet(PropertySet node) {
    if (node.name.isPrivate) {
      privateFields[node.name.text] = node.name.library.importUri.toString();
    }
  }
}

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;

  DiagnosticMessageHandler onDiagnostic;

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

  ExpressionCompiler(
    this._options,
    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].
  ///
  /// Ensures that all [jsModules] are loaded and accessible inside the
  /// expression.
  ///
  /// Returns expression compiled to JavaScript or null on error.
  /// Errors are reported using onDiagnostic function
  /// [moduleName] is of the form 'packages/hello_world_main.dart'
  /// [jsFrameValues] is a map from js variable name to its primitive value
  /// or another variable name, for example
  /// { 'x': '1', 'y': 'y', 'o': 'null' }
  /// [jsModules] is a map from variable name to the module name, where
  /// variable name is the name originally used in JavaScript to contain the
  /// module object, for example:
  /// { 'dart':'dart_sdk', 'main': 'packages/hello_world_main.dart' }
  Future<String> compileExpressionToJs(
      String libraryUri,
      int line,
      int column,
      Map<String, String> jsModules,
      Map<String, String> jsScope,
      String moduleName,
      String expression) async {
    // 1. find dart scope where debugger is paused

    _log('Compiling expression in $moduleName:\n$expression');

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

    // 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));

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

    _log('Performed scope substitutions for expression');

    // 3. compile dart expression to JS

    var jsExpression =
        await _compileExpression(dartScope, jsModules, moduleName, expression);

    if (jsExpression == null) {
      _log('Failed to compile expression in $moduleName:\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.procedure.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(', ');
    var callExpression = '''
try {
($jsExpression(
$args
))
} catch (error) {
error.name + ": " + error.message;
}''';

    _log(
        'Compiled expression in $moduleName:\n$expression to \n$callExpression');
    return callExpression;
  }

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

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

    var builder = DartScopeBuilder(_component, line, column);
    library.accept(builder);
    var scope = builder.build();
    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;
    });
  }

  /// Creates a stament to require a module to bring it back to scope
  /// example:
  /// let dart = require('dart_sdk').dart;
  js_ast.Statement _createRequireModuleStatement(
      String moduleName, String moduleVariable, String fieldName) {
    var variableName = moduleVariable.replaceFirst('.dart', '');
    var rhs = js_ast.PropertyAccess.field(
        js_ast.Call(js_ast.Identifier('require'),
            [js_ast.LiteralExpression('\'$moduleName\'')]),
        '$fieldName');

    return rhs.toVariableDeclaration(js_ast.Identifier('$variableName'));
  }

  js_ast.Statement _createPrivateField(String field, String library) {
    var libraryName = library.replaceFirst('.dart', '');
    var rhs = js_ast.Call(
        js_ast.PropertyAccess.field(js_ast.Identifier('dart'), 'privateName'), [
      js_ast.LiteralExpression(libraryName),
      js_ast.LiteralExpression('"$field"')
    ]);

    // example:
    // let _f = dart.privateName(main, "_f");
    return rhs.toVariableDeclaration(js_ast.Identifier('$field'));
  }

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

  /// Return a JS function that returns the evaluated results when called.
  ///
  /// [scope] current dart scope information
  /// [modules] map from module variable names to module names in JavaScript
  /// code. For example,
  /// { 'dart':'dart_sdk', 'main': 'packages/hello_world_main.dart' }
  /// [currentModule] current js module name.
  /// For example, in library package:hello_world/main.dart:
  /// 'packages/hello_world/main.dart'
  /// [expression] expression to compile in given [scope].
  Future<String> _compileExpression(
      DartScope scope,
      Map<String, String> modules,
      String currentModule,
      String expression) async {
    var procedure = await _compiler.compileExpression(
        expression,
        scope.definitions,
        scope.typeParameters,
        debugProcedureName,
        scope.library.importUri,
        scope.cls?.name,
        scope.procedure.isStatic);

    _log('Compiled expression to kernel');

    // TODO: make this code clear and assumptions enforceable
    // https://github.com/dart-lang/sdk/issues/43273
    //
    // We assume here that ExpressionCompiler is always created using
    // onDisgnostic method that adds to the error list that is passed
    // to the same invocation of the ExpressionCompiler constructor.
    // We only use the error list once - below, to detect if the frontend
    // compilation of the expression has failed.
    if (errors.isNotEmpty) {
      return null;
    }

    var jsFun = _kernel2jsCompiler.emitFunctionIncremental(
        scope.library, scope.cls, procedure.function, '$debugProcedureName');

    _log('Generated JavaScript for expression');

    // apply temporary workarounds for what ideally
    // needs to be done in the compiler

    // get private fields accessed by the evaluated expression
    var fieldsCollector = PrivateFieldsVisitor();
    procedure.accept(fieldsCollector);
    var privateFields = fieldsCollector.privateFields;

    // collect libraries where private fields are defined
    var currentLibraries = <String, String>{};
    var currentModules = <String, String>{};
    for (var variable in modules.keys) {
      var module = modules[variable];
      for (var field in privateFields.keys) {
        var library = privateFields[field];
        var libraryVariable =
            library.replaceAll('.dart', '').replaceAll('/', '__');
        if (libraryVariable.endsWith(variable)) {
          if (currentLibraries[field] != null) {
            onDiagnostic(_createInternalError(
                scope.library.importUri,
                0,
                0,
                'ExpressionCompiler: $field defined in more than one library: '
                '${currentLibraries[field]}, $variable'));
            return null;
          }
          currentLibraries[field] = variable;
          currentModules[variable] = module;
        }
      }
    }

    var body = js_ast.Block([
      // require modules used in evaluated expression
      ...currentModules.keys.map((String variable) =>
          _createRequireModuleStatement(
              currentModules[variable], variable, variable)),
      // re-create private field accessors
      ...currentLibraries.keys
          .map((String k) => _createPrivateField(k, currentLibraries[k])),
      // statements generated by the FE
      ...jsFun.body.statements
    ]);

    var jsFunModified = js_ast.Fun(jsFun.params, body);

    // print JS ast to string for evaluation

    var context = js_ast.SimpleJavaScriptPrintingContext();
    var opts =
        js_ast.JavaScriptPrintingOptions(allowKeywordsInProperties: true);

    jsFunModified.accept(js_ast.Printer(opts, context));
    _log('Performed JavaScript adjustments for expression');

    return context.getText();
  }
}
