/*
 * Copyright (c) 2020-2023, NVIDIA CORPORATION. All rights reserved.
 *
 * This source code and/or documentation ("Licensed Deliverables") are
 * subject to NVIDIA intellectual property rights under U.S. and
 * international Copyright laws.
 */

#pragma once

#include <utils/cudart.hpp>

#include <catch2/catch.hpp>

#include <algorithm>
#include <map>
#include <sstream>
#include <string>
#include <vector>

namespace cugraph::ops::catch2 {

/**
 * @brief Custom matcher class for checking uniqueness of a vector
 *
 * @tparam DataT data type of the arrays
 */
template <typename DataT>
class is_unique_t : public Catch::MatcherBase<std::vector<DataT>> {
 public:
  bool match(std::vector<DataT> const& h_array) const override
  {
    std::map<DataT, int> h_map;
    for (auto& elem : h_array) {
      auto itr = h_map.find(elem);
      if (itr == h_map.end()) {
        h_map[elem] = 1;
      } else {
        ++(itr->second);
      }
    }
    return std::all_of(h_map.begin(), h_map.end(), [](const auto& itr) { return itr.second == 1; });
  }

  [[nodiscard]] std::string describe() const override { return "is_unique"; }
};  // class is_unique_t

/**
 * @brief Builder function for the uniqueness checker
 *
 * @tparam DataT data type of the arrays
 *
 * @return the matcher object
 */
template <typename DataT>
is_unique_t<DataT> is_unique()
{
  return is_unique_t<DataT>();
}

}  // namespace cugraph::ops::catch2
