// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef LIB_TONIC_DART_ARGS_H_
#define LIB_TONIC_DART_ARGS_H_

#include <iostream>
#include <sstream>
#include <type_traits>
#include <utility>

#include "third_party/dart/runtime/include/dart_api.h"
#include "tonic/converter/dart_converter.h"
#include "tonic/dart_wrappable.h"

namespace tonic {

class DartArgIterator {
 public:
  explicit DartArgIterator(Dart_NativeArguments args, int start_index = 1)
      : args_(args), index_(start_index), had_exception_(false) {}

  template <typename T>
  T GetNext() {
    if (had_exception_)
      return T();
    Dart_Handle exception = nullptr;
    T arg = DartConverter<T>::FromArguments(args_, index_++, exception);
    if (exception) {
      had_exception_ = true;
      Dart_ThrowException(exception);
    }
    return arg;
  }

  bool had_exception() const { return had_exception_; }

  Dart_NativeArguments args() const { return args_; }

 private:
  Dart_NativeArguments args_;
  int index_;
  bool had_exception_;

  TONIC_DISALLOW_COPY_AND_ASSIGN(DartArgIterator);
};

// Classes for generating and storing an argument pack of integer indices
// (based on well-known "indices trick", see: http://goo.gl/bKKojn):
template <size_t... indices>
struct IndicesHolder {};

template <size_t requested_index, size_t... indices>
struct IndicesGenerator {
  using type = typename IndicesGenerator<requested_index - 1,
                                         requested_index - 1,
                                         indices...>::type;
};

template <size_t... indices>
struct IndicesGenerator<0, indices...> {
  using type = IndicesHolder<indices...>;
};

template <typename T>
class IndicesForSignature {};

template <typename ResultType, typename... ArgTypes>
struct IndicesForSignature<ResultType (*)(ArgTypes...)> {
  static const size_t count = sizeof...(ArgTypes);
  using type = typename IndicesGenerator<count>::type;
};

template <typename C, typename ResultType, typename... ArgTypes>
struct IndicesForSignature<ResultType (C::*)(ArgTypes...)> {
  static const size_t count = sizeof...(ArgTypes);
  using type = typename IndicesGenerator<count>::type;
};

template <typename C, typename ResultType, typename... ArgTypes>
struct IndicesForSignature<ResultType (C::*)(ArgTypes...) const> {
  static const size_t count = sizeof...(ArgTypes);
  using type = typename IndicesGenerator<count>::type;
};

template <size_t index, typename ArgType>
struct DartArgHolder {
  using ValueType = typename std::remove_const<
      typename std::remove_reference<ArgType>::type>::type;

  ValueType value;

