"""Pruebas de lab/metrics.py, que se saltan mientras quede algún TODO."""
import csv
import os
import statistics
import unittest

from netlab import HERE, load_metrics


def read_trace(name):
    rows = []
    with open(os.path.join(HERE, "lab", name), encoding="utf-8") as file:
        for row in csv.DictReader(file):
            ssthresh = int(row["ssthresh_segments"]) if row["ssthresh_segments"] else None
            rows.append((float(row["t_s"]), int(row["cwnd_segments"]), ssthresh,
                         float(row["rtt_ms"])))
    return rows


class Metrics(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.metrics = load_metrics()

    def test_bdp(self):
        self.assertAlmostEqual(self.metrics.bdp_packets(50, 40), 166.67, places=1)
        self.assertAlmostEqual(self.metrics.bdp_packets(100, 50), 416.67, places=1)
        self.assertAlmostEqual(self.metrics.bdp_packets(100, 50, packet_bytes=1000), 625, places=1)

    def test_queue_delay(self):
        self.assertAlmostEqual(self.metrics.queue_delay_ms(250_000, 50), 40, places=3)
        self.assertAlmostEqual(self.metrics.queue_delay_ms(1_000_000, 8), 1000, places=3)

    def test_mathis(self):
        self.assertAlmostEqual(self.metrics.mathis_mbps(1448, 40, 0.01), 3.55, places=1)
        # Cuadruplicar la pérdida reduce el throughput a la mitad, y lo mismo duplicar el RTT.
        self.assertAlmostEqual(self.metrics.mathis_mbps(1448, 40, 0.04),
                               self.metrics.mathis_mbps(1448, 80, 0.01), places=6)

    def test_decrease_ratios_on_a_small_trace(self):
        rows = [(0, 10, None, 40), (1, 100, None, 40), (2, 50, 50, 40), (3, 80, 50, 40),
                (4, 40, 40, 40), (5, 41, 40, 40)]
        self.assertEqual(self.metrics.decrease_ratios(rows), [0.5, 0.5])

    def test_the_sample_of_the_event_counts_for_the_peak(self):
        rows = [(0, 10, None, 40), (1, 100, 60, 40)]
        self.assertEqual(self.metrics.decrease_ratios(rows), [0.6])

    def test_no_events_no_ratios(self):
        self.assertEqual(self.metrics.decrease_ratios([(0, 10, None, 40), (1, 20, None, 40)]), [])

    def test_real_traces_show_the_two_factors(self):
        reno = self.metrics.decrease_ratios(read_trace("trace-reno.csv"))
        cubic = self.metrics.decrease_ratios(read_trace("trace-cubic.csv"))
        self.assertGreater(len(reno), 2)
        self.assertGreater(len(cubic), 2)
        self.assertLess(statistics.median(reno), 0.62)
        self.assertGreater(statistics.median(cubic), 0.62)


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