// Copyright (c) 2022, 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:_fe_analyzer_shared/src/messages/codes.dart'
    show Message, LocatedMessage, messageWasmImportOrExportInUserCode;
import 'package:_js_interop_checks/js_interop_checks.dart';
import 'package:_js_interop_checks/src/js_interop.dart' as jsInteropHelper;
import 'package:_js_interop_checks/src/transformations/shared_interop_transformer.dart';
import 'package:front_end/src/api_prototype/const_conditional_simplifier.dart'
    show ConstConditionalSimplifier;
import 'package:front_end/src/api_prototype/constant_evaluator.dart'
    as constantEvaluator show ConstantEvaluator;
import 'package:kernel/ast.dart';
import 'package:kernel/class_hierarchy.dart';
import 'package:kernel/clone.dart';
import 'package:kernel/core_types.dart';
import 'package:kernel/reference_from_index.dart';
import 'package:kernel/target/changed_structure_notifier.dart';
import 'package:kernel/target/targets.dart';
import 'package:kernel/type_environment.dart';
import 'package:kernel/verifier.dart';
import 'package:vm/modular/transformations/ffi/common.dart' as ffiHelper
    show calculateTransitiveImportsOfDartFfiIfUsed;
import 'package:vm/modular/transformations/ffi/definitions.dart'
    as transformFfiDefinitions show transformLibraries;
import 'package:vm/modular/transformations/ffi/use_sites.dart'
    as transformFfiUseSites show transformLibraries;
import 'package:vm/modular/transformations/mixin_full_resolution.dart'
    as transformMixins show transformLibraries;

import 'await_transformer.dart' as awaitTrans;
import 'ffi_native_address_transformer.dart' as wasmFfiNativeAddressTrans;
import 'ffi_native_transformer.dart' as wasmFfiNativeTrans;
import 'records.dart' show RecordShape;
import 'transformers.dart' as wasmTrans;

enum Mode {
  regular,
  jsCompatibility,
}

class Dart2WasmConstantsBackend extends ConstantsBackend {
  const Dart2WasmConstantsBackend();

  @override
  bool get supportsUnevaluatedConstants => true;
}

class ConstantResolver extends Transformer {
  ConstantResolver(this.evaluator);

  final constantEvaluator.ConstantEvaluator evaluator;

  StaticTypeContext? _context;

  @override
  TreeNode visitLibrary(Library library) {
    final oldContext = _context;
    _context =
        StaticTypeContext.forAnnotations(library, evaluator.typeEnvironment);
    final result = super.visitLibrary(library);
    _context = oldContext;
    return result;
  }

  @override
  TreeNode defaultMember(Member member) {
    final oldContext = _context;
    _context = StaticTypeContext(member, evaluator.typeEnvironment);
    final result = super.defaultMember(member);
    _context = oldContext;
    return result;
  }

  @override
  TreeNode visitConstantExpression(ConstantExpression node) {
    final constant = node.constant;
    if (constant is UnevaluatedConstant) {
      final expression = constant.expression;
      final newConstant = evaluator.evaluate(_context!, expression);
      ConstantExpression result =
          ConstantExpression(newConstant, node.getStaticType(_context!))
            ..fileOffset = node.fileOffset;

      return result;
    }
    return node;
  }
}

class WasmTarget extends Target {
  WasmTarget(
      {this.enableExperimentalFfi = true,
      this.enableExperimentalWasmInterop = true,
      this.removeAsserts = false,
      this.mode = Mode.regular});

  final bool removeAsserts;
  final Mode mode;
  final bool enableExperimentalFfi;
  final bool enableExperimentalWasmInterop;
  Class? _growableList;
  Class? _immutableList;
  Class? _wasmDefaultMap;
  Class? _wasmDefaultSet;
  Class? _wasmImmutableMap;
  Class? _wasmImmutableSet;
  Class? _jsString;
  Class? _closure;
  Class? _boxedInt;
  Class? _boxedDouble;
  Map<String, Class>? _nativeClasses;

  @override
  bool get enableNoSuchMethodForwarders => true;

  @override
  ConstantsBackend get constantsBackend => const Dart2WasmConstantsBackend();

  @override
  Verification get verification => const WasmVerification();

  @override
  String get name {
    return switch (mode) {
      Mode.regular => 'wasm',
      Mode.jsCompatibility => 'wasm_js_compatibility'
    };
  }