  explicit DartArgHolder(DartArgIterator* it)
      : value(it->GetNext<ValueType>()) {}
};

template <typename T>
void DartReturn(T result, Dart_NativeArguments args) {
  DartConverter<T>::SetReturnValue(args, std::move(result));
}

template <typename IndicesType, typename T>
class DartDispatcher {};

// Match functions on the form:
// `void f(ArgTypes...)`
template <size_t... indices, typename... ArgTypes>
struct DartDispatcher<IndicesHolder<indices...>, void (*)(ArgTypes...)>
    : public DartArgHolder<indices, ArgTypes>... {
  using FunctionPtr = void (*)(ArgTypes...);

  DartArgIterator* it_;

  explicit DartDispatcher(DartArgIterator* it)
      : DartArgHolder<indices, ArgTypes>(it)..., it_(it) {}

  void Dispatch(FunctionPtr func) {
    (*func)(DartArgHolder<indices, ArgTypes>::value...);
  }
};

// Match functions on the form:
// `ResultType f(ArgTypes...)`
template <size_t... indices, typename ResultType, typename... ArgTypes>
struct DartDispatcher<IndicesHolder<indices...>, ResultType (*)(ArgTypes...)>
    : public DartArgHolder<indices, ArgTypes>... {
  using FunctionPtr = ResultType (*)(ArgTypes...);
  using CtorResultType = ResultType;

  DartArgIterator* it_;

  explicit DartDispatcher(DartArgIterator* it)
      : DartArgHolder<indices, ArgTypes>(it)..., it_(it) {}

  void Dispatch(FunctionPtr func) {
    DartReturn((*func)(DartArgHolder<indices, ArgTypes>::value...),
               it_->args());
  }

  ResultType DispatchCtor(FunctionPtr func) {
    return (*func)(DartArgHolder<indices, ArgTypes>::value...);
  }
};

// Match instance methods on the form:
// `void C::m(ArgTypes...)`
template <size_t... indices, typename C, typename... ArgTypes>
struct DartDispatcher<IndicesHolder<indices...>, void (C::*)(ArgTypes...)>
    : public DartArgHolder<indices, ArgTypes>... {
  using FunctionPtr = void (C::*)(ArgTypes...);

  DartArgIterator* it_;

  explicit DartDispatcher(DartArgIterator* it)
      : DartArgHolder<indices, ArgTypes>(it)..., it_(it) {}

  void Dispatch(FunctionPtr func) {
    (GetReceiver<C>(it_->args())->*func)(
        DartArgHolder<indices, ArgTypes>::value...);
  }
};

// Match instance methods on the form:
// `ReturnType (C::m)(ArgTypes...) const`
template <size_t... indices,
          typename C,
          typename ReturnType,
          typename... ArgTypes>
struct DartDispatcher<IndicesHolder<indices...>,
                      ReturnType (C::*)(ArgTypes...) const>
    : public DartArgHolder<indices, ArgTypes>... {
  using FunctionPtr = ReturnType (C::*)(ArgTypes...) const;

  DartArgIterator* it_;

  explicit DartDispatcher(DartArgIterator* it)
      : DartArgHolder<indices, ArgTypes>(it)..., it_(it) {}

  void Dispatch(FunctionPtr func) {
    DartReturn((GetReceiver<C>(it_->args())->*func)(
                   DartArgHolder<indices, ArgTypes>::value...),
               it_->args());
  }
};

// Match instance methods on the form:
// `ReturnType (C::m)(ArgTypes...)`
template <size_t... indices,
          typename C,
          typename ResultType,
          typename... ArgTypes>
struct DartDispatcher<IndicesHolder<indices...>, ResultType (C::*)(ArgTypes...)>
    : public DartArgHolder<indices, ArgTypes>... {
  using FunctionPtr = ResultType (C::*)(ArgTypes...);

  DartArgIterator* it_;

  explicit DartDispatcher(DartArgIterator* it)
      : DartArgHolder<indices, ArgTypes>(it)..., it_(it) {}

  void Dispatch(FunctionPtr func) {
    DartReturn((GetReceiver<C>(it_->args())->*func)(
                   DartArgHolder<indices, ArgTypes>::value...),
               it_->args());
  }
};

template <typename Sig>
void DartCall(Sig func, Dart_NativeArguments args) {
  DartArgIterator it(args);
  using Indices = typename IndicesForSignature<Sig>::type;
  DartDispatcher<Indices, Sig> decoder(&it);
  if (it.had_exception())
    return;
  decoder.Dispatch(func);
}

template <typename Sig>
void DartCallStatic(Sig func, Dart_NativeArguments args) {
  DartArgIterator it(args, 0);
  using Indices = typename IndicesForSignature<Sig>::type;
  DartDispatcher<Indices, Sig> decoder(&it);
  if (it.had_exception())
    return;
  decoder.Dispatch(func);
}

template <typename Sig>
void DartCallConstructor(Sig func, Dart_NativeArguments args) {
  DartArgIterator it(args);
  using Indices = typename IndicesForSignature<Sig>::type;
  using Wrappable = typename DartDispatcher<Indices, Sig>::CtorResultType;
  Wrappable wrappable;
  {
    DartDispatcher<Indices, Sig> decoder(&it);
    if (it.had_exception())
      return;
    wrappable = decoder.DispatchCtor(func);
  }

  Dart_Handle wrapper = Dart_GetNativeArgument(args, 0);
  TONIC_CHECK(!CheckAndHandleError(wrapper));

  intptr_t native_fields[DartWrappable::kNumberOfNativeFields];
  TONIC_CHECK(!CheckAndHandleError(Dart_GetNativeFieldsOfArgument(
      args, 0, DartWrappable::kNumberOfNativeFields, native_fields)));
  TONIC_CHECK(!native_fields[DartWrappable::kPeerIndex]);

  wrappable->AssociateWithDartWrapper(wrapper);
}

// Templates to automatically setup static entry points for FFI Native
// functions.
// Entry points for instance methods take the instance as the first argument and
// call the given method with the remaining arguments.
// Arguments will automatically get converted to and from their FFI
// representations with the DartConverter templates.
//
// @tparam C The type of the receiver. Or `void` if there is no receiver.
// @tparam Signature The signature of the function being dispatched to.
// @tparam function The function pointer being dispatched to.
template <typename C, typename Signature, Signature function>
struct FfiDispatcher;

// Concatenate the FFI representation of each argument to the stream,
// serialising them into a comma separated list.
// Example: "Handle, Bool, Uint64"
template <typename Arg, typename... Args>
void WriteFfiArguments(std::ostringstream* stream) {
  *stream << tonic::DartConverter<typename std::remove_const<
      typename std::remove_reference<Arg>::type>::type>::GetFfiRepresentation();
  if constexpr (sizeof...(Args) > 0) {
    *stream << ", ";
    WriteFfiArguments<Args...>(stream);
  }
}

// Concatenate the Dart representation of each argument to the stream,
// serialising them into a comma separated list.
// Example: "Object, bool, int"
template <typename Arg, typename... Args>
void WriteDartArguments(std::ostringstream* stream) {
  *stream << tonic::DartConverter<
      typename std::remove_const<typename std::remove_reference<Arg>::type>::
          type>::GetDartRepresentation();
  if constexpr (sizeof...(Args) > 0) {
    *stream << ", ";
    WriteDartArguments<Args...>(stream);
  }
}

// Logical 'and' together whether each argument is allowed in a leaf call.
template <typename Arg, typename... Args>
bool AllowedInLeafCall() {
  bool result = tonic::DartConverter<typename std::remove_const<
      typename std::remove_reference<Arg>::type>::type>::AllowedInLeafCall();
  if constexpr (sizeof...(Args) > 0) {
    result &= AllowedInLeafCall<Args...>();
  }
  return result;
}

// Match `Return function(...)`.
template <typename Return, typename... Args, Return (*function)(Args...)>
struct FfiDispatcher<void, Return (*)(Args...), function> {
  using FfiReturn = typename DartConverter<Return>::FfiType;
  static const size_t n_args = sizeof...(Args);

