# 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.

import unittest
from datasketches import req_ints_sketch, req_floats_sketch, req_items_sketch, PyStringsSerDe
import numpy as np

class reqTest(unittest.TestCase):
    def test_req_example(self):
      k = 12
      n = 2 ** 20

      # create a sketch and inject ~1 million N(0,1) points as an array and as a single item
      req = req_floats_sketch(k, True) # high rank accuracy
      req.update(np.random.normal(size=n-1))
      req.update(0.0)

      # 0 should be near the median
      self.assertAlmostEqual(0.5, req.get_rank(0.0), delta=0.045)
      
      # the median should be near 0
      self.assertAlmostEqual(0.0, req.get_quantile(0.5), delta=0.045)

      # we also track the min/max independently from the rest of the data
      # which lets us know the full observed data range
      self.assertLessEqual(req.get_min_value(), req.get_quantile(0.01))
      self.assertLessEqual(0.0, req.get_rank(req.get_min_value()))
      self.assertGreaterEqual(req.get_max_value(), req.get_quantile(0.99))
      self.assertGreaterEqual(1.0, req.get_rank(req.get_max_value()))

      # we can also extract a list of values at a time,
      # here the values should give us something close to [-2, -1, 0, 1, 2].
      # then get the CDF, which will return something close to
      # the original values used in get_quantiles()
      # finally, can check the normalized rank error bound
      pts = req.get_quantiles([0.0228, 0.1587, 0.5, 0.8413, 0.9772])
      cdf = req.get_cdf(pts)  # include 1.0 at end to account for all probability mass
      self.assertEqual(len(cdf), len(pts)+1)

      # For relative error quantiles, the error depends on the actual rank
      # so we need to use that to detemrine the bounds
      est = req.get_rank(0.999, True)
      lb = req.get_rank_lower_bound(est, 1)
      ub = req.get_rank_upper_bound(est, 1)
      self.assertLessEqual(lb, est)
      self.assertLessEqual(est, ub)

      # and a few basic queries about the sketch
      self.assertFalse(req.is_empty())
      self.assertTrue(req.is_estimation_mode())
      self.assertEqual(req.get_n(), n)
      self.assertLess(req.get_num_retained(), n)
      self.assertEqual(req.get_k(), k)

      # merging itself will double the number of items the sketch has seen
      req_copy = req_floats_sketch(req)
      req.merge(req_copy)
      self.assertEqual(req.get_n(), 2*n)

      # we can then serialize and reconstruct the sketch
      req_bytes = req.serialize()
      new_req = req_floats_sketch.deserialize(req_bytes)
      self.assertEqual(req.get_num_retained(), new_req.get_num_retained())
      self.assertEqual(req.get_min_value(), new_req.get_min_value())
      self.assertEqual(req.get_max_value(), new_req.get_max_value())
      self.assertEqual(req.get_quantile(0.7), new_req.get_quantile(0.7))
      self.assertEqual(req.get_rank(0.0), new_req.get_rank(0.0))

      total_weight = 0
      for tuple in req:
        item = tuple[0]
        weight = tuple[1]
        total_weight = total_weight + weight
      self.assertEqual(total_weight, req.get_n())

    def test_req_ints_sketch(self):
        k = 100
        n = 10
        req = req_ints_sketch(k)
        for i in range(0, n):
          req.update(i)

        self.assertEqual(req.get_min_value(), 0)
        self.assertEqual(req.get_max_value(), n-1)
        self.assertEqual(req.get_n(), n)
        self.assertFalse(req.is_empty())
        self.assertFalse(req.is_estimation_mode()) # n < k
        self.assertEqual(req.get_k(), k)

        pmf = req.get_pmf([round(n/2)])
        self.assertIsNotNone(pmf)
        self.assertEqual(len(pmf), 2)

        cdf = req.get_cdf([round(n/2)])
        self.assertIsNotNone(cdf)
        self.assertEqual(len(cdf), 2)

        self.assertEqual(req.get_quantile(0.5), round(n/2))
        quants = req.get_quantiles([0.25, 0.5, 0.75])
        self.assertIsNotNone(quants)
        self.assertEqual(len(quants), 3)

        self.assertEqual(req.get_rank(round(n/2)), 0.5)

        # merge self
        req_copy = req_ints_sketch(req)
        req.merge(req_copy)
        self.assertEqual(req.get_n(), 2 * n)

        sk_bytes = req.serialize()
        self.assertTrue(isinstance(req_ints_sketch.deserialize(sk_bytes), req_ints_sketch))

    def test_req_floats_sketch(self):
      # already tested floats with LRA so just check that HRA works
      k = 75
      req = req_floats_sketch(k, False) # low rank accuracy
      self.assertTrue(req.is_empty())
      self.assertFalse(req.is_hra())

    def test_req_items_sketch(self):
      # most functionality has been tested, but we need to ensure objects and sorting work
      # as well as serialization
      k = 100
      n = 2 ** 16

      # create a sketch and inject enough points to force compaction
      req = req_items_sketch(k)
      for i in range(0, n):
        req.update(str(i))
      
      req_copy = req_items_sketch(req)
      req.merge(req_copy)
      self.assertEqual(req.get_n(), 2 * n)
      
      req_bytes = req.serialize(PyStringsSerDe())
      new_req = req_items_sketch.deserialize(req_bytes, PyStringsSerDe())
      self.assertEqual(req.get_num_retained(), new_req.get_num_retained())
      self.assertEqual(req.get_min_value(), new_req.get_min_value())
      self.assertEqual(req.get_max_value(), new_req.get_max_value())
      self.assertEqual(req.get_quantile(0.7), new_req.get_quantile(0.7))
      self.assertEqual(req.get_rank(str(n/4)), new_req.get_rank(str(n/4)))


if __name__ == '__main__':
    unittest.main()
