/*
 * 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 <memory>
#include <string>
#include <nanobind/nanobind.h>
#include <nanobind/make_iterator.h>
#include <nanobind/stl/array.h>
#include <nanobind/stl/shared_ptr.h>
#include <nanobind/stl/string.h>

#include "py_serde.hpp"
#include "py_object_ostream.hpp"
#include "tuple_policy.hpp"

#include "theta_sketch.hpp"
#include "tuple_sketch.hpp"
#include "tuple_union.hpp"
#include "tuple_intersection.hpp"
#include "tuple_a_not_b.hpp"
#include "theta_jaccard_similarity_base.hpp"
#include "common_defs.hpp"

namespace nb = nanobind;

void init_tuple(nb::module_ &m) {
  using namespace datasketches;

  // generic tuple_policy:
  // * update sketch policy uses create_summary and update_summary
  // * set operation policies all use __call__
  nb::class_<tuple_policy, TuplePolicy>(m, "TuplePolicy",
     "An abstract base class for Tuple Policy objects. All custom policies must extend this class.")
    .def(nb::init())
    .def("create_summary", &tuple_policy::create_summary, "Creates a new Summary object")
    .def("update_summary", &tuple_policy::update_summary, nb::arg("summary"), nb::arg("update"),
         "applies the relevant policy to update the provided summary with the data in update.")
    .def("__call__", &tuple_policy::operator(), nb::arg("summary"), nb::arg("update"),
         "Similar to update_summary but allows a different implementation for set operations (union and intersection)")
  ;

  // potentially useful for debugging but not needed as a permanent
  // object type in the library
  /*
  nb::class_<tuple_policy_holder>(m, "TuplePolicyHolder")
    .def(nb::init<std::shared_ptr<tuple_policy>>(), nb::arg("policy"))
    .def("create", &tuple_policy_holder::create, "Creates a new Summary object")
    .def("update", &tuple_policy_holder::update, nb::arg("summary"), nb::arg("update"),
         "Updates the provided summary using the data in update")
  ;
  */

  using py_tuple_sketch = tuple_sketch<nb::object>;
  using py_update_tuple = update_tuple_sketch<nb::object, nb::object, tuple_policy_holder>;
  using py_compact_tuple = compact_tuple_sketch<nb::object>;
  using py_tuple_union = tuple_union<nb::object, tuple_policy_holder>;
  using py_tuple_intersection = tuple_intersection<nb::object, tuple_policy_holder>;
  using py_tuple_a_not_b = tuple_a_not_b<nb::object>;
  using py_tuple_jaccard_similarity = jaccard_similarity_base<tuple_union<nb::object, dummy_jaccard_policy>, tuple_intersection<nb::object, dummy_jaccard_policy>, pair_extract_key<uint64_t, nb::object>>;

  nb::class_<py_tuple_sketch>(m, "tuple_sketch", "An abstract base class for tuple sketches.")
    .def("__str__", &py_tuple_sketch::to_string,
         "Produces a string summary of the sketch")
    .def("to_string", &py_tuple_sketch::to_string, nb::arg("print_items")=false,
         "Produces a string summary of the sketch")
    .def("is_empty", &py_tuple_sketch::is_empty,
         "Returns True if the sketch is empty, otherwise False")
    .def("get_estimate", &py_tuple_sketch::get_estimate,
         "Estimate of the distinct count of the input stream")
    .def("get_upper_bound", static_cast<double (py_tuple_sketch::*)(uint8_t) const>(&py_tuple_sketch::get_upper_bound), nb::arg("num_std_devs"),
         "Returns an approximate upper bound on the estimate at standard deviations in {1, 2, 3}")
    .def("get_lower_bound", static_cast<double (py_tuple_sketch::*)(uint8_t) const>(&py_tuple_sketch::get_lower_bound), nb::arg("num_std_devs"),
         "Returns an approximate lower bound on the estimate at standard deviations in {1, 2, 3}")
    .def("is_estimation_mode", &py_tuple_sketch::is_estimation_mode,
         "Returns True if sketch is in estimation mode, otherwise False")
    .def_prop_ro("theta", &py_tuple_sketch::get_theta,
         "Theta (effective sampling rate) as a fraction from 0 to 1")
    .def_prop_ro("theta64", &py_tuple_sketch::get_theta64,
         "Theta as 64-bit value")
    .def_prop_ro("num_retained", &py_tuple_sketch::get_num_retained,
         "The number of items currently in the sketch")
    .def("get_seed_hash", [](const py_tuple_sketch& sk) { return sk.get_seed_hash(); }, // why does regular call not work??
         "Returns a hash of the seed used in the sketch")
    .def("is_ordered", &py_tuple_sketch::is_ordered,
         "Returns True if the sketch entries are sorted, otherwise False")
    .def("__iter__",
          [](const py_tuple_sketch& s) {
               return nb::make_iterator(nb::type<py_tuple_sketch>(),
               "tuple_iterator",
               s.begin(),
               s.end());
          }, nb::keep_alive<0,1>()
     )
    .def_prop_ro_static("DEFAULT_SEED", [](nb::object /* self */) { return DEFAULT_SEED; });
  ;

  nb::class_<py_compact_tuple, py_tuple_sketch>(m, "compact_tuple_sketch")
    .def(nb::init<const py_tuple_sketch&, bool>(), nb::arg("other"), nb::arg("ordered")=true,
         "Creates a compact_tuple_sketch from an existing tuple_sketch.\n\n"
         ":param other: a sourch tuple_sketch\n:type other: tuple_sketch\n"
         ":param ordered: whether the incoming sketch entries are sorted. Default True\n"
         ":type ordered: bool, optional"
         )
    .def(nb::init<const theta_sketch&, nb::object&>(), nb::arg("other"), nb::arg("summary"),
         "Creates a compact_tuple_sketch from a theta_sketch using a fixed summary value.\n\n"
         ":param other: a source theta sketch\n:type other: theta_sketch\n"
         ":param summary: a summary to use for every sketch entry\n:type summary: object"
         )
    .def("__copy__", [](const py_compact_tuple& sk){ return py_compact_tuple(sk); })
    .def(
        "serialize",
        [](const py_compact_tuple& sk, py_object_serde& serde) {
          auto bytes = sk.serialize(0, serde);
          return nb::bytes(reinterpret_cast<const char*>(bytes.data()), bytes.size());
        }, nb::arg("serde"),
        "Serializes the sketch into a bytes object"
    )
    .def_static(
        "deserialize",
        [](const nb::bytes& bytes, py_object_serde& serde, uint64_t seed) {
          return py_compact_tuple::deserialize(bytes.c_str(), bytes.size(), seed, serde);
        },
        nb::arg("bytes"), nb::arg("serde"), nb::arg("seed")=DEFAULT_SEED,
        "Reads a bytes object and returns the corresponding compact_tuple_sketch"
    );

  nb::class_<py_update_tuple, py_tuple_sketch>(m, "update_tuple_sketch")
    .def("__init__",
        [](py_update_tuple* sk, std::shared_ptr<tuple_policy> policy, uint8_t lg_k, double p, uint64_t seed) {
          tuple_policy_holder holder(policy);
          new (sk) py_update_tuple(py_update_tuple::builder(holder).set_lg_k(lg_k).set_p(p).set_seed(seed).build());
        },
        nb::arg("policy"), nb::arg("lg_k")=theta_constants::DEFAULT_LG_K, nb::arg("p")=1.0, nb::arg("seed")=DEFAULT_SEED,
        "Creates an update_tuple_sketch using the provided parameters\n\n"
        ":param policy: a policy to use when updating\n:type policy: TuplePolicy\n"
        ":param lg_k: base 2 logarithm of the maximum size of the sketch. Default 12.\n:type lg_k: int, optional\n"
        ":param p: an initial sampling rate to use. Default 1.0\n:type p: float, optional\n"
        ":param seed: the seed to use when hashing values\n:type seed: int, optional"
    )
    .def("__copy__", [](const py_update_tuple& sk){ return py_update_tuple(sk); })
    .def("update", static_cast<void (py_update_tuple::*)(int64_t, nb::object&)>(&py_update_tuple::update),
         nb::arg("datum"), nb::arg("value"),
         "Updates the sketch with the given integral item and summary value")
    .def("update", static_cast<void (py_update_tuple::*)(double, nb::object&)>(&py_update_tuple::update),
         nb::arg("datum"), nb::arg("value"),
         "Updates the sketch with the given floating point item and summary value")
    .def("update", static_cast<void (py_update_tuple::*)(const std::string&, nb::object&)>(&py_update_tuple::update),
         nb::arg("datum"), nb::arg("value"),
         "Updates the sketch with the given string item and summary value")
    .def("compact", &py_update_tuple::compact, nb::arg("ordered")=true,
         "Returns a compacted form of the sketch, optionally sorting it")
    .def("trim", &py_update_tuple::trim, "Removes retained entries in excess of the nominal size k (if any)")
    .def("reset", &py_update_tuple::reset, "Resets the sketch to the initial empty state")
  ;

  nb::class_<py_tuple_union>(m, "tuple_union")
    .def("__init__",
        [](py_tuple_union* u, std::shared_ptr<tuple_policy> policy, uint8_t lg_k, double p, uint64_t seed) {
          tuple_policy_holder holder(policy);
          new (u) py_tuple_union(py_tuple_union::builder(holder).set_lg_k(lg_k).set_p(p).set_seed(seed).build());
        },
        nb::arg("policy"), nb::arg("lg_k")=theta_constants::DEFAULT_LG_K, nb::arg("p")=1.0, nb::arg("seed")=DEFAULT_SEED,
        "Creates a tuple_union using the provided parameters\n\n"
        ":param policy: a policy to use when unioning entries\n:type policy: TuplePolicy\n"
        ":param lg_k: base 2 logarithm of the maximum size of the union. Default 12.\n:type lg_k: int, optional\n"
        ":param p: an initial sampling rate to use. Default 1.0\n:type p: float, optional\n"
        ":param seed: the seed to use when hashing values. Must match any sketch seeds.\n:type seed: int, optional"
    )
    .def("update", &py_tuple_union::update<const py_tuple_sketch&>, nb::arg("sketch"),
         "Updates the union with the given sketch")
    .def("get_result", &py_tuple_union::get_result, nb::arg("ordered")=true,
         "Returns the sketch corresponding to the union result")
    .def("reset", &py_tuple_union::reset,
         "Resets the sketch to the initial empty")
  ;

  nb::class_<py_tuple_intersection>(m, "tuple_intersection")
    .def("__init__",
        [](py_tuple_intersection* sk, std::shared_ptr<tuple_policy> policy, uint64_t seed) {
          tuple_policy_holder holder(policy);
          new (sk) py_tuple_intersection(seed, holder);
        },
        nb::arg("policy"), nb::arg("seed")=DEFAULT_SEED,
        "Creates a tuple_intersection using the provided parameters\n\n"
        ":param policy: a policy to use when intersecting entries\n:type policy: TuplePolicy\n"
        ":param seed: the seed to use when hashing values. Must match any sketch seeds\n:type seed: int, optional"
    )
    .def("update", &py_tuple_intersection::update<const py_tuple_sketch&>, nb::arg("sketch"),
         "Intersects the provided sketch with the current intersection state")
    .def("get_result", &py_tuple_intersection::get_result, nb::arg("ordered")=true,
         "Returns the sketch corresponding to the intersection result")
    .def("has_result", &py_tuple_intersection::has_result,
         "Returns True if the intersection has a valid result, otherwise False")
  ;

  nb::class_<py_tuple_a_not_b>(m, "tuple_a_not_b")
    .def(nb::init<uint64_t>(), nb::arg("seed")=DEFAULT_SEED,
        "Creates a tuple_a_not_b object\n\n"
        ":param seed: the seed to use when hashing values. Must match any sketch seeds.\n:type seed: int, optional"
    )
    .def(
        "compute",
        &py_tuple_a_not_b::compute<const py_tuple_sketch&, const py_tuple_sketch&>,
        nb::arg("a"), nb::arg("b"), nb::arg("ordered")=true,
        "Returns a sketch with the result of applying the A-not-B operation on the given inputs"
    )
  ;

  nb::class_<py_tuple_jaccard_similarity>(m, "tuple_jaccard_similarity",
     "An object to help compute Jaccard similarity between tuple sketches.")
    .def_static(
        "jaccard",
        [](const py_tuple_sketch& sketch_a, const py_tuple_sketch& sketch_b, uint64_t seed) {
          return py_tuple_jaccard_similarity::jaccard(sketch_a, sketch_b, seed);
        },
        nb::arg("sketch_a"), nb::arg("sketch_b"), nb::arg("seed")=DEFAULT_SEED,
        "Returns a list with {lower_bound, estimate, upper_bound} of the Jaccard similarity between sketches"
    )
    .def_static(
        "exactly_equal",
        &py_tuple_jaccard_similarity::exactly_equal<const py_tuple_sketch&, const py_tuple_sketch&>,
        nb::arg("sketch_a"), nb::arg("sketch_b"), nb::arg("seed")=DEFAULT_SEED,
        "Returns True if sketch_a and sketch_b are equivalent, otherwise False"
    )
    .def_static(
        "similarity_test",
        &py_tuple_jaccard_similarity::similarity_test<const py_tuple_sketch&, const py_tuple_sketch&>,
        nb::arg("actual"), nb::arg("expected"), nb::arg("threshold"), nb::arg("seed")=DEFAULT_SEED,
        "Tests similarity of an actual sketch against an expected sketch. Computes the lower bound of the Jaccard "
        "index J_{LB} of the actual and expected sketches. If J_{LB} >= threshold, then the sketches are considered "
        "to be similar with a confidence of 97.7% and returns True, otherwise False.")
    .def_static(
        "dissimilarity_test",
        &py_tuple_jaccard_similarity::dissimilarity_test<const py_tuple_sketch&, const py_tuple_sketch&>,
        nb::arg("actual"), nb::arg("expected"), nb::arg("threshold"), nb::arg("seed")=DEFAULT_SEED,
        "Tests dissimilarity of an actual sketch against an expected sketch. Computes the upper bound of the Jaccard "
        "index J_{UB} of the actual and expected sketches. If J_{UB} <= threshold, then the sketches are considered "
        "to be dissimilar with a confidence of 97.7% and returns True, otherwise False."
    )
  ;
}
