// Copyright 2015 The Chromium 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 SKY_ENGINE_TONIC_DART_CONVERTER_H_
#define SKY_ENGINE_TONIC_DART_CONVERTER_H_

#include <string>
#include "tonic/dart_state.h"
#include "tonic/dart_string.h"
#include "tonic/dart_string_cache.h"
#include "tonic/dart_value.h"
#include "sky/engine/wtf/text/StringUTF8Adaptor.h"
#include "sky/engine/wtf/text/WTFString.h"

namespace blink {

// 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;
};

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

template <>
struct DartConverter<bool> {
  static Dart_Handle ToDart(bool val) { return Dart_NewBoolean(val); }

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

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

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

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

template <typename T>
struct DartConverterInteger {
  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);
  }
};

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

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

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

template <>
struct DartConverter<unsigned long long> {
  static Dart_Handle ToDart(unsigned long long val) {
    // FIXME: WebIDL unsigned long long is guaranteed to fit into 64-bit
    // unsigned,
    // so we need a dart API for constructing an integer from uint64_t.
    DCHECK(val <= 0x7fffffffffffffffLL);
    return Dart_NewInteger(static_cast<int64_t>(val));
  }

  static void SetReturnValue(Dart_NativeArguments args,
                             unsigned long long val) {
    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;
  }
};

template <typename T>
struct DartConverterFloatingPoint {
  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;
  }
};

template <>
struct DartConverter<float> : public DartConverterFloatingPoint<float> {};

template <>
struct DartConverter<double> : public DartConverterFloatingPoint<double> {};

////////////////////////////////////////////////////////////////////////////////
// Enums

template <typename T>
struct DartConverterEnum {
  static T FromArguments(Dart_NativeArguments args,
                         int index,
                         Dart_Handle& exception) {
    Dart_Handle enum_handle = Dart_GetNativeArgument(args, index);
    Dart_Handle index_handle =
        Dart_GetField(enum_handle, DartState::Current()->index_handle());

    uint64_t enum_index = 0;
    Dart_IntegerToUint64(index_handle, &enum_index);
    return static_cast<T>(enum_index);
  }
};

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

template <>
struct DartConverter<String> {
  static Dart_Handle ToDart(DartState* state, const String& val) {
    if (val.isEmpty())
      return Dart_EmptyString();
    return Dart_HandleFromWeakPersistent(state->string_cache().Get(val.impl()));
  }

  static void SetReturnValue(Dart_NativeArguments args,
                             const String& val,
                             bool auto_scope = true) {
    // TODO(abarth): What should we do with auto_scope?
    if (val.isEmpty()) {
      Dart_SetReturnValue(args, Dart_EmptyString());
      return;
    }
    DartState* state = DartState::Current();
    Dart_SetWeakHandleReturnValue(args, state->string_cache().Get(val.impl()));
  }

  static void SetReturnValueWithNullCheck(Dart_NativeArguments args,
                                          const String& val,
                                          bool auto_scope = true) {
    if (val.isNull())
      Dart_SetReturnValue(args, Dart_Null());
    else
      SetReturnValue(args, val, auto_scope);
  }

  static String FromDart(Dart_Handle handle) {
    intptr_t char_size = 0;
    intptr_t length = 0;
    void* peer = nullptr;
    Dart_Handle result =
        Dart_StringGetProperties(handle, &char_size, &length, &peer);
    if (peer)
      return String(static_cast<StringImpl*>(peer));
    if (Dart_IsError(result))
      return String();
    return ExternalizeDartString(handle);
  }

  static String FromArguments(Dart_NativeArguments args,
                              int index,
                              Dart_Handle& exception,
                              bool auto_scope = true) {
    // TODO(abarth): What should we do with auto_scope?
    void* peer = nullptr;
    Dart_Handle handle = Dart_GetNativeStringArgument(args, index, &peer);
    if (peer)
      return reinterpret_cast<StringImpl*>(peer);
    if (Dart_IsError(handle))
      return String();
    return ExternalizeDartString(handle);
  }