  String get platformFile {
    return switch (mode) {
      Mode.regular => 'dart2wasm_platform.dill',
      Mode.jsCompatibility => 'dart2wasm_js_compatibility_platform.dill'
    };
  }

  @override
  TargetFlags get flags => TargetFlags();

  @override
  List<String> get extraRequiredLibraries => [
        'dart:_boxed_bool',
        'dart:_boxed_double',
        'dart:_boxed_int',
        'dart:_compact_hash',
        'dart:_http',
        'dart:_internal',
        'dart:_js_helper',
        'dart:_js_types',
        'dart:_list',
        'dart:_string',
        'dart:_wasm',
        'dart:async',
        'dart:developer',
        'dart:ffi',
        'dart:io',
        'dart:js_interop',
        'dart:js_interop_unsafe',
        'dart:js_util',
        'dart:nativewrappers',
        'dart:typed_data',
      ];

  @override
  List<String> get extraIndexedLibraries => [
        'dart:_boxed_bool',
        'dart:_boxed_double',
        'dart:_boxed_int',
        'dart:_compact_hash',
        'dart:_error_utils',
        'dart:_js_helper',
        'dart:_js_types',
        'dart:_list',
        'dart:_string',
        'dart:_wasm',
        'dart:collection',
        'dart:js_interop',
        'dart:js_interop_unsafe',
        'dart:js_util',
        'dart:typed_data',
      ];

  @override
  bool mayDefineRestrictedType(Uri uri) => uri.isScheme('dart');

  @override
  bool allowPlatformPrivateLibraryAccess(Uri importer, Uri imported) {
    if (super.allowPlatformPrivateLibraryAccess(importer, imported)) {
      return true;
    }

    if (imported.toString() == 'dart:_wasm') {
      return enableExperimentalWasmInterop;
    }

    final importerString = importer.toString();

    // We have some tests that import dart:js*
    if (importerString.contains('tests/web/wasm')) return true;

    // Flutter's dart:ui is also package:ui (in test mode)
    if (importerString.startsWith('package:ui/')) return true;

    // package:js can import dart:js_util & dart:_js_*
    if (importerString.startsWith('package:js/')) return true;

    return false;
  }

  void _patchHostEndian(CoreTypes coreTypes) {
    // Fix Endian.host to be a const field equal to Endian.little instead of
    // a final field. Wasm is a little-endian platform.
    // Can't use normal patching process for this because CFE does not
    // support patching fields.
    // See http://dartbug.com/32836 for the background.
    final Field host =
        coreTypes.index.getField('dart:typed_data', 'Endian', 'host');
    final Field little =
        coreTypes.index.getField('dart:typed_data', 'Endian', 'little');
    host.isConst = true;
    host.initializer = CloneVisitorNotMembers().clone(little.initializer!)
      ..parent = host;
  }

  void _performJSInteropTransformations(
      Component component,
      CoreTypes coreTypes,
      ClassHierarchy hierarchy,
      Set<Library> interopDependentLibraries,
      DiagnosticReporter diagnosticReporter,
      ReferenceFromIndex? referenceFromIndex) {
    _nativeClasses ??= JsInteropChecks.getNativeClasses(component);
    final jsInteropReporter = JsInteropDiagnosticReporter(
        diagnosticReporter as DiagnosticReporter<Message, LocatedMessage>);
    final jsInteropChecks = JsInteropChecks(
        coreTypes, hierarchy, jsInteropReporter, _nativeClasses!,
        isDart2Wasm: true, enableExperimentalFfi: enableExperimentalFfi);
    // Process and validate first before doing anything with exports.
    for (Library library in interopDependentLibraries) {
      jsInteropChecks.visitLibrary(library);
    }
    final sharedInteropTransformer = SharedInteropTransformer(
        TypeEnvironment(coreTypes, hierarchy),
        jsInteropReporter,
        jsInteropChecks.exportChecker,
        jsInteropChecks.extensionIndex);
    for (Library library in interopDependentLibraries) {
      sharedInteropTransformer.visitLibrary(library);
    }
  }

  @override
  void performPreConstantEvaluationTransformations(
      Component component,
      CoreTypes coreTypes,
      List<Library> libraries,
      DiagnosticReporter diagnosticReporter,
      {void Function(String msg)? logger,
      ChangedStructureNotifier? changedStructureNotifier}) {
    _patchHostEndian(coreTypes);
  }

