// 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:kernel/ast.dart';
import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
import 'package:kernel/core_types.dart';
import 'package:kernel/library_index.dart' show LibraryIndex;
import 'package:kernel/reference_from_index.dart' show ReferenceFromIndex;
import 'package:kernel/target/targets.dart' show DiagnosticReporter;
import 'package:vm/modular/transformations/ffi/abi.dart' show Abi;
import 'package:vm/modular/transformations/ffi/common.dart' show NativeType;
import 'package:vm/modular/transformations/ffi/native.dart'
    show FfiNativeTransformer;

import 'abi.dart' show kWasmAbiEnumIndex;

/// Transform `@Native`-annotated functions to convert Dart arguments to
/// Wasm arguments expected by the FFI functions, and convert the Wasm function
/// return value to the Dart value.
///
/// Add a new `external` procedure for the Wasm import.
///
/// Example:
///
///     @Native<Int8 Function(Int8, Int8)>(symbol: "addInt8")
///     external int addInt8(int a, int b);
///
/// Converted to:
///
///     external static wasm::WasmI32 addInt8_$import(wasm::WasmI32 a, wasm::WasmI32 b);
///
///     static int addInt8(int a, int b) =>
///       addInt8_$import(WasmI32::int8FromInt(a), WasmI32::int8FromInt(b)).toIntSigned();
///
void transformLibraries(
    Component component,
    CoreTypes coreTypes,
    ClassHierarchy hierarchy,
    List<Library> libraries,
    DiagnosticReporter diagnosticReporter,
    ReferenceFromIndex? referenceFromIndex) {
  final index = LibraryIndex(component, [
    'dart:core',
    'dart:ffi',
    'dart:_internal',
    'dart:typed_data',
    'dart:nativewrappers',
    'dart:_wasm',
    'dart:isolate',
  ]);
  final transformer = WasmFfiNativeTransformer(
      index, coreTypes, hierarchy, diagnosticReporter, referenceFromIndex);
  libraries.forEach(transformer.visitLibrary);
}

class WasmFfiNativeTransformer extends FfiNativeTransformer {
  final Class wasmI32Class;
  final Class wasmI64Class;
  final Class wasmF32Class;
  final Class wasmF64Class;
  final Class wasmEqRefClass;
  final Procedure wasmI32FromInt;
  final Procedure wasmI32Int8FromInt;
  final Procedure wasmI32Uint8FromInt;
  final Procedure wasmI32Int16FromInt;
  final Procedure wasmI32Uint16FromInt;
  final Procedure wasmI32FromBool;
  final Procedure wasmI32ToIntSigned;
  final Procedure wasmI32ToIntUnsigned;
  final Procedure wasmI32ToBool;
  final Procedure wasmI64FromInt;
  final Procedure wasmI64ToInt;
  final Procedure wasmF32FromDouble;
  final Procedure wasmF32ToDouble;
  final Procedure wasmF64FromDouble;
  final Procedure wasmF64ToDouble;
  final Procedure pointerFromAddressI32;
  final Field pointerAddressField;

