class PathFinder:
    def __init__(self, data):
        self.data = data

    def create_path(self):
        """ Create an eligible solution for data.
        We iteratively add sensors connected to the current solution which taps new targets.
        """
        self.neighbours = []
        self.detected = set([0])
        self.solution = Solution(len(self.data.points))
        self.add_neighbours(0)
        while len(self.neighbours) != 0:
            sum_norm = sum(
                [len(n["neighbours_sens"]) for n in self.neighbours])
            proba = [
                len(n["neighbours_sens"]) / sum_norm for n in self.neighbours
            ]
            neighbour = np.random.choice(self.neighbours, p=proba)
            self.update_neighbours(deepcopy(neighbour))
            self.add_neighbours(neighbour["id"])
            self.solution.add_sensor(neighbour["id"])
        return self.solution

    def add_neighbours(self, target_id):
        """ Update the neighbours list with the neighbours of target_id.
        We add only positions that can tap new targets
        """
        for n in self.data.get_neighbours_com(target_id):
            set_sens = set(self.data.get_neighbours_sens(n) + [n])
            set_reduced = set_sens.difference(self.detected)
            if len(set_reduced) != 0:
                self.neighbours.append({
                    "id": n,
                    "neighbours_sens": set_reduced
                })

    def update_neighbours(self, neighbour_added):
        """ We update detected targets
        We remove newly taped positions from the list of neighbours for potential sensors.
        """
        self.detected = self.detected.union(neighbour_added["neighbours_sens"])
        for n in self.neighbours:
            n["neighbours_sens"] = n["neighbours_sens"].difference(
                neighbour_added["neighbours_sens"])
        self.neighbours = [
            n for n in self.neighbours if n["id"] != neighbour_added["id"]
            and len(n["neighbours_sens"]) != 0
        ]