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, 23, 23, 108), 'networks.slicing.SliceConceptualGraph', 'SliceConceptualGraph', ({(23, 44, 23, 53): 'self.name', (23, 55, 23, 71): 'self.midhaul_qos', (23, 73, 23, 90): 'self.backhaul_qos', (23, 92, 23, 107): 'self.parameters'}, {}), '(self.name, self.midhaul_qos, self.backhaul_qos, self.\n    parameters)', False, 'from networks.slicing import SliceConceptualGraph\n'), ((117, 23, 117, 108), 'networks.slicing.SliceConceptualGraph', 'SliceConceptualGraph', ({(117, 44, 117, 53): 'self.name', (117, 55, 117, 71): 'self.midhaul_qos', (117, 73, 117, 90): 'self.backhaul_qos', (117, 92, 117, 107): 'self.parameters'}, {}), '(self.name, self.midhaul_qos, self.backhaul_qos, self.\n    parameters)', False, 'from networks.slicing import SliceConceptualGraph\n'), ((52, 12, 52, 52), 'networks.slicing.SliceConceptualGraph', 'SliceConceptualGraph', ({(52, 33, 52, 39): '"""test"""', (52, 41, 52, 43): '{}', (52, 45, 52, 47): '{}', (52, 49, 52, 51): '{}'}, {}), "('test', {}, {}, {})", False, 'from networks.slicing import SliceConceptualGraph\n'), ((53, 12, 53, 66), 'networks.slicing.SliceConceptualGraph', 'SliceConceptualGraph', ({(53, 33, 53, 39): '"""test"""', (53, 41, 53, 57): 'self.midhaul_qos', (53, 59, 53, 61): '{}', (53, 63, 53, 65): '{}'}, {}), "('test', self.midhaul_qos, {}, {})", False, 'from networks.slicing import SliceConceptualGraph\n'), ((54, 12, 54, 67), 'networks.slicing.SliceConceptualGraph', 'SliceConceptualGraph', ({(54, 33, 54, 39): '"""test"""', (54, 41, 54, 43): '{}', (54, 45, 54, 62): 'self.backhaul_qos', (54, 64, 54, 66): '{}'}, {}), "('test', {}, self.backhaul_qos, {})", False, 'from networks.slicing import SliceConceptualGraph\n'), ((55, 12, 55, 65), 'networks.slicing.SliceConceptualGraph', 'SliceConceptualGraph', ({(55, 33, 55, 39): '"""test"""', (55, 41, 55, 43): '{}', (55, 45, 55, 47): '{}', (55, 49, 55, 64): 'self.parameters'}, {}), "('test', {}, {}, self.parameters)", False, 'from networks.slicing import SliceConceptualGraph\n'), ((58, 54, 58, 76), 'networks.QoS.QoS', 'QoS', ({(58, 58, 58, 75): 'self.backhaul_qos'}, {}), '(self.backhaul_qos)', False, 'from networks.QoS import QoS\n'), ((62, 54, 62, 79), 'networks.QoS.QoS', 'QoS', ({(62, 58, 62, 78): 'QoS.minimum_qos_dict'}, {}), '(QoS.minimum_qos_dict)', False, 'from networks.QoS import QoS\n'), ((73, 65, 73, 81), 'utils.location.Location', 'Location', ({(73, 74, 73, 76): '(10)', (73, 78, 73, 80): '(10)'}, {}), '(10, 10)', False, 'from utils.location import Location\n'), ((97, 73, 97, 89), 'utils.location.Location', 'Location', ({(97, 82, 97, 84): '(20)', (97, 86, 97, 88): '(20)'}, {}), '(20, 20)', False, 'from utils.location import Location\n'), ((147, 12, 147, 52), 'networks.slicing.SliceConceptualGraph', 'SliceConceptualGraph', ({(147, 33, 147, 39): '"""test"""', (147, 41, 147, 43): '{}', (147, 45, 147, 47): '{}', (147, 49, 147, 51): '{}'}, {}), "('test', {}, {}, {})", False, 'from networks.slicing import SliceConceptualGraph\n'), ((148, 12, 148, 66), 'networks.slicing.SliceConceptualGraph', 'SliceConceptualGraph', ({(148, 33, 148, 39): '"""test"""', (148, 41, 148, 57): 'self.midhaul_qos', (148, 59, 148, 61): '{}', (148, 63, 148, 65): '{}'}, {}), "('test', self.midhaul_qos, {}, {})", False, 'from networks.slicing import SliceConceptualGraph\n'), ((149, 12, 149, 67), 'networks.slicing.SliceConceptualGraph', 'SliceConceptualGraph', ({(149, 33, 149, 39): '"""test"""', (149, 41, 149, 43): '{}', (149, 45, 149, 62): 'self.backhaul_qos', (149, 64, 149, 66): '{}'}, {}), "('test', {}, self.backhaul_qos, {})", False, 'from networks.slicing import SliceConceptualGraph\n'), ((150, 12, 150, 65), 'networks.slicing.SliceConceptualGraph', 'SliceConceptualGraph', ({(150, 33, 150, 39): '"""test"""', (150, 41, 150, 43): '{}', (150, 45, 150, 47): '{}', (150, 49, 150, 64): 'self.parameters'}, {}), "('test', {}, {}, self.parameters)", False, 'from networks.slicing import SliceConceptualGraph\n'), ((153, 54, 153, 76), 'networks.QoS.QoS', 'QoS', ({(153, 58, 153, 75): 'self.backhaul_qos'}, {}), '(self.backhaul_qos)', False, 'from networks.QoS import QoS\n'), ((157, 54, 157, 79), 'networks.QoS.QoS', 'QoS', ({(157, 58, 157, 78): 'QoS.minimum_qos_dict'}, {}), '(QoS.minimum_qos_dict)', False, 'from networks.QoS import QoS\n'), ((168, 65, 168, 81), 'utils.location.Location', 'Location', ({(168, 74, 168, 76): '(10)', (168, 78, 168, 80): '(10)'}, {}), '(10, 10)', False, 'from utils.location import Location\n'), ((182, 73, 182, 89), 'utils.location.Location', 'Location', ({(182, 82, 182, 84): '(20)', (182, 86, 182, 88): '(20)'}, {}), '(20, 20)', False, 'from utils.location import Location\n'), ((36, 60, 36, 78), 'utils.location.Location', 'Location', ({(36, 69, 36, 72): 'lat', (36, 74, 36, 77): 'lon'}, {}), '(lat, lon)', False, 'from utils.location import Location\n'), ((46, 66, 46, 84), 'utils.location.Location', 'Location', ({(46, 75, 46, 78): 'lat', (46, 80, 46, 83): 'lon'}, {}), '(lat, lon)', False, 'from utils.location import Location\n'), ((86, 35, 86, 69), 'utils.location.Location', 'Location', ({}, {}), "(**{'lat': 10, 'lon': 10})", False, 'from utils.location import Location\n'), ((86, 78, 86, 110), 'utils.location.Location', 'Location', ({}, {}), "(**{'lat': 5, 'lon': 5})", False, 'from utils.location import Location\n'), ((131, 60, 131, 78), 'utils.location.Location', 'Location', ({(131, 69, 131, 72): 'lat', (131, 74, 131, 77): 'lon'}, {}), '(lat, lon)', False, 'from utils.location import Location\n'), ((141, 66, 141, 84), 'utils.location.Location', 'Location', ({(141, 75, 141, 78): 'lat', (141, 80, 141, 83): 'lon'}, {}), '(lat, lon)', False, 'from utils.location import Location\n'), ((173, 35, 173, 69), 'utils.location.Location', 'Location', ({}, {}), "(**{'lat': 10, 'lon': 10})", False, 'from utils.location import Location\n'), ((173, 78, 173, 110), 'utils.location.Location', 'Location', ({}, {}), "(**{'lat': 5, 'lon': 5})", False, 'from utils.location import Location\n')]