import unittest

from networks.QoS import QoS
from networks.connections.mathematical_connections import FunctionalDegradation

from networks.slicing import SliceConceptualGraph
from utils.location import Location


class TestBaseStationLinear(unittest.TestCase):
    def setUp(self):
        self.name = "network"
        self.wireless_connection_type = "LinearDegradation"
        self.backhaul_qos = {'latency': {'delay': '3.0ms', 'deviation': '1.0ms'}, 'bandwidth': '100.0mbps',
                             'error_rate': '1.0%'}
        self.midhaul_qos = {'latency': {'delay': '3.0ms', 'deviation': '1.0ms'}, 'bandwidth': '100.0mbps',
                             'error_rate': '1.0%'}
        self.parameters = dict(
            best_qos={'latency': {'delay': '5.0ms', 'deviation': '2.0ms'}, 'bandwidth': '10.0mbps',
                      'error_rate': '1.0%'},
            worst_qos={'latency': {'delay': '100.0ms', 'deviation': '20.0ms'}, 'bandwidth': '5.0mbps',
                       'error_rate': '2.0%'}, radius="5km")
        self.network = SliceConceptualGraph(self.name, self.midhaul_qos, self.backhaul_qos, self.parameters)

    def test_creation(self):
        self.assertEqual(self.network.get_name(), "network")

    def test_get_empty_nodes(self):
        self.assertEqual(self.network.get_nodes(), {})

    def test_add_node(self):
        name, lat, lon = 'node', 33, 40
        lat, lon = 33, 40
        self.network.set_RU(lat, lon)
        self.network.add_node(name, lat, lon)
        self.assertEqual(self.network.get_nodes(), {'node': Location(lat, lon)})
        with self.assertRaises(SliceConceptualGraph.NetworkSliceException):
            self.network.add_node('node', 33, 40)

    def test_get_empty_RUs(self):
        self.assertEqual(self.network.get_RUs(), {})

    def test_set_basetastion(self):
        lat, lon = 33, 40
        self.network.set_RU(lat, lon)
        self.assertEqual(self.network.get_RUs(), {f'{lat}-{lon}': Location(lat, lon)})
        with self.assertRaises(SliceConceptualGraph.NetworkSliceException):
            self.network.set_RU(lat, lon)

    def test_constructor(self):
        with self.assertRaises(FunctionalDegradation.FunctionDegradationNetworkException):
            SliceConceptualGraph('test', {}, {}, {})
            SliceConceptualGraph('test', self.midhaul_qos, {}, {})
            SliceConceptualGraph('test', {}, self.backhaul_qos, {})
            SliceConceptualGraph('test', {}, {}, self.parameters)

    def test_get_qos(self):
        self.assertEqual(self.network.get_backhaul(), QoS(self.backhaul_qos))

    def test_set_qos(self):
        self.network.set_backhaul(QoS.minimum_qos_dict)
        self.assertEqual(self.network.get_backhaul(), QoS(QoS.minimum_qos_dict))

    def test_qos_from_distance(self):
        self.assertEqual(self.network.get_qos_from(5).get_formated_qos(), self.parameters.get('worst_qos'))
        self.assertEqual(self.network.get_qos_from(0.0).get_formated_qos(), self.parameters.get('best_qos'))

    def test_get_node_location(self):
        lat, lon = 33, 40
        self.network.set_RU(lat, lon)
        self.network.add_node('test', 10, 10)
        self.assertEqual(self.network.get_node_location('test2'), None)
        self.assertEqual(self.network.get_node_location('test'), Location(10, 10))

    def test_has_to_pass_through_backhaul(self):
        self.network.set_RU(10, 10)
        self.network.set_RU(20, 20)

        self.network.add_node('source1', 10, 10)
        self.network.add_node('destination1', 10, 10)
        self.network.add_node('destination2', 20, 20)

    def test_set_RUs(self):
        self.network.set_RUs([{'lat': 10, 'lon': 10}, {'lat': 5, 'lon': 5}])
        self.assertEqual(self.network.get_RUs(),
                         {'10-10': Location(**{'lat': 10, 'lon': 10}), '5-5': Location(**{'lat': 5, 'lon': 5})})
        lat, lon = 33, 40
        self.network.set_RU(lat, lon)
        with self.assertRaises(SliceConceptualGraph.NetworkSliceException):
            self.network.set_RUs([{'lat': 10, 'lon': 10}, {'lat': 5, 'lon': 5}])

    def test_set_node_location(self):
        lat, lon = 33, 40
        self.network.set_RU(lat, lon)
        self.network.add_node('destination1', 10, 10)
        self.network.set_node_location('destination1', 20, 20)
        self.assertEqual(self.network.get_node_location('destination1'), Location(20, 20))
        with self.assertRaises(Location.LocationException):
            self.network.set_node_location('destination1', 'test', 20)
        with self.assertRaises(Location.LocationException):
            self.network.set_node_location('destination1', 20, 'test')


