// 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_CONVERTER_TONIC_DART_CONVERTER_H_
#define LIB_CONVERTER_TONIC_DART_CONVERTER_H_

#include <string>
#include <type_traits>
#include <vector>

#include "third_party/dart/runtime/include/dart_api.h"
#include "tonic/common/macros.h"
#include "tonic/logging/dart_error.h"

namespace tonic {

// DartConvert converts types back and forth from Sky to Dart. The template
// parameter |T| determines what kind of type conversion to perform.
template <typename T, typename Enable = void>
struct DartConverter {};

// This is to work around the fact that typedefs do not create new types. If you
// have a typedef, and want it to use a different converter, specialize this
// template and override the types here.
// Ex:
//   typedef int ColorType;  // Want to use a different converter.
//   class ColorConverterType {};  // Dummy type.
//   template<> struct DartConvertType<ColorConverterType> {
//     using ConverterType = ColorConverterType;
//     using ValueType = ColorType;
//   };
template <typename T>
struct DartConverterTypes {
  using ConverterType = T;
  using ValueType = T;
};

template <>
struct DartConverter<void> {
  using FfiType = void;
  static constexpr const char* kFfiRepresentation = "Void";
  static constexpr const char* kDartRepresentation = "void";
  static constexpr bool kAllowedInLeafCall = true;
  static const char* GetFfiRepresentation() { return kFfiRepresentation; }
  static const char* GetDartRepresentation() { return kDartRepresentation; }
  static bool AllowedInLeafCall() { return kAllowedInLeafCall; }
};

////////////////////////////////////////////////////////////////////////////////
// Boolean

template <>
struct DartConverter<bool> {
  using NativeType = bool;
  using FfiType = bool;
  static constexpr const char* kFfiRepresentation = "Bool";
  static constexpr const char* kDartRepresentation = "bool";
  static constexpr bool kAllowedInLeafCall = true;

  static Dart_Handle ToDart(NativeType val) { return Dart_NewBoolean(val); }

  static void SetReturnValue(Dart_NativeArguments args, bool val) {
    Dart_SetBooleanReturnValue(args, val);
  }

  static NativeType FromDart(Dart_Handle handle) {
    bool result = 0;
    Dart_BooleanValue(handle, &result);
    return result;
  }

  static NativeType FromArguments(Dart_NativeArguments args,
                                  int index,
                                  Dart_Handle& exception) {
    bool result = false;
    Dart_GetNativeBooleanArgument(args, index, &result);
    return result;
  }

  static NativeType FromFfi(FfiType val) { return val; }
  static FfiType ToFfi(NativeType val) { return val; }
  static const char* GetFfiRepresentation() { return kFfiRepresentation; }
  static const char* GetDartRepresentation() { return kDartRepresentation; }
  static bool AllowedInLeafCall() { return kAllowedInLeafCall; }
};

////////////////////////////////////////////////////////////////////////////////
// Numbers

template <typename T>
struct DartConverterInteger {
  using FfiType = T;
  static constexpr const char* kDartRepresentation = "int";
  static constexpr bool kAllowedInLeafCall = true;

  static Dart_Handle ToDart(T val) { return Dart_NewInteger(val); }

  static void SetReturnValue(Dart_NativeArguments args, T val) {
    Dart_SetIntegerReturnValue(args, val);
  }

  static T FromDart(Dart_Handle handle) {
    int64_t result = 0;
    Dart_IntegerToInt64(handle, &result);
    return static_cast<T>(result);
  }

