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

/* <GEN_DOC> */

import 'dart:async';
import 'dart:convert';
import 'dart:ffi';
import 'dart:io';
import 'dart:typed_data';
import 'package:ffi/ffi.dart';
import 'package:path/path.dart' as path;
import 'wasmer_api.dart';

class WasmImportDescriptor {
  int kind;
  String moduleName;
  String name;
  Pointer<WasmerFunctype> funcType;
  WasmImportDescriptor(this.kind, this.moduleName, this.name, this.funcType);

  String toString() {
    var kindName = wasmerExternKindName(kind);
    if (kind == WasmerExternKindFunction) {
      var runtime = WasmRuntime();
      var sig = WasmRuntime.getSignatureString("${moduleName}::${name}",
          runtime.getArgTypes(funcType), runtime.getReturnType(funcType));
      return "$kindName: $sig";
    } else {
      return "$kindName: ${moduleName}::${name}";
    }
  }
}

class WasmExportDescriptor {
  int kind;
  String name;
  Pointer<WasmerFunctype> funcType;
  WasmExportDescriptor(this.kind, this.name, this.funcType);

  String toString() {
    var kindName = wasmerExternKindName(kind);
    if (kind == WasmerExternKindFunction) {
      var runtime = WasmRuntime();
      var sig = WasmRuntime.getSignatureString(
          name, runtime.getArgTypes(funcType), runtime.getReturnType(funcType));
      return "$kindName: $sig";
    } else {
      return "$kindName: ${name}";
    }
  }
}

class _WasmTrapsEntry {
  dynamic exception;
  _WasmTrapsEntry(this.exception);
}

class WasmRuntime {
  static WasmRuntime? _inst;

  DynamicLibrary _lib;
  late Pointer<WasmerEngine> _engine;
  Map<int, _WasmTrapsEntry> traps = {};
/* <RUNTIME_MEMB> */

  factory WasmRuntime() {
    return _inst ??= WasmRuntime._init();
  }

  static String _getLibName() {
    if (Platform.isMacOS) return "libwasmer.dylib";
    if (Platform.isLinux) return "libwasmer.so";
    // TODO(dartbug.com/37882): Support more platforms.
    throw Exception("Wasm not currently supported on this platform");
  }

  static String _getLibDir() {
    // The common case, and how cli_util.dart computes the Dart SDK directory,
    // path.dirname called twice on Platform.resolvedExecutable.
    var commonLibDir = path.join(
        path.absolute(path.dirname(path.dirname(Platform.resolvedExecutable))),
        'bin',
        'third_party',
        'wasmer');
    if (Directory(commonLibDir).existsSync()) {
      return commonLibDir;
    }

    // This is the less common case where the user is in the checked out Dart
    // SDK, and is executing dart via:
    // ./out/ReleaseX64/dart ...
    var checkedOutLibDir = path.join(
        path.absolute(path.dirname(Platform.resolvedExecutable)),
        'dart-sdk',
        'bin',
        'third_party',
        'wasmer');
    if (Directory(checkedOutLibDir).existsSync()) {
      return checkedOutLibDir;
    }

    // If neither returned above, we return the common case:
    return commonLibDir;
  }

  WasmRuntime._init()
      : _lib = DynamicLibrary.open(path.join(_getLibDir(), _getLibName())) {
/* <RUNTIME_LOAD> */

    if (_Dart_InitializeApiDL(NativeApi.initializeApiDLData) != 0) {
      throw Exception("Failed to initialize Dart API");
    }
    _engine = _engine_new();
    _checkNotEqual(_engine, nullptr, "Failed to initialize Wasm engine.");
    _set_finalizer_for_engine(this, _engine);
  }

  Pointer<WasmerStore> newStore(Object owner) {
    Pointer<WasmerStore> store = _checkNotEqual(
        _store_new(_engine), nullptr, "Failed to create Wasm store.");
    _set_finalizer_for_store(owner, store);
    return store;
  }

  Pointer<WasmerModule> compile(
      Object owner, Pointer<WasmerStore> store, Uint8List data) {
    var dataPtr = calloc<Uint8>(data.length);
    for (int i = 0; i < data.length; ++i) {
      dataPtr[i] = data[i];
    }
    var dataVec = calloc<WasmerByteVec>();
    dataVec.ref.data = dataPtr;
    dataVec.ref.length = data.length;

    var modulePtr = _module_new(store, dataVec);

    calloc.free(dataPtr);
    calloc.free(dataVec);

    _checkNotEqual(modulePtr, nullptr, "Wasm module compile failed.");
    _set_finalizer_for_module(owner, modulePtr);
    return modulePtr;
  }

