// Copyright 2018 The Fuchsia 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_FIT_VARIANT_H_
#define LIB_FIT_VARIANT_H_

#include <exception>
#include <new>
#include <type_traits>
#include <utility>

#include "constructors_internal.h"
#include "in_place_internal.h"
#include "storage_internal.h"
#include "traits.h"
#include "utility_internal.h"

namespace fit {

// A default-constructible type that may be used as the first variant type to
// make fit::variant default-constructible when other variants are not. This
// type may also be used as an alternative representing an empty value.
struct monostate final {
  constexpr bool operator==(const monostate& other) const { return true; }
  constexpr bool operator!=(const monostate& other) const { return false; }
  constexpr bool operator<(const monostate& other) const { return false; }
  constexpr bool operator>(const monostate& other) const { return false; }
  constexpr bool operator<=(const monostate& other) const { return true; }
  constexpr bool operator>=(const monostate& other) const { return true; }
};

namespace internal {

// Helper type to avoid recursive instantiations of the full variant type.
template <typename...>
struct variant_list {};

// Gets the number of alternatives in a variant_list as a compile-time constant.
template <typename T>
struct variant_list_size;

template <typename... Ts>
struct variant_list_size<variant_list<Ts...>> : std::integral_constant<size_t, sizeof...(Ts)> {};

// Helper to get the type of a variant_list alternative with the given index.
template <size_t Index, typename VariantList>
struct variant_alternative;

template <size_t Index, typename T0, typename... Ts>
struct variant_alternative<Index, variant_list<T0, Ts...>>
    : variant_alternative<Index - 1, variant_list<Ts...>> {};

template <typename T0, typename... Ts>
struct variant_alternative<0, variant_list<T0, Ts...>> {
  using type = T0;
};

}  // namespace internal

// Forward declaration.
template <typename... Ts>
class variant;

// Gets the type of a variant alternative with the given index.
template <size_t Index, typename Variant>
struct variant_alternative;

template <size_t Index, typename... Ts>
struct variant_alternative<Index, variant<Ts...>>
    : ::fit::internal::variant_alternative<Index, ::fit::internal::variant_list<Ts...>> {};

template <size_t index, typename Variant>
using variant_alternative_t = typename variant_alternative<index, Variant>::type;

// Gets the number of alternatives in a variant as a compile-time constant
// expression.
template <typename T>
struct variant_size;

template <typename... Ts>
struct variant_size<variant<Ts...>> : std::integral_constant<size_t, sizeof...(Ts)> {};

template <typename T>
struct variant_size<const T> : variant_size<T> {};
template <typename T>
struct variant_size<volatile T> : variant_size<T> {};
template <typename T>
struct variant_size<const volatile T> : variant_size<T> {};

#ifdef __cpp_inline_variables

template <typename T>
inline constexpr size_t variant_size_v = variant_size<T>::value;

#else

template <typename T>
struct variant_size_holder {
  static constexpr size_t value{variant_size<T>::value};
};

template <typename T>
constexpr size_t variant_size_holder<T>::value;

template <typename T>
static constexpr const size_t& variant_size_v = variant_size_holder<T>::value;

#endif

// Exception type to report bad accesses to variant.
class bad_variant_access : public std::exception {
 public:
  bad_variant_access() noexcept {}

  const char* what() const noexcept override { return reason_; }

 private:
  template <typename... Ts>
  friend class variant;

  bad_variant_access(const char* reason) noexcept : reason_{reason} {}