  static T FromArguments(Dart_NativeArguments args,
                         int index,
                         Dart_Handle& exception) {
    int64_t result = 0;
    Dart_GetNativeIntegerArgument(args, index, &result);
    return static_cast<T>(result);
  }
  static T FromFfi(FfiType val) { return val; }
  static FfiType ToFfi(T val) { return val; }
  static const char* GetDartRepresentation() { return kDartRepresentation; }
  // Note: Returns the correct bit-width for the host architecture.
  static const char* GetFfiRepresentation() {
    if (sizeof(T) == 4) {
      if (std::is_signed<T>()) {
        return "Int32";
      }
      return "Uint32";
    }
    TONIC_DCHECK(sizeof(T) == 8);
    if (std::is_signed<T>()) {
      return "Int64";
    }
    return "Uint64";
  }
  static bool AllowedInLeafCall() { return kAllowedInLeafCall; }
};

template <>
struct DartConverter<int> : public DartConverterInteger<int> {};

template <>
struct DartConverter<long int> : public DartConverterInteger<long int> {};

template <>
struct DartConverter<unsigned> : public DartConverterInteger<unsigned> {};

template <>
struct DartConverter<long long> : public DartConverterInteger<long long> {};

template <>
struct DartConverter<unsigned long>
    : public DartConverterInteger<unsigned long> {};

template <>
struct DartConverter<unsigned long long> {
  using FfiType = unsigned long long;
  static constexpr const char* kFfiRepresentation = "Uint64";
  static constexpr const char* kDartRepresentation = "int";
  static constexpr bool kAllowedInLeafCall = true;

  // TODO(abarth): The Dart VM API doesn't yet have an entry-point for
  // an unsigned 64-bit type. We will need to add a Dart API for
  // constructing an integer from uint64_t.
  //
  // (In the meantime, we have asserts below to check that we're never
  // converting values that have the 64th bit set.)

  static Dart_Handle ToDart(unsigned long long val) {
    TONIC_DCHECK(val <= 0x7fffffffffffffffLL);
    return Dart_NewInteger(static_cast<int64_t>(val));
  }

  static void SetReturnValue(Dart_NativeArguments args,
                             unsigned long long val) {
    TONIC_DCHECK(val <= 0x7fffffffffffffffLL);
    Dart_SetIntegerReturnValue(args, val);
  }

  static unsigned long long FromDart(Dart_Handle handle) {
    int64_t result = 0;
    Dart_IntegerToInt64(handle, &result);
    return result;
  }

  static unsigned long long FromArguments(Dart_NativeArguments args,
                                          int index,
                                          Dart_Handle& exception) {
    int64_t result = 0;
    Dart_GetNativeIntegerArgument(args, index, &result);
    return result;
  }

  static const char* GetFfiRepresentation() { return kFfiRepresentation; }
  static const char* GetDartRepresentation() { return kDartRepresentation; }
  static bool AllowedInLeafCall() { return kAllowedInLeafCall; }
  static FfiType FromFfi(FfiType val) {
    TONIC_DCHECK(val <= 0x7fffffffffffffffLL);
    return val;
  }
  // FFI does a bitwise conversion from uint64_t in C to int64 in Dart.
  static FfiType ToFfi(FfiType val) {
    TONIC_DCHECK(val <= 0x7fffffffffffffffLL);
    return val;
  }
};

template <typename T>
struct DartConverterFloatingPoint {
  using FfiType = T;
  static constexpr bool kAllowedInLeafCall = true;

  static Dart_Handle ToDart(T val) { return Dart_NewDouble(val); }

  static void SetReturnValue(Dart_NativeArguments args, T val) {
    Dart_SetDoubleReturnValue(args, val);
  }

  static T FromDart(Dart_Handle handle) {
    double result = 0;
    Dart_DoubleValue(handle, &result);
    return result;
  }

  static T FromArguments(Dart_NativeArguments args,
                         int index,
                         Dart_Handle& exception) {
    double result = 0;
    Dart_GetNativeDoubleArgument(args, index, &result);
    return result;
  }

  static T FromFfi(FfiType val) { return val; }
  static FfiType ToFfi(T val) { return val; }
  static bool AllowedInLeafCall() { return kAllowedInLeafCall; }
};

template <>
struct DartConverter<float> : public DartConverterFloatingPoint<float> {
  static constexpr const char* kFfiRepresentation = "Float";
  static constexpr const char* kDartRepresentation = "double";
  static const char* GetFfiRepresentation() { return kFfiRepresentation; }
  static const char* GetDartRepresentation() { return kDartRepresentation; }
};

template <>
struct DartConverter<double> : public DartConverterFloatingPoint<double> {
  static constexpr const char* kFfiRepresentation = "Double";
  static constexpr const char* kDartRepresentation = "double";
  static const char* GetFfiRepresentation() { return kFfiRepresentation; }
  static const char* GetDartRepresentation() { return kDartRepresentation; }
};

////////////////////////////////////////////////////////////////////////////////
// Enum Classes

template <typename T>
struct DartConverter<T, typename std::enable_if<std::is_enum<T>::value>::type> {
  using FfiType = int32_t;
  static constexpr const char* kFfiRepresentation = "Int32";
  static constexpr const char* kDartRepresentation = "int";
  static constexpr bool kAllowedInLeafCall = true;

