import os
import random
import sys
import xml.etree.ElementTree as ET
from sumo_experiments.components import InfrastructureBuilder, FlowBuilder, DetectorBuilder
from copy import deepcopy
import random
import libsumo as traci

from sumo_experiments.preset_networks import Network


class BolognaNetwork(Network):
    """
    Create the SUMO network and flows for the city of Lille.
    """

    THIS_FILE_PATH = os.path.abspath(os.path.dirname(__file__))

    def __init__(self, intensity, generation_duration=3600):
        """
        Init of class
        :param intensity: The multiplier of the number of generated vehicles.
        :type intensity: float
        """
        self.exp_name = random.randint(0, 100000)
        self.FULL_LINE_COMMAND = f"sumo -c {self.THIS_FILE_PATH}/bologna/acosta/run_{self.exp_name}.sumocfg"
        self.FULL_LINE_COMMAND_GUI = f"sumo-gui -c {self.THIS_FILE_PATH}/bologna/acosta/run_{self.exp_name}.sumocfg"
        self.NET_FILE = os.path.join(self.THIS_FILE_PATH, 'bologna/acosta/acosta_buslanes.net.xml')
        self.FLOW_FILE = os.path.join(self.THIS_FILE_PATH, 'bologna/acosta/acosta.rou.xml')
        self.NEW_FLOW_FILE = os.path.join(self.THIS_FILE_PATH, f'bologna/acosta/acosta_{self.exp_name}.rou.xml')
        self.CONFIG_FILE = os.path.join(self.THIS_FILE_PATH, f"bologna/acosta/run.sumocfg")
        self.NEW_CONFIG_FILE = os.path.join(self.THIS_FILE_PATH, f"bologna/acosta/run_{self.exp_name}.sumocfg")
        self.generate_config_file()
        self.generate_flows(intensity, generation_duration)
        self.TLS_DETECTORS = {
            '209': self.DETECTORS_209,
            '210': self.DETECTORS_210,
            '219': self.DETECTORS_219,
            '220': self.DETECTORS_220,
            '221': self.DETECTORS_221,
            '235': self.DETECTORS_235,
            '273': self.DETECTORS_273
        }
        self.TL_IDS = ['209', '210', '219', '220', '221', '235', '273']


    def run(self, traci_function, gui=False, seed=None, no_warnings=True, nb_threads=1, time_to_teleport=150):
        """
        Run the network.
        :param traci_function: The function using TraCi package and that can control infrastructures.
        :type: function
        :param gui: True to run SUMO in graphical mode. False otherwise.
        :type gui: bool
        :param seed: The seed of the simulation. Same seeds = same simulations.
        :type seed: int
        :param no_warnings: If set to True, no warnings when executing SUMO.
        :type no_warnings: bool
        :param nb_threads: Number of thread to run SUMO
        :type nb_threads: int
        :param time_to_teleport: The time for a vehicle to teleport when the network is blocked
        :type time_to_teleport: int
        """
        #try:
        if seed is not None:
            seed_text = f'--seed {seed} '
        else:
            seed_text = '--random '
        threads_text = f'--threads {nb_threads} '
        no_warnings_text = ''
        if no_warnings:
            no_warnings_text = '--no-warnings '
        if gui:
            traci.start((self.FULL_LINE_COMMAND_GUI + f' --time-to-teleport {time_to_teleport} ' + threads_text + seed_text + no_warnings_text).split())
        else:
            traci.start((self.FULL_LINE_COMMAND + f' --time-to-teleport {time_to_teleport} ' + threads_text + seed_text + no_warnings_text).split())
        res = traci_function(traci)
        traci.close()
        # except Exception as err:
        #     print("Error during simulation :", sys.exc_info()[0])
        #     print("OS error: {0}".format(err))
        #     res = None
        self.clean_files()
        return res


    def clean_files(self):
        """
        Delete all the files generated by the instance.
        """
        if os.path.isfile(self.NEW_CONFIG_FILE):
            os.remove(self.NEW_CONFIG_FILE)
        if os.path.isfile(self.NEW_FLOW_FILE):
            os.remove(self.NEW_FLOW_FILE)

    def generate_config_file(self):
        """
        Create a new config file for the bologna network.
        """
        if os.path.isfile(self.NEW_CONFIG_FILE):
            os.remove(self.NEW_CONFIG_FILE)
        with open(self.CONFIG_FILE, 'r') as config_file:
            with open(self.NEW_CONFIG_FILE, 'a') as new_config_file:
                line = config_file.readline()
                while line != '':
                    if line != '\n' and line.split()[0] == '<route-files':
                        first_part = line.split('.')[0]
                        second_part = line.split('.')[1:]
                        first_part = ['"'.join(first_part.split('"')[:-1] + [f"acosta_{self.exp_name}"])]
                        new_line = '.'.join(first_part + second_part)
                        new_config_file.write(new_line)
                    else:
                        new_config_file.write(line)
                    line = config_file.readline()


    def generate_infrastructures(self):
        """
        Generate the infrastructures of the network from the network files
        :return: The infrastructures of the network
        :rtype: InfrastructureBuilder
        """
        infra = InfrastructureBuilder()
        tree = ET.parse(self.NET_FILE)
        nodes = [e for e in tree.iter('junction')]
        for node in nodes:
            infra.add_node(id=node.get('id'),
                           x=float(node.get('x')),
                           y=float(node.get('y')),
                           type=node.get('type'))
        edges = [e for e in tree.iter('edge')]
        for edge in edges:
            if not edge.get('id')[0] == ':':
                infra.add_edge(id=edge.get('id'),
                               from_node=edge.get('from'),
                               to_node=edge.get('to'),
                               edge_type='default')
        connections = [e for e in tree.iter('connection')]
        for conn in connections:
            if conn.get('from')[0] != ':' and conn.get('to')[0] != ':':
                infra.add_connection(from_edge=conn.get('from'),
                                     to_edge=conn.get('to'),
                                     from_lane=int(conn.get('fromLane')),
                                     to_lane=int(conn.get('toLane')))
        return infra

    def generate_flows(self, coeff, generation_duration):
        """
        Generate a flow file for the bologna network, based on FLOW_FILE.
        The coeff parameter is used to multiply the number of generated vehicles. Can be superior to 1.
        :param coeff: The multiplier of the number of generated vehicles.
        :type coeff: float
        :param generation_duration: The time during vehicles are generated
        :type generation_duration: int
        :return: Nothing
        """
        if os.path.isfile(self.NEW_FLOW_FILE):
            os.remove(self.NEW_FLOW_FILE)
        time = 0
        while time < generation_duration:
            with open(self.FLOW_FILE, 'r') as flow_file:
                with open(self.NEW_FLOW_FILE, 'a') as new_flow_file:
                    entete = flow_file.readline()
                    if time == 0:
                        new_flow_file.write(entete)
                    next_vehicle = flow_file.readline()
                    while next_vehicle != "</routes>":
                        vehicle_time = int(next_vehicle.split('"')[1])
                        if vehicle_time + time < generation_duration:
                            curr_coeff = deepcopy(coeff)
                            while curr_coeff >= 1:
                                splitted = next_vehicle.split('"')
                                splitted[1] = str(vehicle_time + time)
                                splitted[11] += f'_x{int(curr_coeff * 10 + vehicle_time + time)}'
                                new_vehicle = '"'.join(splitted)
                                new_flow_file.write(new_vehicle)
                                curr_coeff -= 1
                            if random.random() < curr_coeff:
                                splitted = next_vehicle.split('"')
                                splitted[1] = str(vehicle_time + time)
                                splitted[11] += f'_x{int(curr_coeff * 10 + vehicle_time + time)}'
                                new_vehicle = '"'.join(splitted)
                                new_flow_file.write(new_vehicle)
                        next_vehicle = flow_file.readline()
            time += 3600
        with open(self.NEW_FLOW_FILE, 'a') as new_flow_file:
            new_flow_file.write(next_vehicle)




    def generate_detectors(self):
        """
        Generate the detectors of the network.
        :return: The detectors of the network
        :rtype: DetectorBuilder
        """
        det = DetectorBuilder()
        # Intersection 34-27
        det.add_lane_area_detector(id='34_1', edge='43[0]', lane=2, end_pos=20, type='boolean')
        det.add_lane_area_detector(id='34_2', edge='117', lane=0, pos=108, end_pos=128, type='boolean')
        det.add_lane_area_detector(id='34_3', edge='113', lane=0, pos=60, end_pos=80, type='boolean')
        det.add_lane_area_detector(id='34_4', edge='113', lane=1, pos=60, end_pos=80, type='boolean')
        det.add_lane_area_detector(id='34_5', edge='113', lane=2, pos=60, end_pos=80, type='boolean')
        det.add_lane_area_detector(id='34_6', edge='117', lane=0, end_pos=20, type='saturation')
        det.add_lane_area_detector(id='34_7', edge='113', lane=0, end_pos=20, type='saturation')
        det.add_lane_area_detector(id='34_8', edge='113', lane=1, end_pos=20, type='saturation')
        det.add_lane_area_detector(id='34_9', edge='113', lane=2, end_pos=20, type='saturation')
        det.add_lane_area_detector(id='34_10', edge='43[0]', lane=2, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='34_11', edge='210', lane=2, pos=184, end_pos=364, type='numerical')
        det.add_lane_area_detector(id='34_12', edge='117', lane=0, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='34_13', edge='113', lane=0, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='34_14', edge='113', lane=1, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='34_15', edge='113', lane=2, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='34_16', edge='118', lane=0, end_pos=-1, type='exit')
        det.add_lane_area_detector(id='34_17', edge='209', lane=0, end_pos=200, type='exit')
        det.add_lane_area_detector(id='34_18', edge='209', lane=1, end_pos=200, type='exit')
        det.add_lane_area_detector(id='34_19', edge='209', lane=2, end_pos=200, type='exit')
        det.add_lane_area_detector(id='27_1', edge='43[1]', lane=0, pos=60, end_pos=80, type='boolean')
        det.add_lane_area_detector(id='27_2', edge='43[1]', lane=1, pos=60, end_pos=80, type='boolean')
        det.add_lane_area_detector(id='27_3', edge='43[1]', lane=2, pos=60, end_pos=80, type='boolean')
        det.add_lane_area_detector(id='27_4', edge='31', lane=0, end_pos=-1, type='boolean')
        det.add_lane_area_detector(id='27_5', edge='31', lane=1, end_pos=-1, type='boolean')
        det.add_lane_area_detector(id='27_6', edge='31', lane=2, end_pos=-1, type='boolean')
        det.add_lane_area_detector(id='27_7', edge='34', lane=0, pos=38, end_pos=58, type='boolean')
        det.add_lane_area_detector(id='27_8', edge='34', lane=1, pos=38, end_pos=58, type='boolean')
        det.add_lane_area_detector(id='27_9', edge='34', lane=2, pos=38, end_pos=58, type='boolean')
        det.add_lane_area_detector(id='27_10', edge='46', lane=0, pos=46.8, end_pos=66.8, type='boolean')
        det.add_lane_area_detector(id='27_11', edge='46', lane=1, pos=46.8, end_pos=66.8, type='boolean')
        det.add_lane_area_detector(id='27_12', edge='46', lane=2, pos=46.8, end_pos=66.8, type='boolean')
        det.add_lane_area_detector(id='27_13', edge='43[1]', lane=0, end_pos=20, type='saturation')
        det.add_lane_area_detector(id='27_14', edge='43[1]', lane=1, end_pos=20, type='saturation')
        det.add_lane_area_detector(id='27_15', edge='43[1]', lane=2, end_pos=20, type='saturation')
        det.add_lane_area_detector(id='27_16', edge='202', lane=0, end_pos=20, type='saturation')
        det.add_lane_area_detector(id='27_17', edge='202', lane=1, end_pos=20, type='saturation')
        det.add_lane_area_detector(id='27_18', edge='202', lane=2, end_pos=20, type='saturation')
        det.add_lane_area_detector(id='27_19', edge='116', lane=0, end_pos=20, type='saturation')
        det.add_lane_area_detector(id='27_20', edge='43[1]', lane=0, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='27_21', edge='43[1]', lane=1, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='27_22', edge='43[1]', lane=2, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='27_23', edge='31', lane=0, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='27_24', edge='31', lane=1, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='27_25', edge='31', lane=2, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='27_26', edge='133', lane=0, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='27_27', edge='165', lane=0, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='27_28', edge='34', lane=0, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='27_29', edge='34', lane=1, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='27_30', edge='34', lane=2, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='27_31', edge='202', lane=0, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='27_32', edge='202', lane=1, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='27_33', edge='202', lane=2, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='27_34', edge='46', lane=0, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='27_35', edge='46', lane=1, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='27_36', edge='46', lane=2, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='27_37', edge='116', lane=0, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='27_38', edge='201', lane=0, end_pos=200, type='exit')
        det.add_lane_area_detector(id='27_39', edge='201', lane=1, end_pos=200, type='exit')
        det.add_lane_area_detector(id='27_40', edge='201', lane=2, end_pos=200, type='exit')
        det.add_lane_area_detector(id='27_41', edge='115', lane=0, end_pos=-1, type='exit')
        det.add_lane_area_detector(id='27_42', edge='113', lane=0, end_pos=-1, type='exit')
        det.add_lane_area_detector(id='27_43', edge='113', lane=1, end_pos=-1, type='exit')
        det.add_lane_area_detector(id='27_44', edge='113', lane=2, end_pos=-1, type='exit')
        det.add_lane_area_detector(id='27_45', edge='134', lane=0, end_pos=-1, type='exit')
        det.add_lane_area_detector(id='27_46', edge='134b', lane=0, end_pos=-1, type='exit')
        # Intersections 1-1b-1c-3
        det.add_lane_area_detector(id='1_1', edge='201', lane=0, pos=211.3, end_pos=231.3, type='boolean')
        det.add_lane_area_detector(id='1_2', edge='201', lane=1, pos=211.3, end_pos=231.3, type='boolean')
        det.add_lane_area_detector(id='1_3', edge='201', lane=2, pos=211.3, end_pos=231.3, type='boolean')
        det.add_lane_area_detector(id='1_4', edge='203[1]', lane=0, pos=209.7, end_pos=229.7, type='boolean')
        det.add_lane_area_detector(id='1_5', edge='203[1]', lane=1, pos=209.7, end_pos=229.7, type='boolean')
        det.add_lane_area_detector(id='1_6', edge='203[1]', lane=2, pos=209.7, end_pos=229.7, type='boolean')
        det.add_lane_area_detector(id='1_7', edge='1b', lane=0, pos=40.4, end_pos=60.4, type='boolean')
        det.add_lane_area_detector(id='1_8', edge='1b', lane=1, pos=40.4, end_pos=60.4, type='boolean')
        det.add_lane_area_detector(id='1_9', edge='2', lane=0, pos=19.6, end_pos=39.6, type='boolean')
        det.add_lane_area_detector(id='1_10', edge='2', lane=1, pos=19.6, end_pos=39.6, type='boolean')
        det.add_lane_area_detector(id='1_11', edge='2', lane=2, pos=19.6, end_pos=39.6, type='boolean')
        det.add_lane_area_detector(id='1_12', edge='201', lane=0, end_pos=20, type='saturation')
        det.add_lane_area_detector(id='1_13', edge='201', lane=1, end_pos=20, type='saturation')
        det.add_lane_area_detector(id='1_14', edge='201', lane=2, end_pos=20, type='saturation')
        det.add_lane_area_detector(id='1_15', edge='203[1]', lane=0, end_pos=20, type='saturation')
        det.add_lane_area_detector(id='1_16', edge='203[1]', lane=1, end_pos=20, type='saturation')
        det.add_lane_area_detector(id='1_17', edge='203[1]', lane=2, end_pos=20, type='saturation')
        det.add_lane_area_detector(id='1_18', edge='122', lane=0, end_pos=20, type='saturation')
        det.add_lane_area_detector(id='1_19', edge='122', lane=1, end_pos=20, type='saturation')
        det.add_lane_area_detector(id='1_20', edge='122', lane=2, end_pos=20, type='saturation')
        det.add_lane_area_detector(id='1_21', edge='201', lane=0, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='1_22', edge='201', lane=1, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='1_23', edge='201', lane=2, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='1_24', edge='203[1]', lane=0, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='1_25', edge='203[1]', lane=1, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='1_26', edge='203[1]', lane=2, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='1_27', edge='1b', lane=0, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='1_28', edge='1b', lane=1, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='1_29', edge='2', lane=0, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='1_30', edge='2', lane=1, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='1_31', edge='2', lane=2, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='1_32', edge='3', lane=0, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='1_33', edge='3', lane=1, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='1_34', edge='122', lane=0, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='1_35', edge='122', lane=1, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='1_36', edge='122', lane=2, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='1_37', edge='204a[0]', lane=0, end_pos=-1, type='exit')
        det.add_lane_area_detector(id='1_38', edge='204a[0]', lane=1, end_pos=-1, type='exit')
        det.add_lane_area_detector(id='1_39', edge='204a[0]', lane=2, end_pos=-1, type='exit')
        det.add_lane_area_detector(id='1_40', edge='202', lane=0, end_pos=-1, type='exit')
        det.add_lane_area_detector(id='1_41', edge='202', lane=1, end_pos=-1, type='exit')
        det.add_lane_area_detector(id='1_42', edge='202', lane=2, end_pos=-1, type='exit')
        det.add_lane_area_detector(id='1_43', edge='4c', lane=0, end_pos=-1, type='exit')
        # Intersection 78-44-43-204c
        det.add_lane_area_detector(id='78_1', edge='203[0]', lane=0, pos=381.1, end_pos=401.1, type='boolean')
        det.add_lane_area_detector(id='78_2', edge='203[0]', lane=1, pos=381.1, end_pos=401.1, type='boolean')
        det.add_lane_area_detector(id='78_3', edge='203[0]', lane=2, pos=381.1, end_pos=401.1, type='boolean')
        det.add_lane_area_detector(id='78_4', edge='204a[0]', lane=0, pos=170.2, end_pos=190.2, type='boolean')
        det.add_lane_area_detector(id='78_5', edge='204a[0]', lane=1, pos=170.2, end_pos=190.2, type='boolean')
        det.add_lane_area_detector(id='78_6', edge='204a[0]', lane=2, pos=170.2, end_pos=190.2, type='boolean')
        det.add_lane_area_detector(id='78_7', edge='55b', lane=0, end_pos=-1, type='boolean')
        det.add_lane_area_detector(id='78_8', edge='55b', lane=1, end_pos=-1, type='boolean')
        det.add_lane_area_detector(id='78_9', edge='55b', lane=2, end_pos=-1, type='boolean')
        det.add_lane_area_detector(id='78_10', edge='121', lane=0, pos=673.6, end_pos=693.6, type='boolean')
        det.add_lane_area_detector(id='78_11', edge='204a[0]', lane=0, end_pos=20, type='saturation')
        det.add_lane_area_detector(id='78_12', edge='204a[0]', lane=1, end_pos=20, type='saturation')
        det.add_lane_area_detector(id='78_13', edge='204a[0]', lane=2, end_pos=20, type='saturation')
        det.add_lane_area_detector(id='78_14', edge='203[0]', lane=0, pos=200, end_pos=401.1, type='numerical')
        det.add_lane_area_detector(id='78_15', edge='203[0]', lane=1, pos=200, end_pos=401.1, type='numerical')
        det.add_lane_area_detector(id='78_16', edge='203[0]', lane=2, pos=200, end_pos=401.1, type='numerical')
        det.add_lane_area_detector(id='78_17', edge='204a[0]', lane=0, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='78_18', edge='204a[0]', lane=1, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='78_19', edge='204a[0]', lane=2, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='78_19_b', edge='121', lane=0, pos=493.6, end_pos=693.6, type='numerical')
        det.add_lane_area_detector(id='78_19_c', edge='55b', lane=0, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='78_19_d', edge='55b', lane=1, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='78_19_e', edge='55b', lane=2, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='78_19_f', edge='55', lane=0, pos=100, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='78_20', edge='204[1][1]', lane=0, end_pos=200, type='exit')
        det.add_lane_area_detector(id='78_21', edge='204[1][1]', lane=1, end_pos=200, type='exit')
        det.add_lane_area_detector(id='78_22', edge='204[1][1]', lane=2, end_pos=200, type='exit')
        det.add_lane_area_detector(id='78_23', edge='114', lane=0, end_pos=200, type='exit')
        det.add_lane_area_detector(id='78_24', edge='114', lane=1, end_pos=200, type='exit')
        det.add_lane_area_detector(id='78_25', edge='114', lane=2, end_pos=200, type='exit')
        det.add_lane_area_detector(id='78_26', edge='203[1]', lane=0, end_pos=200, type='exit')
        det.add_lane_area_detector(id='78_27', edge='203[1]', lane=1, end_pos=200, type='exit')
        det.add_lane_area_detector(id='78_28', edge='203[1]', lane=2, end_pos=200, type='exit')
        det.add_lane_area_detector(id='78_29', edge='54', lane=0, end_pos=200, type='exit')
        det.add_lane_area_detector(id='78_30', edge='54', lane=1, end_pos=200, type='exit')
        # Intersection 52-15
        det.add_lane_area_detector(id='52_1', edge='69', lane=0, pos=116, end_pos=136, type='boolean')
        det.add_lane_area_detector(id='52_2', edge='69', lane=1, pos=116, end_pos=136, type='boolean')
        det.add_lane_area_detector(id='52_3', edge='171', lane=0, pos=153.8, end_pos=173.8, type='boolean')
        det.add_lane_area_detector(id='52_4', edge='69', lane=0, end_pos=20, type='saturation')
        det.add_lane_area_detector(id='52_5', edge='69', lane=1, end_pos=20, type='saturation')
        det.add_lane_area_detector(id='52_6', edge='171', lane=0, end_pos=20, type='saturation')
        det.add_lane_area_detector(id='52_7', edge='69', lane=0, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='52_8', edge='69', lane=1, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='52_9', edge='171', lane=0, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='52_10', edge='17', lane=0, end_pos=-1, type='exit')
        det.add_lane_area_detector(id='52_11', edge='17', lane=1, end_pos=-1, type='exit')
        det.add_lane_area_detector(id='52_12', edge='69', lane=0, end_pos=-1, type='exit')
        det.add_lane_area_detector(id='52_13', edge='69', lane=1, end_pos=-1, type='exit')
        det.add_lane_area_detector(id='52_14', edge='69', lane=0, end_pos=-1, type='exit')
        det.add_lane_area_detector(id='52_15', edge='69', lane=1, end_pos=-1, type='exit')
        det.add_lane_area_detector(id='15_1', edge='72[1]', lane=0, end_pos=-1, type='boolean')
        det.add_lane_area_detector(id='15_2', edge='72[1]', lane=1, end_pos=-1, type='boolean')
        det.add_lane_area_detector(id='15_3', edge='191', lane=0, pos=148, end_pos=168, type='boolean')
        det.add_lane_area_detector(id='15_4', edge='18', lane=0, pos=6.1, end_pos=26.1, type='boolean')
        det.add_lane_area_detector(id='15_5', edge='18', lane=1, pos=6.1, end_pos=26.1, type='boolean')
        det.add_lane_area_detector(id='15_6', edge='72[0]', lane=0, end_pos=20, type='saturation')
        det.add_lane_area_detector(id='15_7', edge='72[0]', lane=1, end_pos=20, type='saturation')
        det.add_lane_area_detector(id='15_8', edge='72[0]', lane=2, end_pos=20, type='saturation')
        det.add_lane_area_detector(id='15_9', edge='74', lane=0, end_pos=20, type='saturation')
        det.add_lane_area_detector(id='15_10', edge='181', lane=0, end_pos=20, type='saturation')
        det.add_lane_area_detector(id='15_11', edge='181', lane=1, end_pos=20, type='saturation')
        det.add_lane_area_detector(id='15_12', edge='191', lane=0, end_pos=20, type='saturation')
        det.add_lane_area_detector(id='15_13', edge='72[0]', lane=0, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='15_14', edge='72[0]', lane=1, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='15_15', edge='72[0]', lane=2, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='15_16', edge='72[1]', lane=0, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='15_17', edge='72[1]', lane=1, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='15_18', edge='74', lane=0, pos=67, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='15_19', edge='181', lane=0, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='15_20', edge='181', lane=1, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='15_21', edge='18', lane=0, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='15_22', edge='18', lane=1, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='15_23', edge='191', lane=0, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='15_24', edge='72[0]', lane=0, pos=150, end_pos=170, type='boolean')
        det.add_lane_area_detector(id='15_25', edge='72[0]', lane=1, pos=150, end_pos=170, type='boolean')
        det.add_lane_area_detector(id='15_26', edge='72[0]', lane=2, pos=150, end_pos=170, type='boolean')
        # Intersection 9
        det.add_lane_area_detector(id='9_1', edge='12', lane=0, pos=38.6, end_pos=58.6, type='boolean')
        det.add_lane_area_detector(id='9_2', edge='12', lane=1, pos=38.6, end_pos=58.6, type='boolean')
        det.add_lane_area_detector(id='9_3', edge='12', lane=2, pos=38.6, end_pos=58.6, type='boolean')
        det.add_lane_area_detector(id='9_4', edge='71', lane=0, pos=41.2, end_pos=61.2, type='boolean')
        det.add_lane_area_detector(id='9_5', edge='71', lane=1, pos=41.2, end_pos=61.2, type='boolean')
        det.add_lane_area_detector(id='9_6', edge='71', lane=2, pos=41.2, end_pos=61.2, type='boolean')
        det.add_lane_area_detector(id='9_7', edge='11', lane=0, pos=13.9, end_pos=33.9, type='boolean')
        det.add_lane_area_detector(id='9_8', edge='11', lane=1, pos=13.9, end_pos=33.9, type='boolean')
        det.add_lane_area_detector(id='9_9', edge='11', lane=2, pos=13.9, end_pos=33.9, type='boolean')
        det.add_lane_area_detector(id='9_10', edge='85', lane=0, pos=313.1, end_pos=333.1, type='boolean')
        det.add_lane_area_detector(id='9_11', edge='85', lane=1, pos=313.1, end_pos=333.1, type='boolean')
        det.add_lane_area_detector(id='9_12', edge='85', lane=2, pos=313.1, end_pos=333.1, type='boolean')
        det.add_lane_area_detector(id='9_13', edge='83', lane=0, end_pos=20, type='saturation')
        det.add_lane_area_detector(id='9_14', edge='17', lane=0, end_pos=20, type='saturation')
        det.add_lane_area_detector(id='9_15', edge='17', lane=1, end_pos=20, type='saturation')
        det.add_lane_area_detector(id='9_16', edge='68', lane=0, end_pos=20, type='saturation')
        det.add_lane_area_detector(id='9_17', edge='68', lane=1, end_pos=20, type='saturation')
        det.add_lane_area_detector(id='9_18', edge='12', lane=0, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='9_19', edge='12', lane=1, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='9_20', edge='12', lane=2, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='9_21', edge='83', lane=0, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='9_22', edge='71', lane=0, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='9_23', edge='71', lane=1, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='9_24', edge='71', lane=2, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='9_25', edge='17', lane=0, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='9_26', edge='17', lane=1, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='9_27', edge='11', lane=0, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='9_28', edge='11', lane=1, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='9_29', edge='11', lane=2, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='9_30', edge='68', lane=0, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='9_31', edge='68', lane=1, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='9_32', edge='85', lane=0, pos=133.1, end_pos=333.1, type='numerical')
        det.add_lane_area_detector(id='9_33', edge='85', lane=1, pos=133.1, end_pos=333.1, type='numerical')
        det.add_lane_area_detector(id='9_34', edge='85', lane=2, pos=133.1, end_pos=333.1, type='numerical')
        det.add_lane_area_detector(id='9_35', edge='84', lane=0, end_pos=-1, type='exit')
        det.add_lane_area_detector(id='9_36', edge='86', lane=0, end_pos=200, type='exit')
        det.add_lane_area_detector(id='9_37', edge='86', lane=1, end_pos=200, type='exit')
        det.add_lane_area_detector(id='9_38', edge='86', lane=2, end_pos=200, type='exit')
        det.add_lane_area_detector(id='9_39', edge='67', lane=0, end_pos=-1, type='exit')
        det.add_lane_area_detector(id='9_40', edge='67', lane=1, end_pos=-1, type='exit')
        det.add_lane_area_detector(id='9_41', edge='72[0]', lane=0, end_pos=-1, type='exit')
        det.add_lane_area_detector(id='9_42', edge='72[0]', lane=1, end_pos=-1, type='exit')
        det.add_lane_area_detector(id='9_43', edge='72[0]', lane=2, end_pos=-1, type='exit')
        # Intersection 12
        det.add_lane_area_detector(id='12_1', edge='104', lane=0, pos=17.8, end_pos=37.8, type='boolean')
        det.add_lane_area_detector(id='12_2', edge='104', lane=1, pos=17.8, end_pos=37.8, type='boolean')
        det.add_lane_area_detector(id='12_3', edge='15', lane=0, pos=71.4, end_pos=91.4, type='boolean')
        det.add_lane_area_detector(id='12_4', edge='103', lane=0, pos=117.85, end_pos=137.85, type='boolean')
        det.add_lane_area_detector(id='12_5', edge='103', lane=1, pos=117.85, end_pos=137.85, type='boolean')
        det.add_lane_area_detector(id='12_6', edge='103', lane=0, end_pos=20, type='saturation')
        det.add_lane_area_detector(id='12_7', edge='103', lane=1, end_pos=20, type='saturation')
        det.add_lane_area_detector(id='12_8', edge='15', lane=0, end_pos=20, type='saturation')
        det.add_lane_area_detector(id='12_9', edge='13', lane=0, end_pos=20, type='saturation')
        det.add_lane_area_detector(id='12_10', edge='104', lane=0, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='12_11', edge='104', lane=1, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='12_12', edge='15', lane=0, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='12_13', edge='103', lane=0, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='12_14', edge='103', lane=1, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='12_15', edge='13', lane=0, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='12_16', edge='24', lane=0, end_pos=-1, type='exit')
        det.add_lane_area_detector(id='12_17', edge='49', lane=0, end_pos=-1, type='exit')
        det.add_lane_area_detector(id='12_18', edge='14', lane=0, end_pos=-1, type='exit')
        det.add_lane_area_detector(id='12_19', edge='16', lane=0, end_pos=-1, type='exit')
        # Intersection 63-82
        det.add_lane_area_detector(id='63_1', edge='188', lane=0, pos=64.3, end_pos=84.3, type='boolean')
        det.add_lane_area_detector(id='63_2', edge='153', lane=0, pos=376, end_pos=396, type='boolean')
        det.add_lane_area_detector(id='63_3', edge='88', lane=0, pos=30.8, end_pos=50.8, type='boolean')
        det.add_lane_area_detector(id='63_4', edge='188', lane=0, end_pos=20, type='saturation')
        det.add_lane_area_detector(id='63_5', edge='153', lane=0, end_pos=20, type='saturation')
        det.add_lane_area_detector(id='63_6', edge='88', lane=0, end_pos=20, type='saturation')
        det.add_lane_area_detector(id='63_7', edge='188', lane=0, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='63_8', edge='153', lane=0, pos=196, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='63_9', edge='88', lane=0, end_pos=-1, type='numerical')
        det.add_lane_area_detector(id='63_10', edge='187', lane=0, end_pos=-1, type='exit')
        det.add_lane_area_detector(id='63_11', edge='87[0]', lane=0, end_pos=-1, type='exit')
        det.add_lane_area_detector(id='63_12', edge='20001+87[1][0]', lane=0, end_pos=-1, type='exit')
        det.add_lane_area_detector(id='63_13', edge='m90', lane=0, end_pos=-1, type='exit')
        det.add_lane_area_detector(id='82_1', edge='189[1][1]', lane=0, pos=151.55, end_pos=171.55, type='boolean')
        det.add_lane_area_detector(id='82_2', edge='187', lane=0, pos=64.3, end_pos=84.3, type='boolean')
        det.add_lane_area_detector(id='82_3', edge='189[1][1]', lane=0, end_pos=20, type='saturation')
        det.add_lane_area_detector(id='82_4', edge='187', lane=0, end_pos=20, type='saturation')
        det.add_lane_area_detector(id='82_5', edge='189[1][1]', lane=0, end_pos=-1, type='saturation')
        det.add_lane_area_detector(id='82_6', edge='187', lane=0, end_pos=-1, type='saturation')
        return det

    DETECTORS_210 = {
        0: {
            'boolean': ['34_3', '34_4', '34_5', '27_1', '27_2', '27_3', '27_7', '27_8'],
            'saturation': ['34_7', '34_8', '34_9', '27_16', '27_17'],  # '27_13', '27_14', '27_15',,
            'numerical': ['34_13', '34_14', '34_15', '27_20', '27_21', '27_22', '27_28', '27_29', '27_31', '27_32'],
            'exit': ['34_16', '34_17', '34_18', '34_19', '27_38', '27_39', '27_40', '27_42', '27_43', '27_45', '27_46']
        },
        2: {
            'boolean': ['34_1', '34_2', '27_9', '27_3'],
            'saturation': ['27_18'],
            'numerical': ['34_10', '34_11', '34_12', '27_22', '27_30', '27_30'],
            'exit': ['34_16', '34_17', '27_41', '27_45', '27_46']
        },
        4: {
            'boolean': ['34_1', '34_2', '27_4', '27_5', '27_6', '27_10', '27_11', '27_12'],
            'saturation': [],
            'numerical': ['34_10', '34_11', '34_12', '27_34', '27_35', '27_36', '27_37', '27_23', '27_24', '27_25', '27_26', '27_27'],
            'exit': ['34_16', '34_17', '27_38', '27_41', '27_42', '27_44', '27_45', '27_46']
        },
    }

    DETECTORS_221 = {
        0: {
            'boolean': ['1_1', '1_2', '1_3', '1_4', '1_5', '1_6'],
            'saturation': ['1_12', '1_13', '1_14', '1_15', '1_16', '1_17'],
            'numerical': ['1_21', '1_22', '1_23', '1_24', '1_25', '1_26'],
            'exit': ['1_37', '1_38', '1_39', '1_40', '1_41', '1_42', '1_43']
        },
        3: {
            'boolean': ['1_7', '1_8', '1_9', '1_10', '1_11'],
            'saturation': ['1_18', '1_19', '1_20'],
            'numerical': ['1_27', '1_28', '1_29', '1_30', '1_31', '1_32', '1_33', '1_34', '1_35', '1_36'],
            'exit': ['1_37', '1_38', '1_40', '1_41', '1_42', '1_43']
        }
    }

    DETECTORS_235 = {
        0: {
            'boolean': ['78_4', '78_5', '78_6'],
            'saturation': ['78_11', '78_12', '78_13'],
            'numerical': ['78_17', '78_18', '78_19'],
            'exit': ['78_20', '78_21', '78_22', '78_23', '78_24']
        },
        2: {
            'boolean': ['78_7', '78_8', '78_9'],
            'saturation': [],
            'numerical': ['78_19_c', '78_19_d', '78_19_e', '78_19_f'],
            'exit': ['78_20', '78_21', '78_22', '78_23', '78_24']
        },
        4: {
            'boolean': ['78_1', '78_2', '78_3'],
            'saturation': [],
            'numerical': ['78_14', '78_15', '78_16'],
            'exit': ['78_23', '78_26', '78_27', '78_28']
        },
        6: {
            'boolean': ['78_10'],
            'saturation': [],
            'numerical': ['78_19_b'],
            'exit': ['78_26', '78_29', '78_30']
        },
    }

    DETECTORS_220 = {
        0: {
            'boolean': ['15_3', '15_4', '15_5', '52_3'],
            'saturation': ['15_12', '15_10', '15_11', '52_6'],
            'numerical': ['15_23', '15_18', '15_19', '15_20', '15_21', '15_22', '52_9'],
            'exit': ['52_10', '52_11', '52_12', '52_13', '52_14']
        },
        2: {
            'boolean': ['15_1', '15_2', '52_1', '52_2', '15_24', '15_25', '15_26'],
            'saturation': ['15_6', '15_7', '15_8', '15_9', '52_4', '52_5'],
            'numerical': ['15_13', '15_14', '15_15', '15_16', '15_17', '15_18', '52_7', '52_8'],
            'exit': ['52_12', '52_13', '52_14', '52_15']
        }
    }

    DETECTORS_219 = {
        0: {
            'boolean': ['9_7', '9_8', '9_9', '9_1', '9_2', '9_3'],
            'saturation': ['9_16', '9_21'],
            'numerical': ['9_27', '9_30', '9_18', '9_19', '9_20', '9_21'],
            'exit': ['9_35', '9_36', '9_37', '9_38', '9_39', '9_40', '9_41']
        },
        # 2: {
        #     'boolean': ['9_7', '9_8', '9_9'],
        #     'saturation': ['9_16', '9_17'],
        #     'numerical': ['9_27', '9_28', '9_29', '9_30', '9_31'],
        #     'exit': ['15_16', '15_13', '15_14']
        # },
        2: {
            'boolean': ['9_4', '9_5', '9_10', '9_11'],
            'saturation': ['9_14'],
            'numerical': ['9_22', '9_23', '9_25', '9_32', '9_33'],
            'exit': ['9_35', '9_36', '9_37', '9_39', '9_40', '9_41', '9_42', '9_43']
        },
        4: {
            'boolean': ['9_6', '9_12'],
            'saturation': ['9_15'],
            'numerical': ['9_24', '9_26', '9_34'],
            'exit': ['9_35', '9_40']
        }
    }

    DETECTORS_273 = {
        0: {
            'boolean': ['12_4', '12_1', '12_2'],
            'saturation': ['12_9', '12_6'],
            'numerical': ['12_10', '12_11', '12_15', '12_13'],
            'exit': ['12_16', '12_17', '12_18', '12_19']
        },
        2: {
            'boolean': ['12_2', '12_5'],
            'saturation': ['12_9', '12_7'],
            'numerical': ['12_14', '12_11', '12_15'],
            'exit': ['12_17', '12_19']
        },
        4: {
            'boolean': ['12_3'],
            'saturation': ['12_8'],
            'numerical': ['12_12'],
            'exit': ['12_16', '12_17', '12_18', '12_19']
        },
    }

    DETECTORS_209 = {
        0: {
            'boolean': ['63_1'],
            'saturation': ['63_4'],
            'numerical': ['63_7'],
            'exit': ['63_10', '63_11', '63_12', '63_13']
        },
        2: {
            'boolean': ['63_2'],
            'saturation': ['63_5'],
            'numerical': ['63_8'],
            'exit': ['63_10', '63_11', '63_12', '63_13']
        }
    }

if __name__ == '__main__':
    bologna = BolognaNetwork(0.000001, 3600)
    det = bologna.generate_detectors()
    det.build({'detectors': 'acosta_detectors.add.xml'})

