// Copyright (c) 2019, 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.6

import 'dart:_internal' show patch;
import "dart:nativewrappers" show NativeFieldWrapperClass1;
import 'dart:typed_data';

@patch
@pragma("vm:entry-point")
class Int32 {}

@patch
@pragma("vm:entry-point")
class Int64 {}

@patch
@pragma("vm:entry-point")
class Float {}

@patch
@pragma("vm:entry-point")
class Double {}

@patch
@pragma("vm:entry-point")
class Void {}

@patch
class WasmModule {
  @patch
  factory WasmModule(Uint8List data) {
    return _NativeWasmModule(data);
  }
}

@patch
class WasmMemory {
  @patch
  factory WasmMemory(int initialPages, [int maxPages]) {
    return _NativeWasmMemory(initialPages, maxPages);
  }
}

@patch
class WasmImports {
  @patch
  factory WasmImports() {
    return _NativeWasmImports();
  }
}

class _NativeWasmModule extends NativeFieldWrapperClass1 implements WasmModule {
  _NativeWasmModule(Uint8List data) {
    _init(data);
  }

  WasmInstance instantiate(covariant _NativeWasmImports imports) {
    return _NativeWasmInstance(this, imports);
  }

  void _init(Uint8List data) native 'Wasm_initModule';
  String describe() native 'Wasm_describeModule';
}

class _NativeWasmImports extends NativeFieldWrapperClass1
    implements WasmImports {
  List<WasmMemory> _memories;
  List<Function> _fns;

  _NativeWasmImports()
      : _memories = [],
        _fns = [] {
    _init();
  }

  void addMemory(String moduleName, String name, WasmMemory memory) {
    _memories.add(memory);
    _addMemory(moduleName, name, memory);
  }

  void addGlobal<T>(String moduleName, String name, num value, bool mutable) {
    _addGlobal(moduleName, name, value, T, mutable);
  }

  void addFunction<T extends Function>(
      String moduleName, String name, Function fn) {
    int id = _fns.length;
    _fns.add(fn);
    _addFunction(moduleName, name, id, T);
  }

  @pragma("vm:entry-point")
  static Function getFunction(_NativeWasmImports imp, int id) {
    return imp._fns[id];
  }

  void _init() native 'Wasm_initImports';
  void _addMemory(String moduleName, String name, WasmMemory memory)
      native 'Wasm_addMemoryImport';
  void _addGlobal(String moduleName, String name, num value, Type type,
      bool mutable) native 'Wasm_addGlobalImport';
  void _addFunction(String moduleName, String name, int id, Type type)
      native 'Wasm_addFunctionImport';
}

class _NativeWasmMemory extends NativeFieldWrapperClass1 implements WasmMemory {
  int _pages;
  Uint8List _buffer;

  _NativeWasmMemory(int initialPages, int maxPages) : _pages = initialPages {
    _buffer = _init(initialPages, maxPages);
  }

  _NativeWasmMemory.fromInstance(_NativeWasmInstance inst) {
    _buffer = _initFromInstance(inst);
    _pages = _getPages();
  }

  int get lengthInPages => _pages;
  int get lengthInBytes => _buffer.lengthInBytes;
  int operator [](int index) => _buffer[index];
  void operator []=(int index, int value) {
    _buffer[index] = value;
  }

  int grow(int deltaPages) {
    int oldPages = _pages;
    _buffer = _grow(deltaPages);
    _pages += deltaPages;
    return oldPages;
  }

  Uint8List _init(int initialPages, int maxPages) native 'Wasm_initMemory';
  Uint8List _grow(int deltaPages) native 'Wasm_growMemory';
  Uint8List _initFromInstance(_NativeWasmInstance inst)
      native 'Wasm_initMemoryFromInstance';
  int _getPages() native 'Wasm_getMemoryPages';
}

class _NativeWasmInstance extends NativeFieldWrapperClass1
    implements WasmInstance {
  _NativeWasmModule _module;
  _NativeWasmImports _imports;

  _NativeWasmInstance(_NativeWasmModule module, _NativeWasmImports imports)
      : _module = module,
        _imports = imports {
    _init(module, imports);
  }

  WasmFunction<T> lookupFunction<T extends Function>(String name) {
    return _NativeWasmFunction<T>(this, name);
  }

  WasmMemory get memory {
    return _NativeWasmMemory.fromInstance(this);
  }

  void _init(_NativeWasmModule module, _NativeWasmImports imports)
      native 'Wasm_initInstance';
}

class _NativeWasmFunction<T extends Function> extends NativeFieldWrapperClass1
    implements WasmFunction<T> {
  _NativeWasmInstance _inst;

  _NativeWasmFunction(_NativeWasmInstance inst, String name) : _inst = inst {
    _init(inst, name, T);
  }

  num call(List<num> args) {
    var arg_copy = List<num>.from(args, growable: false);
    return _call(arg_copy);
  }

  void _init(_NativeWasmInstance inst, String name, Type fnType)
      native 'Wasm_initFunction';
  num _call(List<num> args) native 'Wasm_callFunction';
}