  // Static C entry-point with Dart FFI signature.
  static FfiReturn Call(
      typename DartConverter<typename std::remove_const<
          typename std::remove_reference<Args>::type>::type>::FfiType... args) {
    // Call C++ function, forwarding converted native arguments.
    return DartConverter<Return>::ToFfi(function(
        DartConverter<typename std::remove_const<typename std::remove_reference<
            Args>::type>::type>::FromFfi(args)...));
  }

  static bool AllowedAsLeafCall() {
    if constexpr (sizeof...(Args) > 0) {
      return AllowedInLeafCall<Return>() && AllowedInLeafCall<Args...>();
    }
    return AllowedInLeafCall<Return>();
  }

  static const char* GetReturnFfiRepresentation() {
    return tonic::DartConverter<Return>::GetFfiRepresentation();
  }

  static const char* GetReturnDartRepresentation() {
    return tonic::DartConverter<Return>::GetDartRepresentation();
  }

  static void WriteFfiArguments(std::ostringstream* stream) {
    if constexpr (sizeof...(Args) > 0) {
      ::tonic::WriteFfiArguments<Args...>(stream);
    }
  }

  static void WriteDartArguments(std::ostringstream* stream) {
    if constexpr (sizeof...(Args) > 0) {
      ::tonic::WriteDartArguments<Args...>(stream);
    }
  }
};

// Match `Return C::method(...)`.
template <typename C,
          typename Return,
          typename... Args,
          Return (C::*method)(Args...)>
struct FfiDispatcher<C, Return (C::*)(Args...), method> {
  using FfiReturn = typename DartConverter<Return>::FfiType;
  static const size_t n_args = sizeof...(Args);