class TestBaseLog2Degradation(unittest.TestCase):
    def setUp(self):
        self.name = "network"
        self.wireless_connection_type = "Log2Degradation"
        self.midhaul_qos = {'latency': {'delay': '3.0ms', 'deviation': '1.0ms'}, 'bandwidth': '100.0mbps',
                             'error_rate': '1.0%'}
        self.backhaul_qos = {'latency': {'delay': '3.0ms', 'deviation': '1.0ms'}, 'bandwidth': '100.0mbps',
                             'error_rate': '1.0%'}
        self.parameters = dict(
            best_qos={'latency': {'delay': '5.0ms', 'deviation': '2.0ms'}, 'bandwidth': '10.0mbps',
                      'error_rate': '1.0%'},
            worst_qos={'latency': {'delay': '100.0ms', 'deviation': '20.0ms'}, 'bandwidth': '5.0mbps',
                       'error_rate': '2.0%'}, radius="5km")
        self.network = SliceConceptualGraph(self.name, self.midhaul_qos, self.backhaul_qos, self.parameters)

    def test_creation(self):
        self.assertEqual(self.network.get_name(), "network")

    def test_get_empty_nodes(self):
        self.assertEqual(self.network.get_nodes(), {})

    def test_add_node(self):
        name, lat, lon = 'node', 33, 40
        with self.assertRaises(SliceConceptualGraph.NetworkSliceException):
            self.network.add_node(name, lat, lon)
        self.network.set_RU(33, 40, 0)
        self.network.add_node(name, lat, lon)
        self.assertEqual(self.network.get_nodes(), {'node': Location(lat, lon)})
        with self.assertRaises(SliceConceptualGraph.NetworkSliceException):
            self.network.add_node('node', 33, 40)

    def test_get_empty_RUs(self):
        self.assertEqual(self.network.get_RUs(), {})

    def test_set_basetastion(self):
        lat, lon = 33, 40
        self.network.set_RU(lat, lon)
        self.assertEqual(self.network.get_RUs(), {f'{lat}-{lon}': Location(lat, lon)})
        with self.assertRaises(SliceConceptualGraph.NetworkSliceException):
            self.network.set_RU(lat, lon)

    def test_constructor(self):
        with self.assertRaises(FunctionalDegradation.FunctionDegradationNetworkException):
            SliceConceptualGraph('test', {} ,{}, {})
            SliceConceptualGraph('test', self.midhaul_qos, {}, {})
            SliceConceptualGraph('test', {}, self.backhaul_qos, {})
            SliceConceptualGraph('test', {}, {}, self.parameters)

    def test_get_qos(self):
        self.assertEqual(self.network.get_backhaul(), QoS(self.backhaul_qos))

    def test_set_qos(self):
        self.network.set_backhaul(QoS.minimum_qos_dict)
        self.assertEqual(self.network.get_backhaul(), QoS(QoS.minimum_qos_dict))

    def test_qos_from_distance(self):
        self.assertEqual(self.network.get_qos_from(5).get_formated_qos(), self.parameters.get('worst_qos'))
        self.assertEqual(self.network.get_qos_from(0.0).get_formated_qos(), self.parameters.get('best_qos'))

    def test_get_node_location(self):
        lat, lon = 33, 40
        self.network.set_RU(lat, lon)
        self.network.add_node('test', 10, 10)
        self.assertEqual(self.network.get_node_location('test2'), None)
        self.assertEqual(self.network.get_node_location('test'), Location(10, 10))

    def test_set_RUs(self):
        self.network.set_RUs([{'lat': 10, 'lon': 10}, {'lat': 5, 'lon': 5}])
        self.assertEqual(self.network.get_RUs(),
                         {'10-10': Location(**{'lat': 10, 'lon': 10}), '5-5': Location(**{'lat': 5, 'lon': 5})})
        with self.assertRaises(SliceConceptualGraph.NetworkSliceException):
            self.network.set_RUs([{'lat': 10, 'lon': 10}, {'lat': 5, 'lon': 5}])

    def test_set_node_location(self):
        lat, lon = 33, 40
        self.network.set_RU(lat, lon)
        self.network.add_node('destination1', 10, 10)
        self.network.set_node_location('destination1', 20, 20)
        self.assertEqual(self.network.get_node_location('destination1'), Location(20, 20))
        with self.assertRaises(Location.LocationException):
            self.network.set_node_location('destination1', 'test', 20)
        with self.assertRaises(Location.LocationException):
            self.network.set_node_location('destination1', 20, 'test')

