def _remove(self, node_to_remove: TreeNode) -> None:
     if node_to_remove.is_leaf():
         if node_to_remove.is_left_child():
             node_to_remove.get_parent().set_left_child(None)
         else:
             node_to_remove.get_parent().set_right_child(None)
         node_to_remove.clear_connections()
     elif node_to_remove.has_only_one_child():
         if node_to_remove.get_left_child():
             self._remove_if_only_one_child(node_to_remove,
                                            node_to_remove.get_left_child)
         else:
             self._remove_if_only_one_child(node_to_remove,
                                            node_to_remove.get_right_child)
     else:
         successor = node_to_remove.get_successor()
         node_to_remove.set_key(successor.get_key())
         node_to_remove.set_value(successor.get_value())
         successor.remove_self()