  List<WasmExportDescriptor> exportDescriptors(Pointer<WasmerModule> module) {
    var exportsVec = calloc<WasmerExporttypeVec>();
    _module_exports(module, exportsVec);
    var exps = <WasmExportDescriptor>[];
    for (var i = 0; i < exportsVec.ref.length; ++i) {
      var exp = exportsVec.ref.data[i];
      var extern = _exporttype_type(exp);
      var kind = _externtype_kind(extern);
      var fnType = kind == WasmerExternKindFunction
          ? _externtype_as_functype(extern)
          : nullptr;
      exps.add(WasmExportDescriptor(
          kind, _exporttype_name(exp).ref.toString(), fnType));
    }
    calloc.free(exportsVec);
    return exps;
  }

  List<WasmImportDescriptor> importDescriptors(Pointer<WasmerModule> module) {
    var importsVec = calloc<WasmerImporttypeVec>();
    _module_imports(module, importsVec);
    var imps = <WasmImportDescriptor>[];
    for (var i = 0; i < importsVec.ref.length; ++i) {
      var imp = importsVec.ref.data[i];
      var extern = _importtype_type(imp);
      var kind = _externtype_kind(extern);
      var fnType = kind == WasmerExternKindFunction
          ? _externtype_as_functype(extern)
          : nullptr;
      imps.add(WasmImportDescriptor(
          kind,
          _importtype_module(imp).ref.toString(),
          _importtype_name(imp).ref.toString(),
          fnType));
    }
    calloc.free(importsVec);
    return imps;
  }

  void maybeThrowTrap(Pointer<WasmerTrap> trap, String source) {
    if (trap != nullptr) {
      // There are 2 kinds of trap, and their memory is managed differently.
      // Traps created in the newTrap method below are stored in the traps map
      // with a corresponding exception, and their memory is managed using a
      // finalizer on the _WasmTrapsEntry. Traps can also be created by WASM
      // code, and in that case we delete them in this function.
      var entry = traps[trap.address];
      if (entry != null) {
        traps.remove(entry);
        throw entry.exception;
      } else {
        var trapMessage = calloc<WasmerByteVec>();
        _trap_message(trap, trapMessage);
        var message = "Wasm trap when calling $source: ${trapMessage.ref}";
        _byte_vec_delete(trapMessage);
        calloc.free(trapMessage);
        _trap_delete(trap);
        throw Exception(message);
      }
    }
  }

  Pointer<WasmerInstance> instantiate(Object owner, Pointer<WasmerStore> store,
      Pointer<WasmerModule> module, Pointer<WasmerExternVec> imports) {
    var trap = calloc<Pointer<WasmerTrap>>();
    trap.value = nullptr;
    var inst = _instance_new(store, module, imports, trap);
    maybeThrowTrap(trap.value, "module initialization function");
    calloc.free(trap);
    _checkNotEqual(inst, nullptr, "Wasm module instantiation failed.");
    _set_finalizer_for_instance(owner, inst);
    return inst;
  }

  // Clean up the exports after use, with deleteExports.
  Pointer<WasmerExternVec> exports(Pointer<WasmerInstance> instancePtr) {
    var exports = calloc<WasmerExternVec>();
    _instance_exports(instancePtr, exports);
    return exports;
  }

  void deleteExports(Pointer<WasmerExternVec> exports) {
    _extern_vec_delete(exports);
    calloc.free(exports);
  }

  int externKind(Pointer<WasmerExtern> extern) {
    return _extern_kind(extern);
  }

  Pointer<WasmerFunc> externToFunction(Pointer<WasmerExtern> extern) {
    return _extern_as_func(extern);
  }

  Pointer<WasmerExtern> functionToExtern(Pointer<WasmerFunc> func) {
    return _func_as_extern(func);
  }

  List<int> getArgTypes(Pointer<WasmerFunctype> funcType) {
    var types = <int>[];
    var args = _functype_params(funcType);
    for (var i = 0; i < args.ref.length; ++i) {
      types.add(_valtype_kind(args.ref.data[i]));
    }
    return types;
  }

  int getReturnType(Pointer<WasmerFunctype> funcType) {
    var rets = _functype_results(funcType);
    if (rets.ref.length == 0) {
      return WasmerValKindVoid;
    } else if (rets.ref.length > 1) {
      throw Exception("Multiple return values are not supported");
    }
    return _valtype_kind(rets.ref.data[0]);
  }

  void call(Pointer<WasmerFunc> func, Pointer<WasmerValVec> args,
      Pointer<WasmerValVec> results, String source) {
    maybeThrowTrap(_func_call(func, args, results), source);
  }

  Pointer<WasmerMemory> externToMemory(Pointer<WasmerExtern> extern) {
    return _extern_as_memory(extern);
  }

  Pointer<WasmerExtern> memoryToExtern(Pointer<WasmerMemory> memory) {
    return _memory_as_extern(memory);
  }

  Pointer<WasmerMemory> newMemory(
      Object owner, Pointer<WasmerStore> store, int pages, int? maxPages) {
    var limPtr = calloc<WasmerLimits>();
    limPtr.ref.min = pages;
    limPtr.ref.max = maxPages ?? wasm_limits_max_default;
    var memType = _memorytype_new(limPtr);
    calloc.free(limPtr);
    _checkNotEqual(memType, nullptr, "Failed to create memory type.");
    _set_finalizer_for_memorytype(owner, memType);
    var memory = _checkNotEqual(
        _memory_new(store, memType), nullptr, "Failed to create memory.");
    _set_finalizer_for_memory(owner, memory);
    return memory;
  }