  WasmFfiNativeTransformer(super.index, super.coreTypes, super.hierarchy,
      super.diagnosticReporter, super.referenceFromIndex)
      : wasmI32Class = index.getClass('dart:_wasm', 'WasmI32'),
        wasmI64Class = index.getClass('dart:_wasm', 'WasmI64'),
        wasmF32Class = index.getClass('dart:_wasm', 'WasmF32'),
        wasmF64Class = index.getClass('dart:_wasm', 'WasmF64'),
        wasmEqRefClass = index.getClass('dart:_wasm', 'WasmEqRef'),
        wasmI32FromInt = index.getProcedure('dart:_wasm', 'WasmI32', 'fromInt'),
        wasmI32Int8FromInt =
            index.getProcedure('dart:_wasm', 'WasmI32', 'int8FromInt'),
        wasmI32Uint8FromInt =
            index.getProcedure('dart:_wasm', 'WasmI32', 'uint8FromInt'),
        wasmI32Int16FromInt =
            index.getProcedure('dart:_wasm', 'WasmI32', 'int16FromInt'),
        wasmI32Uint16FromInt =
            index.getProcedure('dart:_wasm', 'WasmI32', 'uint16FromInt'),
        wasmI32FromBool =
            index.getProcedure('dart:_wasm', 'WasmI32', 'fromBool'),
        wasmI32ToIntSigned =
            index.getProcedure('dart:_wasm', 'WasmI32', 'toIntSigned'),
        wasmI32ToIntUnsigned =
            index.getProcedure('dart:_wasm', 'WasmI32', 'toIntUnsigned'),
        wasmI32ToBool = index.getProcedure('dart:_wasm', 'WasmI32', 'toBool'),
        wasmI64ToInt = index.getProcedure('dart:_wasm', 'WasmI64', 'toInt'),
        wasmI64FromInt = index.getProcedure('dart:_wasm', 'WasmI64', 'fromInt'),
        wasmF32FromDouble =
            index.getProcedure('dart:_wasm', 'WasmF32', 'fromDouble'),
        wasmF32ToDouble =
            index.getProcedure('dart:_wasm', 'WasmF32', 'toDouble'),
        wasmF64FromDouble =
            index.getProcedure('dart:_wasm', 'WasmF64', 'fromDouble'),
        wasmF64ToDouble =
            index.getProcedure('dart:_wasm', 'WasmF64', 'toDouble'),
        pointerFromAddressI32 =
            index.getProcedure('dart:ffi', 'Pointer', '_fromAddressI32'),
        pointerAddressField = index.getField('dart:ffi', 'Pointer', '_address');

  @override
  visitProcedure(Procedure node) {
    // Only transform functions that are external and have Native annotation:
    //   @Native<Double Function(Double)>(symbol: 'Math_sqrt')
    //   external double _square_root(double x);
    final nativeAnnotation = tryGetNativeAnnotationOrWarnOnDuplicates(node);
    if (nativeAnnotation == null) {
      return node;
    }
    final annotationOffset = nativeAnnotation.fileOffset;
    final ffiConstant = nativeAnnotation.constant as InstanceConstant;
    final ffiFunctionType = ffiConstant.typeArguments.first as FunctionType;
    final isLeafField =
        ffiConstant.fieldValues[nativeIsLeafField.fieldReference];
    final isLeaf = (isLeafField as BoolConstant).value;
    final assetField = ffiConstant.fieldValues[nativeAssetField.fieldReference];
    final assetName = (assetField is StringConstant)
        ? assetField
        : (currentAsset ?? StringConstant("ffi"));
    final nameField = ffiConstant.fieldValues[nativeSymbolField.fieldReference];
    final functionName = (nameField is StringConstant)
        ? nameField
        : StringConstant(node.name.text);
    final nativeFunctionName =
        StringConstant("${assetName.value}.${functionName.value}");

    // Original function should be external and without body
    assert(node.isExternal == true);
    assert(node.function.body == null);

    final dartFunctionType =
        node.function.computeThisFunctionType(Nullability.nonNullable);

    final wrappedDartFunctionType = checkFfiType(
        node, dartFunctionType, ffiFunctionType, isLeaf, annotationOffset);

    if (wrappedDartFunctionType == null) {
      // It's OK to continue because the diagnostics issued will cause
      // compilation to fail. By continuing, we can report more diagnostics
      // before compilation ends.
      return node;
    }

    // Create a new extern static procedure for the import. The original
    // function will be calling this one with arguments converted to right Wasm
    // types, and it will convert the return value to the right Dart type.
    final wasmImportName = Name('${node.name.text}_\$import', currentLibrary);
    final wasmImportPragma =
        ConstantExpression(InstanceConstant(pragmaClass.reference, [], {
      pragmaName.fieldReference: StringConstant("wasm:import"),
      pragmaOptions.fieldReference: nativeFunctionName,
    }));

    // For the imported function arguments, use names in the Dart function but
    // types in the FFI declaration
    final List<VariableDeclaration> wasmImportProcedureArgs = [];
    for (int i = 0; i < ffiFunctionType.positionalParameters.length; i += 1) {
      final argWasmType =
          _convertFfiTypeToWasmType(ffiFunctionType.positionalParameters[i]);
      if (argWasmType != null) {
        wasmImportProcedureArgs.add(VariableDeclaration(
          node.function.positionalParameters[i].name!,
          type: argWasmType,
          isSynthesized: true,
        ));
      }
    }

    final retWasmType = _convertFfiTypeToWasmType(ffiFunctionType.returnType);
    final retWasmType_ = retWasmType ?? VoidType();

    final wasmImportProcedure = Procedure(
        wasmImportName,
        ProcedureKind.Method,
        FunctionNode(null,
            positionalParameters: wasmImportProcedureArgs,
            returnType: retWasmType_),
        fileUri: node.fileUri,
        isExternal: true,
        isStatic: true,
        isSynthetic: true)
      ..fileOffset = node.fileOffset;
    wasmImportProcedure.addAnnotation(wasmImportPragma);
    currentLibrary.addProcedure(wasmImportProcedure);

    // Update the original procedure to call the Wasm import, converting
    // arguments and return value
    node.isExternal = false;
    node.annotations.remove(nativeAnnotation);

    // Convert arguments
    assert(ffiFunctionType.positionalParameters.length ==
        node.function.positionalParameters.length);

    final ffiCallArgs = <Expression>[];

    for (int i = 0; i < node.function.positionalParameters.length; i += 1) {
      final ffiArgumentType = ffiFunctionType.positionalParameters[i];

      final ffiValue = _dartValueToFfiValue(
          ffiArgumentType, VariableGet(node.function.positionalParameters[i]));

      if (ffiValue != null) {
        ffiCallArgs.add(ffiValue);
      }
    }

    // Convert return value
    node.function.body = ReturnStatement(_ffiValueToDartValue(
        ffiFunctionType.returnType,
        StaticInvocation(wasmImportProcedure, Arguments(ffiCallArgs))));

    return node;
  }