  @override
  void performModularTransformationsOnLibraries(
      Component component,
      CoreTypes coreTypes,
      ClassHierarchy hierarchy,
      List<Library> libraries,
      Map<String, String>? environmentDefines,
      DiagnosticReporter diagnosticReporter,
      ReferenceFromIndex? referenceFromIndex,
      {void Function(String msg)? logger,
      ChangedStructureNotifier? changedStructureNotifier}) {
    if (!enableExperimentalWasmInterop) {
      // Check `wasm:import` and `wasm:export` pragmas before FFI transforms as
      // FFI transforms convert JS interop annotations to these pragmas.
      _checkWasmImportExportPragmas(libraries, coreTypes,
          diagnosticReporter as DiagnosticReporter<Message, LocatedMessage>);
    }

    Set<Library> transitiveImportingJSInterop = {
      ...jsInteropHelper.calculateTransitiveImportsOfJsInteropIfUsed(
          component.libraries, Uri.parse("package:js/js.dart")),
      ...jsInteropHelper.calculateTransitiveImportsOfJsInteropIfUsed(
          component.libraries, Uri.parse("dart:_js_annotations")),
      ...jsInteropHelper.calculateTransitiveImportsOfJsInteropIfUsed(
          component.libraries, Uri.parse("dart:js_interop")),
      ...jsInteropHelper.calculateTransitiveImportsOfJsInteropIfUsed(
          component.libraries, Uri.parse("dart:convert")),
      ...jsInteropHelper.calculateTransitiveImportsOfJsInteropIfUsed(
          component.libraries, Uri.parse("dart:_string")),
    };
    if (transitiveImportingJSInterop.isEmpty) {
      logger?.call("Skipped JS interop transformations");
    } else {
      _performJSInteropTransformations(component, coreTypes, hierarchy,
          transitiveImportingJSInterop, diagnosticReporter, referenceFromIndex);
      logger?.call("Transformed JS interop classes");
    }

    // If we are compiling with a null environment, skip constant resolution
    // and simplification.
    if (environmentDefines != null) {
      void reportError(LocatedMessage message,
          [List<LocatedMessage>? context]) {
        diagnosticReporter.report(message.messageObject, message.charOffset,
            message.length, message.uri);
        if (context != null) {
          for (final m in context) {
            diagnosticReporter.report(
                m.messageObject, m.charOffset, m.length, m.uri);
          }
        }
      }

      final simplifier = ConstConditionalSimplifier(
        dartLibrarySupport,
        constantsBackend,
        component,
        reportError,
        environmentDefines: environmentDefines,
        coreTypes: coreTypes,
        classHierarchy: hierarchy,
        removeAsserts: removeAsserts,
      );
      final evaluator = simplifier.constantEvaluator;
      ConstantResolver(evaluator).transform(component);
      simplifier.run();
    }

    transformMixins.transformLibraries(
        this, coreTypes, hierarchy, libraries, referenceFromIndex);
    logger?.call("Transformed mixin applications");

    List<Library>? transitiveImportingDartFfi = ffiHelper
        .calculateTransitiveImportsOfDartFfiIfUsed(component, libraries);
    if (transitiveImportingDartFfi == null) {
      logger?.call("Skipped ffi transformation");
    } else {
      wasmFfiNativeAddressTrans.transformLibraries(
          component,
          coreTypes,
          hierarchy,
          transitiveImportingDartFfi,
          diagnosticReporter,
          referenceFromIndex);
      wasmFfiNativeTrans.transformLibraries(component, coreTypes, hierarchy,
          transitiveImportingDartFfi, diagnosticReporter, referenceFromIndex);
      transformFfiDefinitions.transformLibraries(
          component,
          coreTypes,
          hierarchy,
          transitiveImportingDartFfi,
          diagnosticReporter,
          referenceFromIndex,
          changedStructureNotifier);
      transformFfiUseSites.transformLibraries(component, coreTypes, hierarchy,
          transitiveImportingDartFfi, diagnosticReporter, referenceFromIndex);
      logger?.call("Transformed ffi annotations");
    }

    wasmTrans.transformLibraries(libraries, coreTypes, hierarchy);

    awaitTrans.transformLibraries(libraries, hierarchy, coreTypes);
  }

