/*
 * 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 <fstream>
#include <quantiles_sketch.hpp>

namespace datasketches {

// assume the binary sketches for this test have been generated by datasketches-java code
// in the subdirectory called "java" in the root directory of this project
static std::string testBinaryInputPath = std::string(TEST_BINARY_INPUT_PATH) + "../../java/";

TEST_CASE("quantiles double", "[serde_compat]") {
  unsigned n_arr[] = {0, 1, 10, 100, 1000, 10000, 100000, 1000000};
  for (const unsigned n: n_arr) {
    std::ifstream is;
    is.exceptions(std::ios::failbit | std::ios::badbit);
    is.open(testBinaryInputPath + "quantiles_double_n" + std::to_string(n) + ".sk", std::ios::binary);
    auto sketch = quantiles_sketch<double>::deserialize(is);
    REQUIRE(sketch.is_empty() == (n == 0));
    REQUIRE(sketch.is_estimation_mode() == (n > quantiles_constants::DEFAULT_K));
    REQUIRE(sketch.get_n() == n);
    if (n > 0) {
      REQUIRE(sketch.get_min_item() == 1.0);
      REQUIRE(sketch.get_max_item() == static_cast<double>(n));
      uint64_t weight = 0;
      for (const auto pair: sketch) {
        REQUIRE(pair.first >= sketch.get_min_item());
        REQUIRE(pair.first <= sketch.get_max_item());
        weight += pair.second;
      }
      REQUIRE(weight == sketch.get_n());
    }
  }
}

struct string_as_number_less {
  bool operator()(const std::string& a, const std::string& b) const {
    return std::stoi(a) < std::stoi(b);
  }
};

TEST_CASE("quantiles string", "[serde_compat]") {
  unsigned n_arr[] = {0, 1, 10, 100, 1000, 10000, 100000, 1000000};
  for (const unsigned n: n_arr) {
    std::ifstream is;
    is.exceptions(std::ios::failbit | std::ios::badbit);
    is.open(testBinaryInputPath + "quantiles_string_n" + std::to_string(n) + ".sk", std::ios::binary);
    auto sketch = quantiles_sketch<std::string, string_as_number_less>::deserialize(is);
    REQUIRE(sketch.is_empty() == (n == 0));
    REQUIRE(sketch.is_estimation_mode() == (n > quantiles_constants::DEFAULT_K));
    REQUIRE(sketch.get_n() == n);
    if (n > 0) {
      REQUIRE(sketch.get_min_item() == "1");
      REQUIRE(sketch.get_max_item() == std::to_string(n));
      uint64_t weight = 0;
      for (const auto pair: sketch) {
        REQUIRE(std::stoi(pair.first) >= std::stoi(sketch.get_min_item()));
        REQUIRE(std::stoi(pair.first) <= std::stoi(sketch.get_max_item()));
        weight += pair.second;
      }
      REQUIRE(weight == sketch.get_n());
    }
  }
}

} /* namespace datasketches */