  static Dart_Handle ToDart(T val) {
    return Dart_NewInteger(
        static_cast<typename std::underlying_type<T>::type>(val));
  }

  static void SetReturnValue(Dart_NativeArguments args, T val) {
    Dart_SetIntegerReturnValue(
        args, static_cast<typename std::underlying_type<T>::type>(val));
  }

  static T FromDart(Dart_Handle handle) {
    int64_t result = 0;
    Dart_IntegerToInt64(handle, &result);
    return static_cast<T>(result);
  }

  static T FromArguments(Dart_NativeArguments args,
                         int index,
                         Dart_Handle& exception) {
    int64_t result = 0;
    Dart_GetNativeIntegerArgument(args, index, &result);
    return static_cast<T>(result);
  }

  static T FromFfi(FfiType val) { return static_cast<T>(val); }
  static const char* GetFfiRepresentation() { return kFfiRepresentation; }
  static const char* GetDartRepresentation() { return kDartRepresentation; }
  static bool AllowedInLeafCall() { return kAllowedInLeafCall; }
};

////////////////////////////////////////////////////////////////////////////////
// Strings

template <>
struct DartConverter<std::string> {
  using NativeType = std::string;
  using FfiType = Dart_Handle;
  static constexpr const char* kFfiRepresentation = "Handle";
  static constexpr const char* kDartRepresentation = "String";
  static constexpr bool kAllowedInLeafCall = false;

  static Dart_Handle ToDart(const NativeType& val) {
    return Dart_NewStringFromUTF8(reinterpret_cast<const uint8_t*>(val.data()),
                                  val.length());
  }

  static void SetReturnValue(Dart_NativeArguments args, const NativeType& val) {
    Dart_SetReturnValue(args, ToDart(val));
  }

  static NativeType FromDart(Dart_Handle handle) {
    if (Dart_IsNull(handle)) {
      return std::string();
    }
    uint8_t* data = nullptr;
    intptr_t length = 0;
    if (Dart_IsError(Dart_StringToUTF8(handle, &data, &length)))
      return std::string();
    return std::string(reinterpret_cast<char*>(data), length);
  }

  static NativeType FromArguments(Dart_NativeArguments args,
                                  int index,
                                  Dart_Handle& exception) {
    return FromDart(Dart_GetNativeArgument(args, index));
  }

  static NativeType FromFfi(FfiType val) { return FromDart(val); }
  static FfiType ToFfi(NativeType val) { return ToDart(val); }
  static const char* GetFfiRepresentation() { return kFfiRepresentation; }
  static const char* GetDartRepresentation() { return kDartRepresentation; }
  static bool AllowedInLeafCall() { return kAllowedInLeafCall; }
};

template <>
struct DartConverter<std::u16string> {
  using NativeType = std::u16string;
  using FfiType = Dart_Handle;
  static constexpr const char* kFfiRepresentation = "Handle";
  static constexpr const char* kDartRepresentation = "String";
  static constexpr bool kAllowedInLeafCall = false;

  static Dart_Handle ToDart(const NativeType& val) {
    return Dart_NewStringFromUTF16(
        reinterpret_cast<const uint16_t*>(val.data()), val.length());
  }

  static void SetReturnValue(Dart_NativeArguments args, const NativeType& val) {
    Dart_SetReturnValue(args, ToDart(val));
  }

  static NativeType FromDart(Dart_Handle handle) {
    if (Dart_IsNull(handle)) {
      return std::u16string();
    }
    intptr_t length = 0;
    Dart_StringLength(handle, &length);
    std::vector<uint16_t> data(length);
    Dart_StringToUTF16(handle, data.data(), &length);
    return std::u16string(reinterpret_cast<char16_t*>(data.data()), length);
  }

  static NativeType FromArguments(Dart_NativeArguments args,
                                  int index,
                                  Dart_Handle& exception) {
    return FromDart(Dart_GetNativeArgument(args, index));
  }