  // Static C entry-point with Dart FFI signature.
  static FfiReturn Call(
      C* receiver,
      typename DartConverter<typename std::remove_const<
          typename std::remove_reference<Args>::type>::type>::FfiType... args) {
    // Call C++ method on receiver, forwarding converted native arguments.
    return DartConverter<Return>::ToFfi((receiver->*method)(
        DartConverter<typename std::remove_const<typename std::remove_reference<
            Args>::type>::type>::FromFfi(args)...));
  }

  static bool AllowedAsLeafCall() {
    if constexpr (sizeof...(Args) > 0) {
      return AllowedInLeafCall<Return>() && AllowedInLeafCall<Args...>();
    }
    return AllowedInLeafCall<Return>();
  }

  static const char* GetReturnFfiRepresentation() {
    return tonic::DartConverter<Return>::GetFfiRepresentation();
  }

  static const char* GetReturnDartRepresentation() {
    return tonic::DartConverter<Return>::GetDartRepresentation();
  }

  static void WriteFfiArguments(std::ostringstream* stream) {
    *stream << tonic::DartConverter<C*>::GetFfiRepresentation();
    if constexpr (sizeof...(Args) > 0) {
      *stream << ", ";
      ::tonic::WriteFfiArguments<Args...>(stream);
    }
  }

  static void WriteDartArguments(std::ostringstream* stream) {
    *stream << tonic::DartConverter<C*>::GetDartRepresentation();
    if constexpr (sizeof...(Args) > 0) {
      *stream << ", ";
      ::tonic::WriteDartArguments<Args...>(stream);
    }
  }
};

// Match `Return C::method(...) const`.
template <typename C,
          typename Return,
          typename... Args,
          Return (C::*method)(Args...) const>
struct FfiDispatcher<C, Return (C::*)(Args...) const, method> {
  using FfiReturn = typename DartConverter<Return>::FfiType;
  static const size_t n_args = sizeof...(Args);

  // Static C entry-point with Dart FFI signature.
  static FfiReturn Call(
      C* receiver,
      typename DartConverter<typename std::remove_const<
          typename std::remove_reference<Args>::type>::type>::FfiType... args) {
    // Call C++ method on receiver, forwarding converted native arguments.
    return DartConverter<Return>::ToFfi((receiver->*method)(
        DartConverter<typename std::remove_const<typename std::remove_reference<
            Args>::type>::type>::FromFfi(args)...));
  }

  static bool AllowedAsLeafCall() {
    if constexpr (sizeof...(Args) > 0) {
      return AllowedInLeafCall<Return>() && AllowedInLeafCall<Args...>();
    }
    return AllowedInLeafCall<Return>();
  }

  static const char* GetReturnFfiRepresentation() {
    return tonic::DartConverter<Return>::GetFfiRepresentation();
  }

  static const char* GetReturnDartRepresentation() {
    return tonic::DartConverter<Return>::GetDartRepresentation();
  }

