// 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_FIDL_CPP_COMPARISON_H_
#define LIB_FIDL_CPP_COMPARISON_H_

#include <array>
#include <cstdint>
#include <map>
#include <memory>
#include <string>
#include <type_traits>
#include <utility>
#include <vector>

#include "lib/fidl/cpp/types.h"

#ifdef __Fuchsia__
#include <lib/zx/object.h>
#endif

// Comparisons that uses structure equality on on std::unique_ptr instead of
// pointer equality.
namespace fidl {

template <class T>
bool Equals(const T& lhs, const T& rhs);

template <typename T, typename = void>
struct Equality {};

template <class T>
struct Equality<T, typename std::enable_if_t<std::is_integral<T>::value>> {
  constexpr bool operator()(const T& lhs, const T& rhs) const { return lhs == rhs; }
};

template <class T>
struct Equality<T, typename std::enable_if_t<std::is_floating_point<T>::value>> {
  constexpr bool operator()(const T& lhs, const T& rhs) const {
    // TODO(ianloic): do something better for floating point comparison?
    return lhs == rhs;
  }
};

#ifdef __Fuchsia__
template <class T>
struct Equality<T, typename std::enable_if_t<std::is_base_of<zx::object_base, T>::value>> {
  bool operator()(const T& lhs, const T& rhs) const { return lhs.get() == rhs.get(); }
};
#endif  // __Fuchsia__

template <typename T, size_t N>
struct Equality<std::array<T, N>> {
  // N.B.: This may be constexpr-able in C++20.
  bool operator()(const std::array<T, N>& lhs, const std::array<T, N>& rhs) const {
    return std::equal(lhs.cbegin(), lhs.cend(), rhs.cbegin(), rhs.cend(), ::fidl::Equality<T>{});
  }
};

template <>
struct Equality<std::string> {
  bool operator()(const std::string& lhs, const std::string& rhs) const { return lhs == rhs; }
};

template <class T>
struct Equality<std::vector<T>> {
  bool operator()(const std::vector<T>& lhs, const std::vector<T>& rhs) const {
    if (lhs.size() != rhs.size()) {
      return false;
    }

    return std::equal(lhs.cbegin(), lhs.cend(), rhs.cbegin(), rhs.cend(), ::fidl::Equality<T>{});
  }
};

template <class T>
struct Equality<std::unique_ptr<T>> {
  constexpr bool operator()(const std::unique_ptr<T>& lhs, const std::unique_ptr<T>& rhs) const {
    if (lhs == nullptr || rhs == nullptr) {
      return rhs == lhs;
    }
    return ::fidl::Equality<T>{}(*lhs, *rhs);
  }
};

template <>
struct Equality<UnknownBytes> {
  bool operator()(const UnknownBytes& lhs, const UnknownBytes& rhs) const {
    return ::fidl::Equality<std::vector<uint8_t>>{}(lhs.bytes, rhs.bytes);
  }
};

template <>
struct Equality<std::map<uint64_t, std::vector<uint8_t>>> {
  bool operator()(const std::map<uint64_t, std::vector<uint8_t>>& lhs,
                  const std::map<uint64_t, std::vector<uint8_t>>& rhs) const {
    return lhs == rhs;
  }
};

#ifdef __Fuchsia__
template <>
struct Equality<UnknownData> {
  bool operator()(const UnknownData& lhs, const UnknownData& rhs) const {
    return ::fidl::Equality<std::vector<uint8_t>>{}(lhs.bytes, rhs.bytes) &&
           ::fidl::Equality<std::vector<zx::handle>>{}(lhs.handles, rhs.handles);
  }
};

template <>
struct Equality<std::map<uint64_t, UnknownData>> {
  bool operator()(const std::map<uint64_t, UnknownData>& lhs,
                  const std::map<uint64_t, UnknownData>& rhs) const {
    if (lhs.size() != rhs.size()) {
      return false;
    }

    auto l = lhs.cbegin();
    auto r = rhs.cbegin();
    while (l != lhs.cend()) {
      if (!Equals(l->first, r->first) || !Equals(l->second, r->second)) {
        return false;
      }
      std::advance(l, 1);
      std::advance(r, 1);
    }
    return true;
  }
};
#endif

template <class T>
bool Equals(const T& lhs, const T& rhs) {
  return ::fidl::Equality<T>{}(lhs, rhs);
}

}  // namespace fidl

#endif  // LIB_FIDL_CPP_COMPARISON_H_