  // String describing the reason for the bad access. Must point to a string
  // with static storage duration.
  const char* reason_;
};

namespace internal {

// Helper type to check that conversions do not narrow.
template <typename T>
struct check_narrow {
  T x[1];
};

// Builds a check(Ti) function for each alternative Ti. This trait is evaluated
// for each element of fit::variant<Ts...>. Essentially: for (Index, Ti) in Ts.
//
// Index is the zero-based index of the corresponding element Ti in the pack Ts.
// T is the type deduced from the converting constructor or assignment operator
// of fit::variant for which we want to find an appropriately convertible
// element.
//
// The specializations below match the element Ti that passes the conversion
// checks.
template <size_t Index, typename T, typename Ti,
          bool IsBool = std::is_same<bool, std::remove_cv_t<Ti>>::value, typename = void>
struct check_valid_option {
  // Non-static so that check_valid_option<...>::check is always a valid
  // name, but doesn't participate in the overload resolution in the
  // valid_option_index selection trait.
  void check();
};

// Checks that Ti x[] = {std::forward<T>()} is well formed.
template <size_t Index, typename T, typename Ti>
struct check_valid_option<Index, T, Ti, false,
                          void_t<decltype(check_narrow<Ti>{{std::declval<T>()}})>> {
  static std::integral_constant<size_t, Index> check(Ti);
};

// Checks that remove_cvref_t<T> is bool when Ti is cv bool.
template <size_t Index, typename T, typename Ti>
struct check_valid_option<Index, T, Ti, true,
                          std::enable_if_t<std::is_same<bool, remove_cvref_t<T>>::value>> {
  static std::integral_constant<size_t, Index> check(Ti);
};

// Mixes in instantiations of check_valid_option for each element in
// fit::variant<Ts...>, creating a set of check(Ti) functions that might match
// T following the conversion rules.
template <typename T, typename VariantList,
          typename = std::make_index_sequence<variant_list_size<VariantList>::value>>
struct find_valid_option {
  // Non-static so that find_valid_option<...>::check is always a valid name
  // in the using clause of the recursive case, but doesn't participate in the
  // overload resolution in the valid_option_index trait.
  void check();
};

// Recursive case. This would be simpler with C++17 pack expansion in using
// directives, but this must function in C++14.
template <typename T, typename Ti, size_t Index, typename... Ts, size_t... Is>
struct find_valid_option<T, variant_list<Ti, Ts...>, std::index_sequence<Index, Is...>>
    : check_valid_option<Index, T, Ti>,
      find_valid_option<T, variant_list<Ts...>, std::index_sequence<Is...>> {
  // Introduce the base class definitions of check() into this scope. The
  // static check(Ti) methods participate in overload resolution in the
  // valid_option_index trait, while the non-static check() methods are
  // ignored.
  using check_valid_option<Index, T, Ti>::check;
  using find_valid_option<T, variant_list<Ts...>, std::index_sequence<Is...>>::check;
};

// Evaluates to the index of the valid target type Ti selected from
// fit::variant<Ts...>. The type expression is well formed IFF a single valid
// target type is available that converts from T.
template <typename T, typename VariantList>
using valid_option_index = decltype(find_valid_option<T, VariantList>::check(std::declval<T>()));

// Evaluates to the index of the valid target Ti that converts from T or the
// reserved empty index when no uniquely suitable option is available.
template <typename T, typename Variant, typename = void>
struct selected_index : std::integral_constant<size_t, ::fit::internal::empty_index> {};

template <typename T, typename... Ts>
struct selected_index<T, variant<Ts...>, void_t<valid_option_index<T, variant_list<Ts...>>>>
    : valid_option_index<T, variant_list<Ts...>> {};

}  // namespace internal

// A resonably complete implementation of std::variant compatible with C++14.
template <typename... Ts>
class variant
    : private ::fit::internal::modulate_default_constructor<::fit::internal::first_t<Ts...>>,
      private ::fit::internal::modulate_copy_and_move<Ts...> {
 private:
  static_assert(sizeof...(Ts) > 0, "Variant must have at least one type!");

  static constexpr bool nothrow_default_constructible =
      std::is_nothrow_default_constructible<::fit::internal::first_t<Ts...>>::value;

  static constexpr bool nothrow_move_constructible =
      conjunction_v<std::is_nothrow_move_constructible<Ts>...>;

  static constexpr auto default_init_v = ::fit::internal::default_init_v;
  static constexpr auto trivial_init_v = ::fit::internal::trivial_init_v;

  template <typename T>
  using type_tag = ::fit::internal::type_tag<T>;
  template <size_t Index>
  using index_tag = ::fit::internal::index_tag<Index>;

  template <typename T>
  using not_self_type = ::fit::internal::not_same_type<variant, T>;

  template <typename T>
  using not_in_place = ::fit::internal::not_same_type<in_place_t, T>;

  template <typename T>
  struct occurs_once
      : std::integral_constant<bool, ::fit::internal::occurences_of_v<T, Ts...> == 1> {};

  template <typename... Conditions>
  using requires_conditions = ::fit::internal::requires_conditions<Conditions...>;

  template <typename... Conditions>
  using assignment_requires_conditions =
      ::fit::internal::assignment_requires_conditions<variant&, Conditions...>;

  template <typename T, typename... Args>
  using emplace_constructible_by_type =
      std::enable_if_t<(::fit::internal::occurences_of_v<T, Ts...> == 1 &&
                        std::is_constructible<T, Args...>::value),
                       std::add_lvalue_reference_t<T>>;

  template <size_t Index, typename = std::enable_if_t<(Index < sizeof...(Ts))>>
  using alternative_t = variant_alternative_t<Index, variant>;

  template <size_t Index, typename... Args>
  using emplace_constructible_by_index =
      std::enable_if_t<std::is_constructible<alternative_t<Index>, Args...>::value,
                       std::add_lvalue_reference_t<alternative_t<Index>>>;

  template <typename T>
  static constexpr size_t selected_index = ::fit::internal::selected_index<T, variant>::value;

  template <typename T, typename = std::enable_if<not_self_type<T>::value>>
  using selected_t = alternative_t<selected_index<T>>;

  [[noreturn]] static constexpr void throw_bad_variant_access(const char* reason) {
#if __cpp_exceptions
    throw bad_variant_access(reason);
#else
    (void)reason;
    __builtin_abort();
#endif
  }

 public:
  // Default constructors.

  constexpr variant() noexcept(nothrow_default_constructible) : storage_{default_init_v} {}

  // Copy/move constructors and assignment operators.

  constexpr variant(const variant&) = default;
  constexpr variant& operator=(const variant&) = default;

  constexpr variant(variant&&) noexcept(nothrow_move_constructible) = default;
  constexpr variant& operator=(variant&&) = default;

  // Converting constructors.

  template <typename T,
            requires_conditions<std::integral_constant<bool, (sizeof...(Ts) > 0)>,
                                not_in_place<T>> = true,
            typename Ti = selected_t<T&&>,
            requires_conditions<occurs_once<Ti>, std::is_constructible<Ti, T>> = true>
  constexpr variant(T&& value) noexcept(std::is_nothrow_constructible<Ti, T>::value)
      : storage_(type_tag<Ti>{}, std::forward<T>(value)) {}

  template <typename T, typename... Args,
            requires_conditions<occurs_once<T>, std::is_constructible<T, Args...>> = true>
  explicit constexpr variant(in_place_type_t<T>, Args&&... args)
      : storage_(type_tag<T>{}, std::forward<Args>(args)...) {}

  template <typename T, typename U, typename... Args,
            requires_conditions<occurs_once<T>, std::is_constructible<T, std::initializer_list<T>&,
                                                                      Args...>> = true>
  explicit constexpr variant(in_place_type_t<T>, std::initializer_list<U> init_list, Args&&... args)
      : storage_(type_tag<T>{}, init_list, std::forward<Args>(args)...) {}

  template <size_t Index, typename... Args,
            requires_conditions<std::is_constructible<alternative_t<Index>, Args...>> = true>
  explicit constexpr variant(in_place_index_t<Index>, Args&&... args)
      : storage_(index_tag<Index>{}, std::forward<Args>(args)...) {}

  template <size_t Index, typename U, typename... Args,
            requires_conditions<std::is_constructible<alternative_t<Index>,
                                                      std::initializer_list<U>&, Args...>> = true>
  explicit constexpr variant(in_place_index_t<Index>, std::initializer_list<U> init_list,
                             Args&&... args)
      : storage_(index_tag<Index>{}, init_list, std::forward<Args>(args)...) {}

  ~variant() = default;

  // Converting assignment.

  template <typename T>
  constexpr assignment_requires_conditions<
      occurs_once<selected_t<T>>, std::is_constructible<selected_t<T&&>, T>,
      std::is_assignable<selected_t<T&&>&, T>,
      disjunction<std::is_nothrow_constructible<selected_t<T&&>, T>,
                  negation<std::is_nothrow_move_constructible<selected_t<T&&>>>>>
  operator=(T&& value) noexcept(std::is_nothrow_assignable<selected_t<T&&>&, T>::value&&
                                    std::is_nothrow_constructible<selected_t<T&&>, T>::value) {
    constexpr auto index = selected_index<T>;
    if (storage_.index() == index) {
      storage_.get(index_tag<index>{}) = std::forward<T>(value);
    } else {
      this->emplace<index>(std::forward<T>(value));
    }
    return *this;
  }

  template <typename T>
  constexpr assignment_requires_conditions<
      occurs_once<selected_t<T>>, std::is_constructible<selected_t<T&&>, T>,
      std::is_assignable<selected_t<T&&>&, T>,
      conjunction<negation<std::is_nothrow_constructible<selected_t<T&&>, T>>,
                  std::is_nothrow_move_constructible<selected_t<T&&>>>>
  operator=(T&& value) noexcept(std::is_nothrow_assignable<selected_t<T&&>&, T>::value&&
                                    std::is_nothrow_constructible<selected_t<T&&>, T>::value) {
    constexpr auto index = selected_index<T>;
    if (storage_.index() == index) {
      storage_.get(index_tag<index>{}) = std::forward<T>(value);
    } else {
      this->operator=(variant(std::forward<T>(value)));
    }
    return *this;
  }

  constexpr size_t index() const noexcept { return storage_.index(); }

  // TODO(eieio): Remove uses of these in favor of non-member get.
  template <size_t Index>
  constexpr auto& get() & {
    if (storage_.has_value()) {
      return storage_.get(index_tag<Index>{});
    } else {
      throw_bad_variant_access("Access to empty variant!");
    }
  }
  template <size_t Index>
  constexpr const auto& get() const& {
    if (storage_.has_value()) {
      return storage_.get(index_tag<Index>{});
    } else {
      throw_bad_variant_access("Access to empty variant!");
    }
  }
  template <size_t Index>
  constexpr auto&& get() && {
    if (storage_.has_value()) {
      return std::move(storage_.get(index_tag<Index>{}));
    } else {
      throw_bad_variant_access("Access to empty variant!");
    }
  }
  template <size_t Index>
  constexpr const auto&& get() const&& {
    if (storage_.has_value()) {
      return std::move(storage_.get(index_tag<Index>{}));
    } else {
      throw_bad_variant_access("Access to empty variant!");
    }
  }

  template <typename T>
  constexpr auto& get() & {
    if (storage_.has_value()) {
      return storage_.get(type_tag<T>{});
    } else {
      throw_bad_variant_access("Access to empty variant!");
    }
  }
  template <typename T>
  constexpr const auto& get() const& {
    if (storage_.has_value()) {
      return storage_.get(type_tag<T>{});
    } else {
      throw_bad_variant_access("Access to empty variant!");
    }
  }
  template <typename T>
  constexpr auto&& get() && {
    if (storage_.has_value()) {
      return std::move(storage_.get(type_tag<T>{}));
    } else {
      throw_bad_variant_access("Access to empty variant!");
    }
  }
  template <typename T>
  constexpr const auto&& get() const&& {
    if (storage_.has_value()) {
      return std::move(storage_.get(type_tag<T>{}));
    } else {
      throw_bad_variant_access("Access to empty variant!");
    }
  }

  // Emplacement.

  template <typename T, typename... Args>
  constexpr emplace_constructible_by_type<T, Args&&...> emplace(Args&&... args) {
    storage_.reset();
    storage_.construct(type_tag<T>{}, std::forward<Args>(args)...);
    return storage_.get(type_tag<T>{});
  }

  template <typename T, typename U, typename... Args>
  constexpr emplace_constructible_by_type<T, std::initializer_list<U>&, Args&&...> emplace(
      std::initializer_list<U> init_list, Args&&... args) {
    storage_.reset();
    storage_.construct(type_tag<T>{}, init_list, std::forward<Args>(args)...);
    return storage_.get(type_tag<T>{});
  }

  template <size_t Index, typename... Args>
  constexpr emplace_constructible_by_index<Index, Args&&...> emplace(Args&&... args) {
    storage_.reset();
    storage_.construct(index_tag<Index>{}, std::forward<Args>(args)...);
    return storage_.get(index_tag<Index>{});
  }

  template <size_t Index, typename U, typename... Args>
  constexpr emplace_constructible_by_index<Index, std::initializer_list<U>&, Args&&...> emplace(
      std::initializer_list<U> init_list, Args&&... args) {
    storage_.reset();
    storage_.construct(index_tag<Index>{}, init_list, std::forward<Args>(args)...);
    return storage_.get(index_tag<Index>{});
  }

  // Swap.

  void swap(variant& other) { storage_.swap(other.storage_); }

  // Comparison.

  friend constexpr bool operator==(const variant& lhs, const variant& rhs) {
    bool result = false;
    const bool has_value =
        lhs.storage_.visit([&result, &lhs, &rhs](auto, auto active_index_tag, const auto*) {
          if (lhs.index() != rhs.index()) {
            result = false;
          } else {
            result = lhs.storage_.get(active_index_tag) == rhs.storage_.get(active_index_tag);
          }
        });
    return !has_value || result;
  }
  friend constexpr bool operator!=(const variant& lhs, const variant& rhs) {
    bool result = true;
    const bool has_value =
        lhs.storage_.visit([&result, &lhs, &rhs](auto, auto active_index_tag, const auto*) {
          if (lhs.index() != rhs.index()) {
            result = true;
          } else {
            result = lhs.storage_.get(active_index_tag) != rhs.storage_.get(active_index_tag);
          }
        });
    return has_value && result;
  }
  friend constexpr bool operator<(const variant& lhs, const variant& rhs) {
    bool result = true;
    const bool has_value =
        rhs.storage_.visit([&result, &lhs, &rhs](auto, auto active_index_tag, const auto*) {
          if (!lhs.storage_.has_value()) {
            result = true;
          } else if (lhs.index() < rhs.index()) {
            result = true;
          } else if (lhs.index() > rhs.index()) {
            result = false;
          } else {
            result = lhs.storage_.get(active_index_tag) < rhs.storage_.get(active_index_tag);
          }
        });
    return has_value && result;
  }
  friend constexpr bool operator>(const variant& lhs, const variant& rhs) {
    bool result = true;
    const bool has_value =
        lhs.storage_.visit([&result, &lhs, &rhs](auto, auto active_index_tag, const auto*) {
          if (!rhs.storage_.has_value()) {
            result = true;
          } else if (lhs.index() > rhs.index()) {
            result = true;
          } else if (lhs.index() < rhs.index()) {
            result = false;
          } else {
            result = lhs.storage_.get(active_index_tag) > rhs.storage_.get(active_index_tag);
          }
        });
    return has_value && result;
  }
  friend constexpr bool operator<=(const variant& lhs, const variant& rhs) {
    bool result = false;
    const bool has_value =
        lhs.storage_.visit([&result, &lhs, &rhs](auto, auto active_index_tag, const auto*) {
          if (!rhs.storage_.has_value()) {
            result = false;
          } else if (lhs.index() < rhs.index()) {
            result = true;
          } else if (lhs.index() > rhs.index()) {
            result = false;
          } else {
            result = lhs.storage_.get(active_index_tag) <= rhs.storage_.get(active_index_tag);
          }
        });
    return !has_value || result;
  }
  friend constexpr bool operator>=(const variant& lhs, const variant& rhs) {
    bool result = false;
    const bool has_value =
        rhs.storage_.visit([&result, &lhs, &rhs](auto, auto active_index_tag, const auto*) {
          if (!lhs.storage_.has_value()) {
            result = false;
          } else if (lhs.index() > rhs.index()) {
            result = true;
          } else if (lhs.index() < rhs.index()) {
            result = false;
          } else {
            result = lhs.storage_.get(active_index_tag) >= rhs.storage_.get(active_index_tag);
          }
        });
    return !has_value || result;
  }

 private:
  ::fit::internal::storage_type<Ts...> storage_;
};

// Swaps variants.
template <typename... Ts>
void swap(variant<Ts...>& a, variant<Ts...>& b) {
  a.swap(b);
}

// Accesses the variant by zero-based index.
//
// Accesses should use ADL, similar to the pattern for std::swap:
//
//  using std::get;
//  get<some_index>(some_fit_variant);
//
// This makes code adaptable to substituting std::variant for fit::variant on
// newer compilers.
template <size_t Index, typename... Ts>
constexpr auto& get(variant<Ts...>& value) {
  return value.template get<Index>();
}
template <size_t Index, typename... Ts>
constexpr auto&& get(variant<Ts...>&& value) {
  return std::move(value).template get<Index>();
}
template <size_t Index, typename... Ts>
constexpr const auto& get(const variant<Ts...>& value) {
  return value.template get<Index>();
}
template <size_t Index, typename... Ts>
constexpr const auto&& get(const variant<Ts...>&& value) {
  return std::move(value).template get<Index>();
}

// Accesses the variant by unique type. See note above about ADL.
template <typename T, typename... Ts>
constexpr auto& get(variant<Ts...>& value) {
  return value.template get<T>();
}
template <typename T, typename... Ts>
constexpr auto&& get(variant<Ts...>&& value) {
  return std::move(value).template get<T>();
}
template <typename T, typename... Ts>
constexpr const auto& get(const variant<Ts...>& value) {
  return value.template get<T>();
}
template <typename T, typename... Ts>
constexpr const auto&& get(const variant<Ts...>&& value) {
  return std::move(value).template get<T>();
}

// Checks if the variant holds type T. See note above about ADL.
template <typename T, typename... Ts>
constexpr bool holds_alternative(const variant<Ts...>& value) {
  constexpr auto index = ::fit::internal::selected_index<T, variant<Ts...>>::value;
  return value.index() == index;
}

// TODO(eieio): Remove once the old ::fit::internal spellings of these types is
// removed from FIDL.
namespace internal {

using ::fit::monostate;
using ::fit::variant;

}  // namespace internal

}  // namespace fit

#endif  // LIB_FIT_VARIANT_H_