  @override
  void performTransformationsOnProcedure(
      CoreTypes coreTypes,
      ClassHierarchy hierarchy,
      Procedure procedure,
      Map<String, String>? environmentDefines,
      {void Function(String msg)? logger}) {
    wasmTrans.transformProcedure(procedure, coreTypes, hierarchy);
  }

  Expression _instantiateInvocation(
      CoreTypes coreTypes, String name, Arguments arguments) {
    if (name.startsWith("set:")) {
      name = name.substring(4);
      Procedure invocationSetter = coreTypes.invocationClass.procedures
          .firstWhere((c) => c.name.text == "setter");
      return StaticInvocation(invocationSetter,
          Arguments([SymbolLiteral(name), arguments.positional.single]));
    } else if (name.startsWith("get:")) {
      name = name.substring(4);
      Procedure invocationGetter = coreTypes.invocationClass.procedures
          .firstWhere((c) => c.name.text == "getter");
      return StaticInvocation(
          invocationGetter, Arguments([SymbolLiteral(name)]));
    } else if (arguments.types.isEmpty) {
      Procedure invocationMethod = coreTypes.invocationClass.procedures
          .firstWhere((c) => c.name.text == "method");
      return StaticInvocation(
          invocationMethod,
          Arguments([
            SymbolLiteral(name),
            ListLiteral(arguments.positional),
            MapLiteral(List<MapLiteralEntry>.from(
                arguments.named.map((NamedExpression arg) {
              return MapLiteralEntry(SymbolLiteral(arg.name), arg.value);
            })), keyType: coreTypes.symbolNonNullableRawType)
              ..isConst = (arguments.named.isEmpty)
          ]));
    } else {
      Procedure invocationGenericMethod = coreTypes.invocationClass.procedures
          .firstWhere((c) => c.name.text == "genericMethod");
      return StaticInvocation(
          invocationGenericMethod,
          Arguments([
            SymbolLiteral(name),
            ListLiteral(arguments.types.map((t) => TypeLiteral(t)).toList()),
            ListLiteral(arguments.positional),
            MapLiteral(List<MapLiteralEntry>.from(
                arguments.named.map((NamedExpression arg) {
              return MapLiteralEntry(SymbolLiteral(arg.name), arg.value);
            })), keyType: coreTypes.symbolNonNullableRawType)
              ..isConst = (arguments.named.isEmpty)
          ]));
    }
  }

  @override
  Expression instantiateInvocation(CoreTypes coreTypes, Expression receiver,
      String name, Arguments arguments, int offset, bool isSuper) {
    return _instantiateInvocation(coreTypes, name, arguments);
  }

  @override
  Expression instantiateNoSuchMethodError(CoreTypes coreTypes,
      Expression receiver, String name, Arguments arguments, int offset,
      {bool isMethod = false,
      bool isGetter = false,
      bool isSetter = false,
      bool isField = false,
      bool isLocalVariable = false,
      bool isDynamic = false,
      bool isSuper = false,
      bool isStatic = false,
      bool isConstructor = false,
      bool isTopLevel = false}) {
    return StaticInvocation(
        coreTypes.noSuchMethodErrorDefaultConstructor,
        Arguments(
            [receiver, _instantiateInvocation(coreTypes, name, arguments)]));
  }

  @override
  bool get supportsSetLiterals => true;

  @override
  int get enabledLateLowerings => LateLowering.all;

  @override
  int get enabledConstructorTearOffLowerings => ConstructorTearOffLowering.all;

  @override
  bool get supportsExplicitGetterCalls => true;

  @override
  bool get supportsLateLoweringSentinel => false;

  @override
  bool get useStaticFieldLowering => false;

  @override
  Class concreteListLiteralClass(CoreTypes coreTypes) {
    return _growableList ??=
        coreTypes.index.getClass('dart:_list', 'GrowableList');
  }

  @override
  Class concreteConstListLiteralClass(CoreTypes coreTypes) {
    return _immutableList ??=
        coreTypes.index.getClass('dart:_list', 'ImmutableList');
  }

  @override
  Class concreteMapLiteralClass(CoreTypes coreTypes) {
    return _wasmDefaultMap ??=
        coreTypes.index.getClass('dart:_compact_hash', 'DefaultMap');
  }

  @override
  Class concreteConstMapLiteralClass(CoreTypes coreTypes) {
    return _wasmImmutableMap ??=
        coreTypes.index.getClass('dart:_compact_hash', '_ConstMap');
  }

