class SweepLineStatus:
    """ Implemented with AVLTree. """

    def __init__(self):
        self.tree = AVLTree()
        self.size = 0

    def add_segment(self, segment: Segment) -> bool:
        res = self.tree.insert(segment)
        if res:
            self.size += 1
        return res

    def remove_segment(self, segment: Segment) -> bool:
        res = self.tree.delete(segment)
        if res:
            self.size -= 1
        return res

    def get_above_neighbor(self, segment: Segment) -> Optional[Segment]:
        current = self.tree.find(segment)
        assert (current is not None)
        above = self.tree.successor(current)
        if above is not None:
            return above.key
        return None

    def get_below_neighbor(self, segment: Segment) -> Optional[Segment]:
        current = self.tree.find(segment)
        assert (current is not None)
        below = self.tree.predecessor(current)
        if below is not None:
            return below.key
        return below

    def intersection_with_upper(self, segment: Segment) -> Optional[Point]:
        current = self.tree.find(segment)
        assert (current is not None)
        # Successor, because upper's y coordinate is bigger
        upper = self.tree.successor(current)
        if upper is None:
            return None
        else:
            point = calculate_intersection_point(upper.key, segment)
            if point is None:
                return None
            return point

    def intersection_with_lower(self, segment: Segment) -> Optional[Point]:
        current = self.tree.find(segment)
        assert (current is not None)
        lower = self.tree.predecessor(current)
        if lower is None:
            return None
        else:
            point = calculate_intersection_point(lower.key, segment)
            if point is None:
                return None
            return point

    def reach_intersection_of(self, upper: Segment, lower: Segment):
        upper_node = self.tree.find(upper)
        lower_node = self.tree.find(lower)

        temp_key = upper_node.key
        upper_node.key = lower_node.key
        lower_node.key = temp_key