  static NativeType FromFfi(FfiType val) { return FromDart(val); }
  static FfiType ToFfi(NativeType val) { return ToDart(val); }
  static const char* GetFfiRepresentation() { return kFfiRepresentation; }
  static const char* GetDartRepresentation() { return kDartRepresentation; }
  static bool AllowedInLeafCall() { return kAllowedInLeafCall; }
};

template <>
struct DartConverter<const char*> {
  static Dart_Handle ToDart(const char* val) {
    return Dart_NewStringFromCString(val);
  }

  static void SetReturnValue(Dart_NativeArguments args, const char* val) {
    Dart_SetReturnValue(args, ToDart(val));
  }

  static const char* FromDart(Dart_Handle handle) {
    if (Dart_IsNull(handle)) {
      return nullptr;
    }
    const char* result = nullptr;
    Dart_StringToCString(handle, &result);
    return result;
  }

  static const char* FromArguments(Dart_NativeArguments args,
                                   int index,
                                   Dart_Handle& exception) {
    return FromDart(Dart_GetNativeArgument(args, index));
  }
};

////////////////////////////////////////////////////////////////////////////////
// Collections

inline Dart_Handle LookupNonNullableType(const std::string& library_name,
                                         const std::string& type_name) {
  auto library =
      Dart_LookupLibrary(DartConverter<std::string>::ToDart(library_name));
  if (CheckAndHandleError(library)) {
    return library;
  }
  auto type_string = DartConverter<std::string>::ToDart(type_name);
  if (CheckAndHandleError(type_string)) {
    return type_string;
  }
  auto type = Dart_GetNonNullableType(library, type_string, 0, nullptr);
  if (CheckAndHandleError(type)) {
    return type;
  }
  return type;
}

template <typename T,
          std::enable_if_t<std::is_same<std::string, T>::value, int> = 0>
Dart_Handle ToDartTypeHandle() {
  return LookupNonNullableType("dart:core", "String");
}

template <typename T, std::enable_if_t<std::is_integral<T>::value, int> = 0>
Dart_Handle ToDartTypeHandle() {
  return LookupNonNullableType("dart:core", "int");
}

template <typename T,
          std::enable_if_t<std::is_floating_point<T>::value, int> = 0>
Dart_Handle ToDartTypeHandle() {
  return LookupNonNullableType("dart:core", "double");
}

template <typename T>
Dart_Handle CreateZeroInitializedDartObject(
    Dart_Handle type_handle_or_null = ::Dart_Null()) {
  if constexpr (std::is_same<std::string, T>::value) {
    return ::Dart_EmptyString();
  } else if constexpr (std::is_integral<T>::value) {
    return ::Dart_NewIntegerFromUint64(0u);
  } else if constexpr (std::is_floating_point<T>::value) {
    return ::Dart_NewDouble(0.0);
  } else {
    auto object = ::Dart_New(type_handle_or_null, ::Dart_Null(), 0, nullptr);
    CheckAndHandleError(object);
    return object;
  }
  return ::Dart_Null();
}

template <typename T, typename Enable = void>
struct DartListFactory {
  static Dart_Handle NewList(Dart_Handle type_handle, intptr_t length) {
    bool is_nullable = false;
    auto is_nullable_handle = ::Dart_IsNullableType(type_handle, &is_nullable);
    if (CheckAndHandleError(is_nullable_handle)) {
      return is_nullable_handle;
    }
    if (is_nullable) {
      auto list = ::Dart_NewListOfType(type_handle, length);
      CheckAndHandleError(list);
      return list;
    } else {
      auto sentinel = CreateZeroInitializedDartObject<T>(type_handle);
      if (CheckAndHandleError(sentinel)) {
        return sentinel;
      }
      auto list = ::Dart_NewListOfTypeFilled(type_handle, sentinel, length);
      CheckAndHandleError(list);
      return list;
    }
    return ::Dart_Null();
  }
};

template <typename T>
struct DartConverter<std::vector<T>> {
  using FfiType = Dart_Handle;
  static constexpr const char* kFfiRepresentation = "Handle";
  static constexpr const char* kDartRepresentation = "List";
  static constexpr bool kAllowedInLeafCall = false;