  /// Converts a Dart value to the corresponding Wasm FFI value according to
  /// emscripten ABI.
  ///
  /// For example, converts a Dart `int` for an `Uint8` native type to Wasm I32
  /// and masks high bits.
  ///
  /// Unboxes `Pointer` values as `i32`.
  ///
  /// Returns `null` for [Void] values.
  Expression? _dartValueToFfiValue(DartType ffiType, Expression expr) {
    final InterfaceType abiType_ =
        _getFixedWidthIntegerFromAbiSpecificInteger(ffiType as InterfaceType);
    final NativeType abiTypeNativeType = getType(abiType_.classNode)!;

    return switch (abiTypeNativeType) {
      NativeType.kInt8 =>
        StaticInvocation(wasmI32Int8FromInt, Arguments([expr])),
      NativeType.kUint8 =>
        StaticInvocation(wasmI32Uint8FromInt, Arguments([expr])),
      NativeType.kInt16 =>
        StaticInvocation(wasmI32Int16FromInt, Arguments([expr])),
      NativeType.kUint16 =>
        StaticInvocation(wasmI32Uint16FromInt, Arguments([expr])),
      NativeType.kInt32 ||
      NativeType.kUint32 =>
        StaticInvocation(wasmI32FromInt, Arguments([expr])),
      NativeType.kInt64 ||
      NativeType.kUint64 =>
        StaticInvocation(wasmI64FromInt, Arguments([expr])),
      NativeType.kFloat =>
        StaticInvocation(wasmF32FromDouble, Arguments([expr])),
      NativeType.kDouble =>
        StaticInvocation(wasmF64FromDouble, Arguments([expr])),
      NativeType.kPointer => InstanceGet(
          InstanceAccessKind.Instance,
          expr,
          pointerAddressField.name,
          interfaceTarget: pointerAddressField,
          resultType: InterfaceType(wasmI32Class, Nullability.nonNullable),
        ),
      NativeType.kBool => StaticInvocation(wasmI32FromBool, Arguments([expr])),
      NativeType.kVoid => null,
      _ => throw '_dartValueToFfiValue: $abiTypeNativeType cannot be converted'
    };
  }

