/*
 *  Copyright (c) 2016, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 */

#ifndef FATAL_INCLUDE_fatal_type_impl_compare_h
#define FATAL_INCLUDE_fatal_type_impl_compare_h

#include <type_traits>

namespace fatal {
namespace i_c {

template <typename, typename, typename, int = 0> struct sc;

template <typename Less, typename LHS, typename RHS>
struct sc<Less, LHS, RHS, -1>: std::true_type {};

template <typename Less, typename LHS, typename RHS>
struct sc<Less, LHS, RHS, 1>: std::false_type {};

template <typename Less, template <typename...> class Variadic>
struct sc<Less, Variadic<>, Variadic<>, 0>: std::false_type {};

template <typename Less, template <typename...> class Variadic, typename... LHS>
struct sc<Less, Variadic<LHS...>, Variadic<>, 0>: std::false_type {};

template <typename Less, template <typename...> class Variadic, typename... RHS>
struct sc<Less, Variadic<>, Variadic<RHS...>, 0>: std::true_type {};

template <
  typename Less,
  template <typename...> class Variadic,
  typename L, typename... LHS,
  typename R, typename... RHS
>
struct sc<Less, Variadic<L, LHS...>, Variadic<R, RHS...>, 0>:
  sc<
    Less,
    Variadic<LHS...>,
    Variadic<RHS...>,
    Less::template apply<L, R>::value
      ? -1
      : Less::template apply<R, L>::value
        ? 1
        : 0
  >
{};

template <typename Less, template <typename V, V...> class Variadic, typename T>
struct sc<Less, Variadic<T>, Variadic<T>, 0>: std::false_type {};

template <
  typename Less,
  template <typename V, V...> class Variadic,
  typename T, T L, T... LHS
>
struct sc<Less, Variadic<T, L, LHS...>, Variadic<T>, 0>: std::false_type {};

template <
  typename Less,
  template <typename V, V...> class Variadic,
  typename T, T R, T... RHS
>
struct sc<Less, Variadic<T>, Variadic<T, R, RHS...>, 0>: std::true_type {};

template <
  typename Less,
  template <typename V, V...> class Variadic,
  typename T,
  T L, T... LHS,
  T R, T... RHS
>
struct sc<Less, Variadic<T, L, LHS...>, Variadic<T, R, RHS...>, 0>:
  sc<
    Less,
    Variadic<T, LHS...>,
    Variadic<T, RHS...>,
    (L < R) ? -1 : (R < L) ? 1 : 0 // TODO: USE PREDICATE
    // TODO: FIX PREDICATE FOR SEQUENCES
    /*
    Less::template apply<L, R>::value
      ? -1
      : Less::template apply<R, L>::value
        ? 1
        : 0
    */
  >
{};

} // namespace i_c {
} // namespace fatal {

#endif // FATAL_INCLUDE_fatal_type_impl_compare_h
