/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */

#include <catch2/catch.hpp>

#include "cpc_union.hpp"

#include <stdexcept>

namespace datasketches {

static const double RELATIVE_ERROR_FOR_LG_K_11 = 0.02;

TEST_CASE("cpc union: lg k limits", "[cpc_union]") {
  cpc_union u1(cpc_constants::MIN_LG_K); // this should work
  cpc_union u2(cpc_constants::MAX_LG_K); // this should work
  REQUIRE_THROWS_AS(cpc_union(cpc_constants::MIN_LG_K - 1), std::invalid_argument);
  REQUIRE_THROWS_AS(cpc_union(cpc_constants::MAX_LG_K + 1), std::invalid_argument);
}

TEST_CASE("cpc union: empty", "[cpc_union]") {
  cpc_union u(11);
  auto s = u.get_result();
  REQUIRE(s.is_empty());
  REQUIRE(s.get_estimate() == 0.0);
}

TEST_CASE("cpc union: copy", "[cpc_union]") {
  cpc_sketch s(11);
  s.update(1);
  cpc_union u1(11);
  u1.update(s);

  cpc_union u2 = u1; // copy constructor
  auto s1 = u2.get_result();
  REQUIRE_FALSE(s1.is_empty());
  REQUIRE(s1.get_estimate() == Approx(1).margin(RELATIVE_ERROR_FOR_LG_K_11));
  s.update(2);
  u2.update(s);
  u1 = u2; // operator=
  auto s2 = u1.get_result();
  REQUIRE_FALSE(s2.is_empty());
  REQUIRE(s2.get_estimate() == Approx(2).margin(2 * RELATIVE_ERROR_FOR_LG_K_11));
}

TEST_CASE("cpc union: custom seed", "[cpc_union]") {
  cpc_sketch s(11, 123);

  s.update(1);
  s.update(2);
  s.update(3);

  cpc_union u1(11, 123);
  u1.update(s);
  auto r = u1.get_result();
  REQUIRE_FALSE(r.is_empty());
  REQUIRE(r.get_estimate() == Approx(3).margin(3 * RELATIVE_ERROR_FOR_LG_K_11));

  // incompatible seed
  cpc_union u2(11, 234);
  REQUIRE_THROWS_AS(u2.update(s), std::invalid_argument);
}

TEST_CASE("cpc union: large", "[cpc_union]") {
  int key = 0;
  cpc_sketch s(11);
  cpc_union u(11);
  for (int i = 0; i < 1000; i++) {
    cpc_sketch tmp(11);
    for (int j = 0; j < 10000; j++) {
      s.update(key);
      tmp.update(key);
      key++;
    }
    u.update(tmp);
  }
  cpc_sketch r = u.get_result();
  REQUIRE(r.get_num_coupons() == s.get_num_coupons());
  REQUIRE(r.get_estimate() == Approx(s.get_estimate()).margin(s.get_estimate() * RELATIVE_ERROR_FOR_LG_K_11));
}

TEST_CASE("cpc union: reduce k empty", "[cpc_union]") {
  cpc_sketch s(11);
  for (int i = 0; i < 10000; i++) s.update(i);
  cpc_union u(12);
  u.update(s);
  cpc_sketch r = u.get_result();
  REQUIRE(r.get_lg_k() == 11);
  REQUIRE(r.get_estimate() == Approx(10000).margin(10000 * RELATIVE_ERROR_FOR_LG_K_11));
}

TEST_CASE("cpc union: reduce k sparse", "[cpc_union]") {
  cpc_union u(12);

  cpc_sketch s12(12);
  for (int i = 0; i < 100; i++) s12.update(i);
  u.update(s12);

  cpc_sketch s11(11);
  for (int i = 0; i < 1000; i++) s11.update(i);
  u.update(s11);

  cpc_sketch r = u.get_result();
  REQUIRE(r.get_lg_k() == 11);
  REQUIRE(r.get_estimate() == Approx(1000).margin(1000 * RELATIVE_ERROR_FOR_LG_K_11));
}

TEST_CASE("cpc union: reduce k window", "[cpc_union]") {
  cpc_union u(12);

  cpc_sketch s12(12);
  for (int i = 0; i < 500; i++) s12.update(i);
  u.update(s12);

  cpc_sketch s11(11);
  for (int i = 0; i < 1000; i++) s11.update(i);
  u.update(s11);

  cpc_sketch r = u.get_result();
  REQUIRE(r.get_lg_k() == 11);
  REQUIRE(r.get_estimate() == Approx(1000).margin(1000 * RELATIVE_ERROR_FOR_LG_K_11));
}

TEST_CASE("cpc union: moving update", "[cpc_union]") {
  cpc_union u(11);
  cpc_sketch s(11);
  for (int i = 0; i < 100; i++) s.update(i); // sparse
  u.update(std::move(s));
  cpc_sketch r = u.get_result();
  REQUIRE(r.get_estimate() == Approx(100).margin(100 * RELATIVE_ERROR_FOR_LG_K_11));
}



} /* namespace datasketches */
