/*
 * 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")
    .def(nb::init())
    .def("create_summary", &tuple_policy::create_summary)
    .def("update_summary", &tuple_policy::update_summary, nb::arg("summary"), nb::arg("update"))
    .def("__call__", &tuple_policy::operator(), nb::arg("summary"), nb::arg("update"))
  ;

  // 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")
    .def("__str__", &py_tuple_sketch::to_string, nb::arg("print_items")=false,
         "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("get_theta", &py_tuple_sketch::get_theta,
         "Returns theta (effective sampling rate) as a fraction from 0 to 1")
    .def("get_theta64", &py_tuple_sketch::get_theta64,
         "Returns theta as 64-bit value")
    .def("get_num_retained", &py_tuple_sketch::get_num_retained,
         "Returns 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_compact_tuple&>(), nb::arg("other"))
    .def(nb::init<const py_tuple_sketch&, bool>(), nb::arg("other"), nb::arg("ordered")=true)
    .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.")
    .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
    )
    .def(nb::init<const py_update_tuple&>())
    .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
    )
    .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)
    .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)
    .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")
    .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."
    )
  ;
}
