class Token:
    def __init__(
            self,
            manager,
            input_id,
            parent_token,
            position_id,
            kv_cache_idx,
            hidden_state=None,
            fixed=False,
            score=1.0,
    ):
        self.manager = manager

        self.input_id = input_id
        self.parent_token = parent_token
        self.position_id = position_id
        self.kv_cache_idx = kv_cache_idx
        self.draft_kv_cache_idx = None

        self.hidden_state = hidden_state
        self.fixed = fixed
        self.is_leaf = True
        self.score = score

    def __del__(self):
        if self.kv_cache_idx is not None:
            self.manager.kvcache_pool.free([self.kv_cache_idx])
        if self.draft_kv_cache_idx is not None:
            self.manager.draft_kvcache_pool.free([self.draft_kv_cache_idx])

    def __hash__(self):
        return hash(f"{self.input_id}_{self.position_id}")

    def __le__(self, other):
        return self.score >= other.score  # reversed for min heap

    def __lt__(self, other):
        return self.score > other.score  # reversed for min heap

    def __repr__(self):
        return f"Token(id={id(self)}, input_id={self.input_id}, position_id={self.position_id}, score={self.score:.3f}, parent={id(self.parent_token)})"

    def __str__(self):
        return self.__repr__()