  using ValueType = typename DartConverterTypes<T>::ValueType;
  using ConverterType = typename DartConverterTypes<T>::ConverterType;

  static Dart_Handle ToDart(const std::vector<ValueType>& val) {
    Dart_Handle list = DartListFactory<ValueType>::NewList(
        ToDartTypeHandle<ValueType>(), val.size());
    if (Dart_IsError(list))
      return list;
    for (size_t i = 0; i < val.size(); i++) {
      Dart_Handle result =
          Dart_ListSetAt(list, i, DartConverter<ConverterType>::ToDart(val[i]));
      if (Dart_IsError(result))
        return result;
    }
    return list;
  }

  static void SetReturnValue(Dart_NativeArguments args,
                             const std::vector<ValueType>& val) {
    Dart_SetReturnValue(args, ToDart(val));
  }

  static std::vector<ValueType> FromDart(Dart_Handle handle) {
    std::vector<ValueType> result;

    if (!Dart_IsList(handle))
      return result;

    intptr_t length = 0;
    Dart_ListLength(handle, &length);

    if (length == 0)
      return result;

    result.reserve(length);

    std::vector<Dart_Handle> items(length);
    Dart_Handle items_result =
        Dart_ListGetRange(handle, 0, length, items.data());
    TONIC_DCHECK(!Dart_IsError(items_result));

    for (intptr_t i = 0; i < length; ++i) {
      TONIC_DCHECK(items[i]);
      result.push_back(DartConverter<ConverterType>::FromDart(items[i]));
    }
    return result;
  }

  static std::vector<ValueType> FromArguments(Dart_NativeArguments args,
                                              int index,
                                              Dart_Handle& exception) {
    return FromDart(Dart_GetNativeArgument(args, index));
  }

  static std::vector<ValueType> FromFfi(FfiType val) { return FromDart(val); }
  static FfiType ToFfi(std::vector<ValueType> val) { return ToDart(val); }
  static const char* GetFfiRepresentation() { return kFfiRepresentation; }
  static const char* GetDartRepresentation() { return kDartRepresentation; }
  static bool AllowedInLeafCall() { return kAllowedInLeafCall; }
};

////////////////////////////////////////////////////////////////////////////////
// Dart_Handle

template <>
struct DartConverter<Dart_Handle> {
  using NativeType = Dart_Handle;
  using FfiType = Dart_Handle;
  static constexpr const char* kFfiRepresentation = "Handle";
  static constexpr const char* kDartRepresentation = "Object";
  static constexpr bool kAllowedInLeafCall = false;

  static Dart_Handle ToDart(NativeType val) { return val; }

  static void SetReturnValue(Dart_NativeArguments args, Dart_Handle val) {
    Dart_SetReturnValue(args, val);
  }

  static NativeType FromDart(Dart_Handle handle) { return handle; }

  static NativeType FromArguments(Dart_NativeArguments args,
                                  int index,
                                  Dart_Handle& exception) {
    Dart_Handle result = Dart_GetNativeArgument(args, index);
    TONIC_DCHECK(!Dart_IsError(result));
    return result;
  }

  static NativeType FromFfi(FfiType val) { return val; }
  static FfiType ToFfi(NativeType val) { return val; }
  static const char* GetFfiRepresentation() { return kFfiRepresentation; }
  static const char* GetDartRepresentation() { return kDartRepresentation; }
  static bool AllowedInLeafCall() { return kAllowedInLeafCall; }
};

////////////////////////////////////////////////////////////////////////////////
// Convenience wrappers using type inference

template <typename T>
Dart_Handle ToDart(const T& object) {
  return DartConverter<T>::ToDart(object);
}

////////////////////////////////////////////////////////////////////////////////
// std::string support

inline Dart_Handle StdStringToDart(const std::string& val) {
  return DartConverter<std::string>::ToDart(val);
}

inline std::string StdStringFromDart(Dart_Handle handle) {
  return DartConverter<std::string>::FromDart(handle);
}

// Alias Dart_NewStringFromCString for less typing.
inline Dart_Handle ToDart(const char* val) {
  return Dart_NewStringFromCString(val);
}

}  // namespace tonic

#endif  // LIB_CONVERTER_TONIC_DART_CONVERTER_H_
