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')

[(23, 'networks.slicing.SliceConceptualGraph', 'SliceConceptualGraph', False, 'from networks.slicing import SliceConceptualGraph\n'), (117, 'networks.slicing.SliceConceptualGraph', 'SliceConceptualGraph', False, 'from networks.slicing import SliceConceptualGraph\n'), (52, 'networks.slicing.SliceConceptualGraph', 'SliceConceptualGraph', False, 'from networks.slicing import SliceConceptualGraph\n'), (53, 'networks.slicing.SliceConceptualGraph', 'SliceConceptualGraph', False, 'from networks.slicing import SliceConceptualGraph\n'), (54, 'networks.slicing.SliceConceptualGraph', 'SliceConceptualGraph', False, 'from networks.slicing import SliceConceptualGraph\n'), (55, 'networks.slicing.SliceConceptualGraph', 'SliceConceptualGraph', False, 'from networks.slicing import SliceConceptualGraph\n'), (58, 'networks.QoS.QoS', 'QoS', False, 'from networks.QoS import QoS\n'), (62, 'networks.QoS.QoS', 'QoS', False, 'from networks.QoS import QoS\n'), (73, 'utils.location.Location', 'Location', False, 'from utils.location import Location\n'), (97, 'utils.location.Location', 'Location', False, 'from utils.location import Location\n'), (147, 'networks.slicing.SliceConceptualGraph', 'SliceConceptualGraph', False, 'from networks.slicing import SliceConceptualGraph\n'), (148, 'networks.slicing.SliceConceptualGraph', 'SliceConceptualGraph', False, 'from networks.slicing import SliceConceptualGraph\n'), (149, 'networks.slicing.SliceConceptualGraph', 'SliceConceptualGraph', False, 'from networks.slicing import SliceConceptualGraph\n'), (150, 'networks.slicing.SliceConceptualGraph', 'SliceConceptualGraph', False, 'from networks.slicing import SliceConceptualGraph\n'), (153, 'networks.QoS.QoS', 'QoS', False, 'from networks.QoS import QoS\n'), (157, 'networks.QoS.QoS', 'QoS', False, 'from networks.QoS import QoS\n'), (168, 'utils.location.Location', 'Location', False, 'from utils.location import Location\n'), (182, 'utils.location.Location', 'Location', False, 'from utils.location import Location\n'), (36, 'utils.location.Location', 'Location', False, 'from utils.location import Location\n'), (46, 'utils.location.Location', 'Location', False, 'from utils.location import Location\n'), (86, 'utils.location.Location', 'Location', False, 'from utils.location import Location\n'), (86, 'utils.location.Location', 'Location', False, 'from utils.location import Location\n'), (131, 'utils.location.Location', 'Location', False, 'from utils.location import Location\n'), (141, 'utils.location.Location', 'Location', False, 'from utils.location import Location\n'), (173, 'utils.location.Location', 'Location', False, 'from utils.location import Location\n'), (173, 'utils.location.Location', 'Location', False, 'from utils.location import Location\n')]