  /// Converts a Wasm FFI value to the corresponding Dart value according to
  /// emscripten ABI.
  ///
  /// For example, converts an `Bool` native type to Dart bool by checking the
  /// Wasm I32 value for the bool: 0 means `false`, non-0 means `true`.
  Expression _ffiValueToDartValue(DartType ffiType, Expression expr) {
    final InterfaceType ffiType_ =
        _getFixedWidthIntegerFromAbiSpecificInteger(ffiType as InterfaceType);
    final NativeType nativeType = getType(ffiType_.classNode)!;

    Expression instanceInvocation(Procedure converter, Expression receiver) =>
        InstanceInvocation(
          InstanceAccessKind.Instance,
          receiver,
          converter.name,
          Arguments([]),
          interfaceTarget: converter,
          functionType: converter.getterType as FunctionType,
        );

    switch (nativeType) {
      case NativeType.kInt8:
      case NativeType.kInt16:
      case NativeType.kInt32:
        return instanceInvocation(wasmI32ToIntSigned, expr);

      case NativeType.kUint8:
      case NativeType.kUint16:
      case NativeType.kUint32:
        return instanceInvocation(wasmI32ToIntUnsigned, expr);

      case NativeType.kPointer:
        assert(ffiType_.classNode == pointerClass);
        assert(ffiType_.typeArguments.length == 1);
        return StaticInvocation(pointerFromAddressI32,
            Arguments([expr], types: ffiType_.typeArguments));

      case NativeType.kVoid:
        return expr;

      case NativeType.kUint64:
      case NativeType.kInt64:
        return instanceInvocation(wasmI64ToInt, expr);

      case NativeType.kFloat:
        return instanceInvocation(wasmF32ToDouble, expr);

      case NativeType.kDouble:
        return instanceInvocation(wasmF64ToDouble, expr);

      case NativeType.kBool:
        return instanceInvocation(wasmI32ToBool, expr);

      case NativeType.kHandle:
      case NativeType.kNativeDouble:
      case NativeType.kNativeFunction:
      case NativeType.kNativeInteger:
      case NativeType.kNativeType:
      case NativeType.kOpaque:
      case NativeType.kStruct:
        throw '_ffiValueToDartValue: $nativeType cannot be converted';
    }
  }

  InterfaceType _getFixedWidthIntegerFromAbiSpecificInteger(
      InterfaceType ffiType) {
    final MapConstant? abiIntegerMapping =
        getAbiSpecificIntegerMappingAnnotation(ffiType.classNode);
    if (abiIntegerMapping == null) {
      // This isn't an ABI specific integer. Just return the type itself
      return ffiType;
    }
    final Abi wasmAbi = Abi.values[kWasmAbiEnumIndex];
    final entry = abiIntegerMapping.entries
        .firstWhere((e) => constantAbis[e.key] == wasmAbi);
    return (entry.value as InstanceConstant)
        .classNode
        .getThisType(coreTypes, Nullability.nonNullable);
  }

  /// Converts an FFI type like `InterfaceType(Int8)` to the corresponding Wasm
  /// type (`InterfaceType(WasmI32)`) according to emscripten Wasm ABI.
  ///
  /// Returns `null` for [Void]. Other types are converted to their
  /// [InterfaceType]s.
  DartType? _convertFfiTypeToWasmType(DartType ffiType) {
    if (ffiType is! InterfaceType) {
      throw 'Native type is not an interface type: $ffiType';
    }
    ffiType = _getFixedWidthIntegerFromAbiSpecificInteger(ffiType);
    final NativeType nativeType_ = getType(ffiType.classNode)!;

    switch (nativeType_) {
      case NativeType.kInt8:
      case NativeType.kUint8:
      case NativeType.kInt16:
      case NativeType.kUint16:
      case NativeType.kInt32:
      case NativeType.kUint32:
      case NativeType.kBool:
      case NativeType.kPointer:
        return InterfaceType(wasmI32Class, Nullability.nonNullable);

      case NativeType.kInt64:
      case NativeType.kUint64:
        return InterfaceType(wasmI64Class, Nullability.nonNullable);

      case NativeType.kFloat:
        return InterfaceType(wasmF32Class, Nullability.nonNullable);

      case NativeType.kDouble:
        return InterfaceType(wasmF64Class, Nullability.nonNullable);

      case NativeType.kStruct:
        return ffiType;

      case NativeType.kVoid:
        return null;

      case NativeType.kHandle:
      case NativeType.kNativeDouble:
      case NativeType.kNativeFunction:
      case NativeType.kNativeInteger:
      case NativeType.kNativeType:
      case NativeType.kOpaque:
        throw '_convertFfiTypeToWasmType: $nativeType_ cannot be converted';
    }
  }
}
