/*
 * Copyright 2015 Facebook, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// @author Nicholas Ormrod <njormrod@fb.com>

#ifndef DYNAMIC_CONVERTER_H
#define DYNAMIC_CONVERTER_H

#include <folly/dynamic.h>
namespace folly {
  template <typename T> T convertTo(const dynamic&);
  template <typename T> dynamic toDynamic(const T&);
}

/**
 * convertTo returns a well-typed representation of the input dynamic.
 *
 * Example:
 *
 *   dynamic d = { { 1, 2, 3 }, { 4, 5 } }; // a vector of vector of int
 *   auto vvi = convertTo<fbvector<fbvector<int>>>(d);
 *
 * See docs/DynamicConverter.md for supported types and customization
 */


#include <type_traits>
#include <iterator>
#include <boost/iterator/iterator_adaptor.hpp>
#include <boost/mpl/has_xxx.hpp>
#include <folly/Likely.h>

namespace folly {

///////////////////////////////////////////////////////////////////////////////
// traits

namespace dynamicconverter_detail {

BOOST_MPL_HAS_XXX_TRAIT_DEF(value_type);
BOOST_MPL_HAS_XXX_TRAIT_DEF(iterator);
BOOST_MPL_HAS_XXX_TRAIT_DEF(mapped_type);

template <typename T> struct iterator_class_is_container {
  typedef std::reverse_iterator<typename T::iterator> some_iterator;
  enum { value = has_value_type<T>::value &&
              std::is_constructible<T, some_iterator, some_iterator>::value };
};

template <typename T>
using class_is_container = typename
  std::conditional<
    has_iterator<T>::value,
    iterator_class_is_container<T>,
    std::false_type
  >::type;

template <typename T> struct class_is_range {
  enum { value = has_value_type<T>::value &&
                 has_iterator<T>::value };
};


template <typename T> struct is_container
  : std::conditional<
      std::is_class<T>::value,
      class_is_container<T>,
      std::false_type
    >::type {};

template <typename T> struct is_range
  : std::conditional<
      std::is_class<T>::value,
      class_is_range<T>,
      std::false_type
    >::type {};

template <typename T> struct is_map
  : std::integral_constant<
      bool,
      is_range<T>::value && has_mapped_type<T>::value
    > {};

} // namespace dynamicconverter_detail

///////////////////////////////////////////////////////////////////////////////
// custom iterators

/**
 * We have iterators that dereference to dynamics, but need iterators
 * that dereference to typename T.
 *
 * Implementation details:
 *   1. We cache the value of the dereference operator. This is necessary
 *      because boost::iterator_adaptor requires *it to return a
 *      reference.
 *   2. For const reasons, we cannot call operator= to refresh the
 *      cache: we must call the destructor then placement new.
 */

namespace dynamicconverter_detail {

template<typename T>
struct Dereferencer {
  static inline void
  derefToCache(T* mem, const dynamic::const_item_iterator& it) {
    throw TypeError("array", dynamic::Type::OBJECT);
  }

  static inline void derefToCache(T* mem, const dynamic::const_iterator& it) {
    new (mem) T(convertTo<T>(*it));
  }
};

template<typename F, typename S>
struct Dereferencer<std::pair<F, S>> {
  static inline void
  derefToCache(std::pair<F, S>* mem, const dynamic::const_item_iterator& it) {
    new (mem) std::pair<F, S>(
        convertTo<F>(it->first), convertTo<S>(it->second)
    );
  }