  static String FromArgumentsWithNullCheck(Dart_NativeArguments args,
                                           int index,
                                           Dart_Handle& exception,
                                           bool auto_scope = true) {
    // TODO(abarth): What should we do with auto_scope?
    void* peer = nullptr;
    Dart_Handle handle = Dart_GetNativeStringArgument(args, index, &peer);
    if (peer)
      return reinterpret_cast<StringImpl*>(peer);
    if (Dart_IsError(handle) || Dart_IsNull(handle))
      return String();
    return ExternalizeDartString(handle);
  }
};

template <>
struct DartConverter<AtomicString> {
  static Dart_Handle ToDart(DartState* state, const AtomicString& val) {
    return DartConverter<String>::ToDart(state, val.string());
  }
};

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

template <typename T>
struct DartConverter<Vector<T>> {
  using ValueType = typename DartConverterTypes<T>::ValueType;
  using ConverterType = typename DartConverterTypes<T>::ConverterType;

  static Dart_Handle ToDart(const Vector<ValueType>& val) {
    Dart_Handle list = Dart_NewList(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 Vector<ValueType> FromDart(Dart_Handle handle) {
    Vector<ValueType> result;
    if (!Dart_IsList(handle))
      return result;
    intptr_t length = 0;
    Dart_ListLength(handle, &length);
    result.reserveCapacity(length);
    for (intptr_t i = 0; i < length; ++i) {
      Dart_Handle item = Dart_ListGetAt(handle, i);
      DCHECK(!Dart_IsError(item));
      DCHECK(item);
      result.append(DartConverter<ConverterType>::FromDart(item));
    }
    return result;
  }

  static Vector<ValueType> FromArguments(Dart_NativeArguments args,
                                          int index,
                                          Dart_Handle& exception,
                                          bool auto_scope = true) {
    // TODO(abarth): What should we do with auto_scope?
    return FromDart(Dart_GetNativeArgument(args, index));
  }
};

////////////////////////////////////////////////////////////////////////////////
// DartValue

template <>
struct DartConverter<DartValue*> {
  static Dart_Handle ToDart(DartState* state, DartValue* val) {
    return val->dart_value();
  }

  static void SetReturnValue(Dart_NativeArguments args, DartValue* val) {
    Dart_SetReturnValue(args, val->dart_value());
  }

  static PassRefPtr<DartValue> FromDart(Dart_Handle handle) {
    return DartValue::Create(DartState::Current(), handle);
  }

  static PassRefPtr<DartValue> FromArguments(Dart_NativeArguments args,
                                             int index,
                                             Dart_Handle& exception,
                                             bool auto_scope = true) {
    // TODO(abarth): What should we do with auto_scope?
    return FromDart(Dart_GetNativeArgument(args, index));
  }
};

////////////////////////////////////////////////////////////////////////////////
// Convience wrappers for commonly used conversions

inline Dart_Handle StringToDart(DartState* state, const String& val) {
  return DartConverter<String>::ToDart(state, val);
}

inline Dart_Handle StringToDart(DartState* state, const AtomicString& val) {
  return DartConverter<AtomicString>::ToDart(state, val);
}

inline String StringFromDart(Dart_Handle handle) {
  return DartConverter<String>::FromDart(handle);
}

////////////////////////////////////////////////////////////////////////////////
// Convience wrappers using type inference for ease of code generation

template <typename T>
inline Dart_Handle VectorToDart(const Vector<T>& val) {
  return DartConverter<Vector<T>>::ToDart(val);
}

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

////////////////////////////////////////////////////////////////////////////////
// std::string support (slower, but more convienent for some clients)

inline Dart_Handle StdStringToDart(const std::string& val) {
  return Dart_NewStringFromUTF8(reinterpret_cast<const uint8_t*>(val.data()),
                                val.length());
}

inline std::string StdStringFromDart(Dart_Handle handle) {
  String string = StringFromDart(handle);
  StringUTF8Adaptor utf8(string);
  return std::string(utf8.data(), utf8.length());
}


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

}  // namespace blink

#endif  // SKY_ENGINE_TONIC_DART_CONVERTER_H_
