// 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 'runtime.dart';
import 'wasmer_api.dart';
import 'dart:ffi';
import 'package:ffi/ffi.dart';

/// WasmFunction is a callable function from a WasmInstance.
class WasmFunction {
  String _name;
  Pointer<WasmerFunc> _func;
  List<int> _argTypes;
  int _returnType;
  Pointer<WasmerValVec> _args = calloc<WasmerValVec>();
  Pointer<WasmerValVec> _results = calloc<WasmerValVec>();

  WasmFunction(this._name, this._func, this._argTypes, this._returnType) {
    _args.ref.length = _argTypes.length;
    _args.ref.data =
        _argTypes.length == 0 ? nullptr : calloc<WasmerVal>(_argTypes.length);
    _results.ref.length = _returnType == WasmerValKindVoid ? 0 : 1;
    _results.ref.data =
        _returnType == WasmerValKindVoid ? nullptr : calloc<WasmerVal>();
    for (var i = 0; i < _argTypes.length; ++i) {
      _args.ref.data[i].kind = _argTypes[i];
    }
  }

  String toString() {
    return WasmRuntime.getSignatureString(_name, _argTypes, _returnType);
  }

  bool _fillArg(dynamic arg, int i) {
    switch (_argTypes[i]) {
      case WasmerValKindI32:
        if (arg is! int) return false;
        _args.ref.data[i].i32 = arg;
        return true;
      case WasmerValKindI64:
        if (arg is! int) return false;
        _args.ref.data[i].i64 = arg;
        return true;
      case WasmerValKindF32:
        if (arg is! num) return false;
        _args.ref.data[i].f32 = arg;
        return true;
      case WasmerValKindF64:
        if (arg is! num) return false;
        _args.ref.data[i].f64 = arg;
        return true;
    }
    return false;
  }

  dynamic apply(List<dynamic> args) {
    if (args.length != _argTypes.length) {
      throw ArgumentError("Wrong number arguments for WASM function: $this");
    }
    for (var i = 0; i < args.length; ++i) {
      if (!_fillArg(args[i], i)) {
        throw ArgumentError("Bad argument type for WASM function: $this");
      }
    }
    WasmRuntime().call(_func, _args, _results, toString());

    if (_returnType == WasmerValKindVoid) {
      return null;
    }
    var result = _results.ref.data[0];
    assert(_returnType == result.kind);
    switch (_returnType) {
      case WasmerValKindI32:
        return result.i32;
      case WasmerValKindI64:
        return result.i64;
      case WasmerValKindF32:
        return result.f32;
      case WasmerValKindF64:
        return result.f64;
    }
  }

  dynamic noSuchMethod(Invocation invocation) {
    if (invocation.memberName == #call) {
      return apply(invocation.positionalArguments);
    }
    return super.noSuchMethod(invocation);
  }
}