  // Intentional duplication of the code in Dereferencer
  template <typename T>
  static inline void derefToCache(T* mem, const dynamic::const_iterator& it) {
    new (mem) T(convertTo<T>(*it));
  }
};

template <typename T, typename It>
class Transformer : public boost::iterator_adaptor<
                             Transformer<T, It>,
                             It,
                             typename T::value_type
                           > {
  friend class boost::iterator_core_access;

  typedef typename T::value_type ttype;

  mutable ttype cache_;
  mutable bool valid_;

  void increment() {
    ++this->base_reference();
    valid_ = false;
  }

  ttype& dereference() const {
    if (LIKELY(!valid_)) {
      cache_.~ttype();
      Dereferencer<ttype>::derefToCache(&cache_, this->base_reference());
      valid_ = true;
    }
    return cache_;
  }

public:
  explicit Transformer(const It& it)
    : Transformer::iterator_adaptor_(it), valid_(false) {}
};

// conversion factory
template <typename T, typename It>
inline std::move_iterator<Transformer<T, It>>
conversionIterator(const It& it) {
  return std::make_move_iterator(Transformer<T, It>(it));
}

} // namespace dynamicconverter_detail

///////////////////////////////////////////////////////////////////////////////
// DynamicConverter specializations

/**
 * Each specialization of DynamicConverter has the function
 *     'static T convert(const dynamic&);'
 */

// default - intentionally unimplemented
template <typename T, typename Enable = void> struct DynamicConverter;

// boolean
template <>
struct DynamicConverter<bool> {
  static bool convert(const dynamic& d) {
    return d.asBool();
  }
};

// integrals
template <typename T>
struct DynamicConverter<T,
    typename std::enable_if<std::is_integral<T>::value &&
                            !std::is_same<T, bool>::value>::type> {
  static T convert(const dynamic& d) {
    return folly::to<T>(d.asInt());
  }
};

// floating point
template <typename T>
struct DynamicConverter<T,
    typename std::enable_if<std::is_floating_point<T>::value>::type> {
  static T convert(const dynamic& d) {
    return folly::to<T>(d.asDouble());
  }
};

// fbstring
template <>
struct DynamicConverter<folly::fbstring> {
  static folly::fbstring convert(const dynamic& d) {
    return d.asString();
  }
};

// std::string
template <>
struct DynamicConverter<std::string> {
  static std::string convert(const dynamic& d) {
    return d.asString().toStdString();
  }
};

// std::pair
template <typename F, typename S>
struct DynamicConverter<std::pair<F,S>> {
  static std::pair<F, S> convert(const dynamic& d) {
    if (d.isArray() && d.size() == 2) {
      return std::make_pair(convertTo<F>(d[0]), convertTo<S>(d[1]));
    } else if (d.isObject() && d.size() == 1) {
      auto it = d.items().begin();
      return std::make_pair(convertTo<F>(it->first), convertTo<S>(it->second));
    } else {
      throw TypeError("array (size 2) or object (size 1)", d.type());
    }
  }
};

// containers
template <typename C>
struct DynamicConverter<C,
    typename std::enable_if<
      dynamicconverter_detail::is_container<C>::value>::type> {
  static C convert(const dynamic& d) {
    if (d.isArray()) {
      return C(dynamicconverter_detail::conversionIterator<C>(d.begin()),
               dynamicconverter_detail::conversionIterator<C>(d.end()));
    } else if (d.isObject()) {
      return C(dynamicconverter_detail::conversionIterator<C>
                 (d.items().begin()),
               dynamicconverter_detail::conversionIterator<C>
                 (d.items().end()));
    } else {
      throw TypeError("object or array", d.type());
    }
  }
};

///////////////////////////////////////////////////////////////////////////////
// DynamicConstructor specializations

/**
 * Each specialization of DynamicConstructor has the function
 *     'static dynamic construct(const C&);'
 */

// default
template <typename C, typename Enable = void>
struct DynamicConstructor {
  static dynamic construct(const C& x) {
    return dynamic(x);
  }
};

// maps
template<typename C>
struct DynamicConstructor<C,
    typename std::enable_if<
      dynamicconverter_detail::is_map<C>::value>::type> {
  static dynamic construct(const C& x) {
    dynamic d = dynamic::object;
    for (auto& pair : x) {
      d.insert(toDynamic(pair.first), toDynamic(pair.second));
    }
    return d;
  }
};

// other ranges
template<typename C>
struct DynamicConstructor<C,
    typename std::enable_if<
      !dynamicconverter_detail::is_map<C>::value &&
      !std::is_constructible<StringPiece, const C&>::value &&
      dynamicconverter_detail::is_range<C>::value>::type> {
  static dynamic construct(const C& x) {
    dynamic d = {};
    for (auto& item : x) {
      d.push_back(toDynamic(item));
    }
    return d;
  }
};

// pair
template<typename A, typename B>
struct DynamicConstructor<std::pair<A, B>, void> {
  static dynamic construct(const std::pair<A, B>& x) {
    dynamic d = {};
    d.push_back(toDynamic(x.first));
    d.push_back(toDynamic(x.second));
    return d;
  }
};

///////////////////////////////////////////////////////////////////////////////
// implementation

template <typename T>
T convertTo(const dynamic& d) {
  return DynamicConverter<typename std::remove_cv<T>::type>::convert(d);
}

template<typename T>
dynamic toDynamic(const T& x) {
  return DynamicConstructor<typename std::remove_cv<T>::type>::construct(x);
}

} // namespace folly

#endif // DYNAMIC_CONVERTER_H
