/*
 * 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 <cmath>
#include <sstream>
#include <fstream>

#include <quantiles_sketch.hpp>
#include <serde.hpp>
#include <test_allocator.hpp>

namespace datasketches {

#ifdef TEST_BINARY_INPUT_PATH
static std::string testBinaryInputPath = TEST_BINARY_INPUT_PATH;
#else
static std::string testBinaryInputPath = "test/";
#endif

// these tests are for compatibility with old versions of Java's
// Quantiles sketch, which is only for doubles.
// 
// typical usage would be just quantiles_sketch<double>, but here we use test_allocator
using quantiles_double_sketch = quantiles_sketch<double, std::less<double>, test_allocator<double>>;

static void quantiles_decode_and_check(uint16_t k, uint64_t n, const std::string& version,
                                       double expected_median) {
  const double median_rank = 0.5;

  std::ostringstream filestr;
  filestr << "Qk" << k << "_n" << n << "_v" << version << ".sk";
  // as stream
  std::ifstream is;
  is.exceptions(std::ios::failbit | std::ios::badbit);
  std::string filename = testBinaryInputPath + filestr.str();

  is.open(filename, std::ios::binary);
  auto sketch_stream = quantiles_double_sketch::deserialize(is, serde<double>(), 0);
  is.close();
  REQUIRE(sketch_stream.get_quantile(median_rank) == expected_median);

  // as bytes
  std::ifstream infile(filename, std::ios::binary);
  std::vector<char> bytes(
    (std::istreambuf_iterator<char>(infile)),
    (std::istreambuf_iterator<char>()));
  infile.close();
  auto sketch_bytes = quantiles_double_sketch::deserialize(bytes.data(), bytes.size(), serde<double>(), 0);
  REQUIRE(sketch_bytes.get_quantile(median_rank) == expected_median);
}

TEST_CASE("quantiles compatibility", "[quantiles_compatibility]") {

  // setup
  test_allocator_total_bytes = 0;

  SECTION("Qk128_n50_v0.3.0.sk") {
    // file: Qk128_n50_v0.3.0.sk
    // median: 26.0
    quantiles_decode_and_check(128, 50, "0.3.0", 26.0);
  }

  SECTION("Qk128_n1000_v0.3.0.sk") {
    // file: Qk128_n1000_v0.3.0.sk
    // median: 501.0
    quantiles_decode_and_check(128, 1000, "0.3.0", 501.0);
  }

  SECTION("Qk128_n50_v0.6.0.sk") {
    // file: Qk128_n50_v0.6.0.sk
    // median: 26.0
    quantiles_decode_and_check(128, 50, "0.6.0", 26.0);
  }

  SECTION("Qk128_n1000_v0.6.0.sk") {
    // file: Qk128_n1000_v0.6.0.sk
    // median: 501.0
    quantiles_decode_and_check(128, 1000, "0.6.0", 501.0);
  }

  SECTION("Qk128_n50_v0.8.0.sk") {
    // file: Qk128_n50_v0.8.0.sk
    // median: 26.0
    quantiles_decode_and_check(128, 50, "0.8.0", 26.0);
  }

  SECTION("Qk128_n1000_v0.8.0.sk") {
    // file: Qk128_n1000_v0.8.0.sk
    // median: 501.0
    quantiles_decode_and_check(128, 1000, "0.8.0", 501.0);
  }

  SECTION("Qk128_n50_v0.8.3.sk") {
    // file: Qk128_n50_v0.8.3.sk
    // median: 26.0
    quantiles_decode_and_check(128, 50, "0.8.3", 26.0);
  }

  SECTION("Qk128_n1000_v0.8.3.sk") {
    // file: Qk128_n1000_v0.8.3.sk
    // median: 501.0
    quantiles_decode_and_check(128, 1000, "0.8.3", 501.0);
  }

  // cleanup
  if (test_allocator_total_bytes != 0) {
    REQUIRE(test_allocator_total_bytes == 0);
  }

}

} /* namespace datasketches */