  @override
  Class concreteSetLiteralClass(CoreTypes coreTypes) {
    return _wasmDefaultSet ??=
        coreTypes.index.getClass('dart:_compact_hash', 'DefaultSet');
  }

  @override
  Class concreteConstSetLiteralClass(CoreTypes coreTypes) {
    return _wasmImmutableSet ??=
        coreTypes.index.getClass('dart:_compact_hash', '_ConstSet');
  }

  @override
  Class concreteStringLiteralClass(CoreTypes coreTypes, String value) {
    return _jsString ??=
        coreTypes.index.getClass("dart:_string", "JSStringImpl");
  }

  // In dart2wasm we can't assume that `x == "hello"` means `x`'s class is
  // `concreteStringLiteralClass("hello")`, it may also be `JSStringImpl` when
  // it's obtained from a JS call, or `TwoByteString` when it's a substring of a
  // `TwoByteString`.
  @override
  bool get canInferStringClassAfterEqualityComparison => false;

  @override
  Class concreteClosureClass(CoreTypes coreTypes) {
    return _closure ??= coreTypes.index.getClass('dart:core', '_Closure');
  }

  @override
  bool isSupportedPragma(String pragmaName) =>
      pragmaName.startsWith("wasm:") || pragmaName.startsWith("dyn-module:");

  late final Map<RecordShape, Class> recordClasses;

  @override
  Class getRecordImplementationClass(CoreTypes coreTypes,
          int numPositionalFields, List<String> namedFields) =>
      recordClasses[RecordShape(numPositionalFields, namedFields)]!;

  @override
  Class concreteIntLiteralClass(CoreTypes coreTypes, int value) =>
      _boxedInt ??= coreTypes.index.getClass("dart:_boxed_int", "BoxedInt");

  @override
  Class concreteDoubleLiteralClass(CoreTypes coreTypes, double value) =>
      _boxedDouble ??=
          coreTypes.index.getClass("dart:_boxed_double", "BoxedDouble");

  @override
  DartLibrarySupport get dartLibrarySupport => CustomizedDartLibrarySupport(
      unsupported: {if (!enableExperimentalFfi) 'ffi'});
}

class WasmVerification extends Verification {
  const WasmVerification();

  @override
  bool allowNoFileOffset(VerificationStage stage, TreeNode node) {
    if (super.allowNoFileOffset(stage, node)) {
      return true;
    }
    if (stage >= VerificationStage.afterModularTransformations) {
      // Allow synthesized classes, procedures, fields and casts.
      // TODO(askesc): Improve the precision of these exceptions.
      return node is Class ||
          node is Constructor ||
          node is Procedure ||
          node is Field ||
          node is AsExpression;
    }
    return false;
  }
}

final _dartCoreUri = Uri.parse('dart:core');

/// Check that `wasm:import` and `wasm:export` pragmas are only used in `dart:`
/// libraries and in tests, with the exception of
/// `reject_import_export_pragmas` test.
void _checkWasmImportExportPragmas(List<Library> libraries, CoreTypes coreTypes,
    DiagnosticReporter<Message, LocatedMessage> diagnosticReporter) {
  for (Library library in libraries) {
    final importUri = library.importUri;
    if (importUri.isScheme('dart') ||
        (importUri.isScheme('package') &&
            JsInteropChecks.allowedInteropLibrariesInDart2WasmPackages
                .any((pkg) => importUri.pathSegments.first == pkg))) {
      continue;
    }

    for (Member member in library.members) {
      for (Expression annotation in member.annotations) {
        if (annotation is! ConstantExpression) {
          continue;
        }
        final annotationConstant = annotation.constant;
        if (annotationConstant is! InstanceConstant) {
          continue;
        }
        final cls = annotationConstant.classNode;
        if (cls.name == 'pragma' &&
            cls.enclosingLibrary.importUri == _dartCoreUri) {
          final pragmaName = annotationConstant
              .fieldValues[coreTypes.pragmaName.fieldReference];
          if (pragmaName is StringConstant) {
            if (pragmaName.value == 'wasm:import' ||
                pragmaName.value == 'wasm:export') {
              diagnosticReporter.report(
                messageWasmImportOrExportInUserCode,
                annotation.fileOffset,
                0,
                library.fileUri,
              );
            }
          }
        }
      }
    }
  }
}