  void growMemory(Pointer<WasmerMemory> memory, int deltaPages) {
    _checkNotEqual(
        _memory_grow(memory, deltaPages), 0, "Failed to grow memory.");
  }

  int memoryLength(Pointer<WasmerMemory> memory) {
    return _memory_size(memory);
  }

  Uint8List memoryView(Pointer<WasmerMemory> memory) {
    return _memory_data(memory).asTypedList(_memory_data_size(memory));
  }

  Pointer<WasmerFunc> newFunc(
      Object owner,
      Pointer<WasmerStore> store,
      Pointer<WasmerFunctype> funcType,
      Pointer func,
      Pointer env,
      Pointer finalizer) {
    var f = _func_new_with_env(
        store, funcType, func.cast(), env.cast(), finalizer.cast());
    _checkNotEqual(f, nullptr, "Failed to create function.");
    _set_finalizer_for_func(owner, f);
    return f;
  }

  Pointer<WasmerTrap> newTrap(Pointer<WasmerStore> store, dynamic exception) {
    var msg = calloc<WasmerByteVec>();
    msg.ref.data = calloc<Uint8>();
    msg.ref.data[0] = 0;
    msg.ref.length = 0;
    var trap = _trap_new(store, msg);
    calloc.free(msg.ref.data);
    calloc.free(msg);
    _checkNotEqual(trap, nullptr, "Failed to create trap.");
    var entry = _WasmTrapsEntry(exception);
    _set_finalizer_for_trap(entry, trap);
    traps[trap.address] = entry;
    return trap;
  }

  Pointer<WasmerWasiConfig> newWasiConfig() {
    var name = calloc<Uint8>();
    name[0] = 0;
    var config = _wasi_config_new(name);
    calloc.free(name);
    return _checkNotEqual(config, nullptr, "Failed to create WASI config.");
  }

  void captureWasiStdout(Pointer<WasmerWasiConfig> config) {
    _wasi_config_inherit_stdout(config);
  }

  void captureWasiStderr(Pointer<WasmerWasiConfig> config) {
    _wasi_config_inherit_stderr(config);
  }

  Pointer<WasmerWasiEnv> newWasiEnv(Pointer<WasmerWasiConfig> config) {
    return _checkNotEqual(
        _wasi_env_new(config), nullptr, "Failed to create WASI environment.");
  }

  void wasiEnvSetMemory(
      Pointer<WasmerWasiEnv> env, Pointer<WasmerMemory> memory) {
    _wasi_env_set_memory(env, memory);
  }

  void getWasiImports(Pointer<WasmerStore> store, Pointer<WasmerModule> mod,
      Pointer<WasmerWasiEnv> env, Pointer<WasmerExternVec> imports) {
    _checkNotEqual(_wasi_get_imports(store, mod, env, imports), 0,
        "Failed to fill WASI imports.");
  }

  Stream<List<int>> getWasiStdoutStream(Pointer<WasmerWasiEnv> env) {
    return Stream.fromIterable(_WasiStreamIterable(env, _wasi_env_read_stdout));
  }

  Stream<List<int>> getWasiStderrStream(Pointer<WasmerWasiEnv> env) {
    return Stream.fromIterable(_WasiStreamIterable(env, _wasi_env_read_stderr));
  }

  String _getLastError() {
    var length = _wasmer_last_error_length();
    var buf = calloc<Uint8>(length);
    _wasmer_last_error_message(buf, length);
    String message = utf8.decode(buf.asTypedList(length));
    calloc.free(buf);
    return message;
  }

  T _checkNotEqual<T>(T x, T y, String errorMessage) {
    if (x == y) {
      throw Exception("$errorMessage\n${_getLastError()}");
    }
    return x;
  }

  static String getSignatureString(
      String name, List<int> argTypes, int returnType) {
    return "${wasmerValKindName(returnType)} $name" +
        "(${argTypes.map(wasmerValKindName).join(", ")})";
  }
}

class _WasiStreamIterator implements Iterator<List<int>> {
  static final int _bufferLength = 1024;
  Pointer<WasmerWasiEnv> _env;
  Function _reader;
  Pointer<Uint8> _buf = calloc<Uint8>(_bufferLength);
  int _length = 0;
  _WasiStreamIterator(this._env, this._reader) {}

  bool moveNext() {
    _length = _reader(_env, _buf, _bufferLength);
    return true;
  }

  List<int> get current => _buf.asTypedList(_length);
}

class _WasiStreamIterable extends Iterable<List<int>> {
  Pointer<WasmerWasiEnv> _env;
  Function _reader;
  _WasiStreamIterable(this._env, this._reader) {}
  @override
  Iterator<List<int>> get iterator => _WasiStreamIterator(_env, _reader);
}