  static void WriteFfiArguments(std::ostringstream* stream) {
    *stream << tonic::DartConverter<C*>::GetFfiRepresentation();
    if constexpr (sizeof...(Args) > 0) {
      *stream << ", ";
      ::tonic::WriteFfiArguments<Args...>(stream);
    }
  }

  static void WriteDartArguments(std::ostringstream* stream) {
    *stream << tonic::DartConverter<C*>::GetDartRepresentation();
    if constexpr (sizeof...(Args) > 0) {
      *stream << ", ";
      ::tonic::WriteDartArguments<Args...>(stream);
    }
  }
};

// `void` specialisation since we can't declare `ToFfi` to take void rvalues.
// Match `void function(...)`.
template <typename... Args, void (*function)(Args...)>
struct FfiDispatcher<void, void (*)(Args...), function> {
  static const size_t n_args = sizeof...(Args);

  // Static C entry-point with Dart FFI signature.
  static void Call(
      typename DartConverter<typename std::remove_const<
          typename std::remove_reference<Args>::type>::type>::FfiType... args) {
    // Call C++ function, forwarding converted native arguments.
    function(
        DartConverter<typename std::remove_const<typename std::remove_reference<
            Args>::type>::type>::FromFfi(args)...);
  }

  static bool AllowedAsLeafCall() {
    if constexpr (sizeof...(Args) > 0) {
      return AllowedInLeafCall<Args...>();
    }
    return true;
  }

  static const char* GetReturnFfiRepresentation() {
    return tonic::DartConverter<void>::GetFfiRepresentation();
  }

  static const char* GetReturnDartRepresentation() {
    return tonic::DartConverter<void>::GetDartRepresentation();
  }

  static void WriteFfiArguments(std::ostringstream* stream) {
    if constexpr (sizeof...(Args) > 0) {
      ::tonic::WriteFfiArguments<Args...>(stream);
    }
  }

  static void WriteDartArguments(std::ostringstream* stream) {
    if constexpr (sizeof...(Args) > 0) {
      ::tonic::WriteDartArguments<Args...>(stream);
    }
  }
};

// `void` specialisation since we can't declare `ToFfi` to take void rvalues.
// Match `void C::method(...)`.
template <typename C, typename... Args, void (C::*method)(Args...)>
struct FfiDispatcher<C, void (C::*)(Args...), method> {
  static const size_t n_args = sizeof...(Args);

  // Static C entry-point with Dart FFI signature.
  static void Call(
      C* receiver,
      typename DartConverter<typename std::remove_const<
          typename std::remove_reference<Args>::type>::type>::FfiType... args) {
    // Call C++ method on receiver, forwarding converted native arguments.
    (receiver->*method)(
        DartConverter<typename std::remove_const<typename std::remove_reference<
            Args>::type>::type>::FromFfi(args)...);
  }

  static bool AllowedAsLeafCall() {
    if constexpr (sizeof...(Args) > 0) {
      return AllowedInLeafCall<Args...>();
    }
    return true;
  }

  static const char* GetReturnFfiRepresentation() {
    return tonic::DartConverter<void>::GetFfiRepresentation();
  }

  static const char* GetReturnDartRepresentation() {
    return tonic::DartConverter<void>::GetDartRepresentation();
  }

  static void WriteFfiArguments(std::ostringstream* stream) {
    *stream << tonic::DartConverter<C*>::GetFfiRepresentation();
    if constexpr (sizeof...(Args) > 0) {
      *stream << ", ";
      ::tonic::WriteFfiArguments<Args...>(stream);
    }
  }

  static void WriteDartArguments(std::ostringstream* stream) {
    *stream << tonic::DartConverter<C*>::GetDartRepresentation();
    if constexpr (sizeof...(Args) > 0) {
      *stream << ", ";
      ::tonic::WriteDartArguments<Args...>(stream);
    }
  }
};

}  // namespace tonic

#endif  // LIB_TONIC_DART_ARGS_H_