[((1054, 1144), 'networks.slicing.SliceConceptualGraph', 'SliceConceptualGraph', (['self.name', 'self.midhaul_qos', 'self.backhaul_qos', 'self.parameters'], {}), '(self.name, self.midhaul_qos, self.backhaul_qos, self.\n    parameters)\n', (1074, 1144), False, 'from networks.slicing import SliceConceptualGraph\n'), ((5498, 5588), 'networks.slicing.SliceConceptualGraph', 'SliceConceptualGraph', (['self.name', 'self.midhaul_qos', 'self.backhaul_qos', 'self.parameters'], {}), '(self.name, self.midhaul_qos, self.backhaul_qos, self.\n    parameters)\n', (5518, 5588), False, 'from networks.slicing import SliceConceptualGraph\n'), ((2240, 2280), 'networks.slicing.SliceConceptualGraph', 'SliceConceptualGraph', (['"""test"""', '{}', '{}', '{}'], {}), "('test', {}, {}, {})\n", (2260, 2280), False, 'from networks.slicing import SliceConceptualGraph\n'), ((2293, 2347), 'networks.slicing.SliceConceptualGraph', 'SliceConceptualGraph', (['"""test"""', 'self.midhaul_qos', '{}', '{}'], {}), "('test', self.midhaul_qos, {}, {})\n", (2313, 2347), False, 'from networks.slicing import SliceConceptualGraph\n'), ((2360, 2415), 'networks.slicing.SliceConceptualGraph', 'SliceConceptualGraph', (['"""test"""', '{}', 'self.backhaul_qos', '{}'], {}), "('test', {}, self.backhaul_qos, {})\n", (2380, 2415), False, 'from networks.slicing import SliceConceptualGraph\n'), ((2428, 2481), 'networks.slicing.SliceConceptualGraph', 'SliceConceptualGraph', (['"""test"""', '{}', '{}', 'self.parameters'], {}), "('test', {}, {}, self.parameters)\n", (2448, 2481), False, 'from networks.slicing import SliceConceptualGraph\n'), ((2565, 2587), 'networks.QoS.QoS', 'QoS', (['self.backhaul_qos'], {}), '(self.backhaul_qos)\n', (2568, 2587), False, 'from networks.QoS import QoS\n'), ((2728, 2753), 'networks.QoS.QoS', 'QoS', (['QoS.minimum_qos_dict'], {}), '(QoS.minimum_qos_dict)\n', (2731, 2753), False, 'from networks.QoS import QoS\n'), ((3297, 3313), 'utils.location.Location', 'Location', (['(10)', '(10)'], {}), '(10, 10)\n', (3305, 3313), False, 'from utils.location import Location\n'), ((4377, 4393), 'utils.location.Location', 'Location', (['(20)', '(20)'], {}), '(20, 20)\n', (4385, 4393), False, 'from utils.location import Location\n'), ((6785, 6825), 'networks.slicing.SliceConceptualGraph', 'SliceConceptualGraph', (['"""test"""', '{}', '{}', '{}'], {}), "('test', {}, {}, {})\n", (6805, 6825), False, 'from networks.slicing import SliceConceptualGraph\n'), ((6838, 6892), 'networks.slicing.SliceConceptualGraph', 'SliceConceptualGraph', (['"""test"""', 'self.midhaul_qos', '{}', '{}'], {}), "('test', self.midhaul_qos, {}, {})\n", (6858, 6892), False, 'from networks.slicing import SliceConceptualGraph\n'), ((6905, 6960), 'networks.slicing.SliceConceptualGraph', 'SliceConceptualGraph', (['"""test"""', '{}', 'self.backhaul_qos', '{}'], {}), "('test', {}, self.backhaul_qos, {})\n", (6925, 6960), False, 'from networks.slicing import SliceConceptualGraph\n'), ((6973, 7026), 'networks.slicing.SliceConceptualGraph', 'SliceConceptualGraph', (['"""test"""', '{}', '{}', 'self.parameters'], {}), "('test', {}, {}, self.parameters)\n", (6993, 7026), False, 'from networks.slicing import SliceConceptualGraph\n'), ((7110, 7132), 'networks.QoS.QoS', 'QoS', (['self.backhaul_qos'], {}), '(self.backhaul_qos)\n', (7113, 7132), False, 'from networks.QoS import QoS\n'), ((7273, 7298), 'networks.QoS.QoS', 'QoS', (['QoS.minimum_qos_dict'], {}), '(QoS.minimum_qos_dict)\n', (7276, 7298), False, 'from networks.QoS import QoS\n'), ((7842, 7858), 'utils.location.Location', 'Location', (['(10)', '(10)'], {}), '(10, 10)\n', (7850, 7858), False, 'from utils.location import Location\n'), ((8578, 8594), 'utils.location.Location', 'Location', (['(20)', '(20)'], {}), '(20, 20)\n', (8586, 8594), False, 'from utils.location import Location\n'), ((1563, 1581), 'utils.location.Location', 'Location', (['lat', 'lon'], {}), '(lat, lon)\n', (1571, 1581), False, 'from utils.location import Location\n'), ((1965, 1983), 'utils.location.Location', 'Location', (['lat', 'lon'], {}), '(lat, lon)\n', (1973, 1983), False, 'from utils.location import Location\n'), ((3785, 3819), 'utils.location.Location', 'Location', ([], {}), "(**{'lat': 10, 'lon': 10})\n", (3793, 3819), False, 'from utils.location import Location\n'), ((3828, 3860), 'utils.location.Location', 'Location', ([], {}), "(**{'lat': 5, 'lon': 5})\n", (3836, 3860), False, 'from utils.location import Location\n'), ((6108, 6126), 'utils.location.Location', 'Location', (['lat', 'lon'], {}), '(lat, lon)\n', (6116, 6126), False, 'from utils.location import Location\n'), ((6510, 6528), 'utils.location.Location', 'Location', (['lat', 'lon'], {}), '(lat, lon)\n', (6518, 6528), False, 'from utils.location import Location\n'), ((8050, 8084), 'utils.location.Location', 'Location', ([], {}), "(**{'lat': 10, 'lon': 10})\n", (8058, 8084), False, 'from utils.location import Location\n'), ((8093, 8125), 'utils.location.Location', 'Location', ([], {}), "(**{'lat': 5, 'lon': 5})\n", (8101, 8125), False, 'from utils.location import Location\n')]