/*
 * 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 <sstream>
#include <pybind11/pybind11.h>

#include "theta_sketch.hpp"
#include "theta_union.hpp"
#include "theta_intersection.hpp"
#include "theta_a_not_b.hpp"
#include "common_defs.hpp"


namespace py = pybind11;

namespace datasketches {
namespace python {

update_theta_sketch update_theta_sketch_factory(uint8_t lg_k, double p, uint64_t seed) {
  update_theta_sketch::builder builder;
  builder.set_lg_k(lg_k);
  builder.set_p(p);
  builder.set_seed(seed);
  return builder.build();
}

theta_union theta_union_factory(uint8_t lg_k, double p, uint64_t seed) {
  theta_union::builder builder;
  builder.set_lg_k(lg_k);
  builder.set_p(p);
  builder.set_seed(seed);
  return builder.build();
}

theta_sketch* theta_sketch_deserialize(py::bytes skBytes, uint64_t seed) {
  std::string skStr = skBytes; // implicit cast  
  return theta_sketch::deserialize(skStr.c_str(), skStr.length(), seed).release();
}

py::object theta_sketch_serialize(const theta_sketch& sk) {
  auto serResult = sk.serialize();
  return py::bytes((char*)serResult.data(), serResult.size());
}

uint16_t theta_sketch_get_seed_hash(const theta_sketch& sk) {
  return sk.get_seed_hash();
}

update_theta_sketch update_theta_sketch_deserialize(py::bytes skBytes, uint64_t seed) {
  std::string skStr = skBytes; // implicit cast  
  return update_theta_sketch::deserialize(skStr.c_str(), skStr.length(), seed);
}

compact_theta_sketch compact_theta_sketch_deserialize(py::bytes skBytes, uint64_t seed) {
  std::string skStr = skBytes; // implicit cast  
  return compact_theta_sketch::deserialize(skStr.c_str(), skStr.length(), seed);
}

}
}

namespace dspy = datasketches::python;

void init_theta(py::module &m) {
  using namespace datasketches;

  py::class_<theta_sketch>(m, "theta_sketch")
    .def("serialize", &dspy::theta_sketch_serialize,
         "Serializes the sketch into a bytes object")
    .def_static("deserialize", &dspy::theta_sketch_deserialize, py::arg("bytes"), py::arg("seed")=DEFAULT_SEED,
         "Reads a bytes object and returns the corresponding cpc_sketch")
    .def("__str__", &theta_sketch::to_string, py::arg("print_items")=false,
         "Produces a string summary of the sketch")
    .def("to_string", &theta_sketch::to_string, py::arg("print_items")=false,
         "Produces a string summary of the sketch")
    .def("is_empty", &theta_sketch::is_empty,
         "Returns True if the sketch is empty, otherwise Dalse")
    .def("get_estimate", &theta_sketch::get_estimate,
         "Estimate of the distinct count of the input stream")
    .def("get_upper_bound", &theta_sketch::get_upper_bound, py::arg("num_std_devs"),
         "Returns an approximate upper bound on the estimate at standard deviations in {1, 2, 3}")
    .def("get_lower_bound", &theta_sketch::get_lower_bound, py::arg("num_std_devs"),
         "Returns an approximate lower bound on the estimate at standard deviations in {1, 2, 3}")
    .def("is_estimation_mode", &theta_sketch::is_estimation_mode,
         "Returns True if sketch is in estimation mode, otherwise False")
    .def("get_theta", &theta_sketch::get_theta,
         "Returns theta (effective sampling rate) as a fraction from 0 to 1")
    .def("get_num_retained", &theta_sketch::get_num_retained,
         "Retunrs the number of items currently in the sketch")
    .def("get_seed_hash", &dspy::theta_sketch_get_seed_hash,
         "Returns a hash of the seed used in the sketch")
    .def("is_ordered", &theta_sketch::is_ordered,
         "Returns True if the sketch entries are sorted, otherwise False")
  ;

  py::class_<update_theta_sketch, theta_sketch>(m, "update_theta_sketch")
    .def(py::init(&dspy::update_theta_sketch_factory),
         py::arg("lg_k")=update_theta_sketch::builder::DEFAULT_LG_K, py::arg("p")=1.0, py::arg("seed")=DEFAULT_SEED)
    .def(py::init<const update_theta_sketch&>())
    .def("update", (void (update_theta_sketch::*)(int64_t)) &update_theta_sketch::update, py::arg("datum"),
         "Updates the sketch with the given integral value")
    .def("update", (void (update_theta_sketch::*)(double)) &update_theta_sketch::update, py::arg("datum"),
         "Updates the sketch with the given floating point value")
    .def("update", (void (update_theta_sketch::*)(const std::string&)) &update_theta_sketch::update, py::arg("datum"),
         "Updates the sketch with the given string")
    .def("compact", &update_theta_sketch::compact, py::arg("ordered")=true,
         "Returns a compacted form of the sketch, optionally sorting it")
    .def_static("deserialize", &dspy::update_theta_sketch_deserialize,
        py::arg("bytes"), py::arg("seed")=DEFAULT_SEED,
        "Reads a bytes object and returns the corresponding update_theta_sketch")
  ;

  py::class_<compact_theta_sketch, theta_sketch>(m, "compact_theta_sketch")
    .def(py::init<const compact_theta_sketch&>())
    .def(py::init<const theta_sketch&, bool>())
    .def_static("deserialize", &dspy::compact_theta_sketch_deserialize,
        py::arg("bytes"), py::arg("seed")=DEFAULT_SEED,
        "Reads a bytes object and returns the corresponding update_theta_sketch")        
  ;

  py::class_<theta_union>(m, "theta_union")
    .def(py::init(&dspy::theta_union_factory),
         py::arg("lg_k")=update_theta_sketch::builder::DEFAULT_LG_K, py::arg("p")=1.0, py::arg("seed")=DEFAULT_SEED)
    .def("update", &theta_union::update, py::arg("sketch"),
         "Updates the union with the given sketch")
    .def("get_result", &theta_union::get_result, py::arg("ordered")=true,
         "Returns the sketch corresponding to the union result")
  ;

  py::class_<theta_intersection>(m, "theta_intersection")
    .def(py::init<uint64_t>(), py::arg("seed")=DEFAULT_SEED)
    .def(py::init<const theta_intersection&>())
    .def("update", &theta_intersection::update, py::arg("sketch"),
         "Intersections the provided sketch with the current intersection state")
    .def("get_result", &theta_intersection::get_result, py::arg("ordered")=true,
         "Returns the sketch corresponding to the intersection result")
    .def("has_result", &theta_intersection::has_result,
         "Returns True if the intersection has a valid result, otherwisel False")
  ;

  py::class_<theta_a_not_b>(m, "theta_a_not_b")
    .def(py::init<uint64_t>(), py::arg("seed")=DEFAULT_SEED)
    .def("compute", &theta_a_not_b::compute, py::arg("a"), py::arg("b"), py::arg("ordered")=true,
         "Returns a sketch with the reuslt of appying the A-not-B operation on the given inputs")
  ;
}
