# Copyright 2026 SigmaSRC, Inc. All Rights Reserved.

"""FuelSet class, used in various places."""


class FuelSet(set):
    """A set of Fuel objects.

    Fuel may have its own set operations, so we define a subclass of
    the Python set class. Comparisons with None are special-cased for
    Fuel language semantics.
    """

    def __eq__(self, other):
        if isinstance(other, (set, frozenset)):
            return set.__eq__(self, other)
        elif other is None:
            return False
        else:
            return NotImplemented

    def __ne__(self, other):
        if isinstance(other, (set, frozenset)):
            return set.__ne__(self, other)
        elif other is None:
            return True
        else:
            return NotImplemented

    def __lt__(self, other):
        if isinstance(other, (set, frozenset)):
            return set.__lt__(self, other)
        elif other is None:
            return False
        else:
            return NotImplemented

    def __le__(self, other):
        if isinstance(other, (set, frozenset)):
            return set.__le__(self, other)
        elif other is None:
            return False
        else:
            return NotImplemented

    def __gt__(self, other):
        if isinstance(other, (set, frozenset)):
            return set.__gt__(self, other)
        elif other is None:
            return True
        else:
            return NotImplemented

    def __ge__(self, other):
        if isinstance(other, (set, frozenset)):
            return set.__ge__(self, other)
        elif other is None:
            return True
        else:
            return NotImplemented

    def __repr__(self):
        return 'FuelSet(%s)' % list(self)

    def _wrap(self, result):
        if result is NotImplemented:
            return result
        return FuelSet(result)

    def __and__(self, other):
        return self._wrap(set.__and__(self, other))

    def __rand__(self, other):
        return self._wrap(set.__rand__(self, other))

    def __or__(self, other):
        return self._wrap(set.__or__(self, other))

    def __ror__(self, other):
        return self._wrap(set.__ror__(self, other))

    def __sub__(self, other):
        return self._wrap(set.__sub__(self, other))

    def __rsub__(self, other):
        return self._wrap(set.__rsub__(self, other))

    def __xor__(self, other):
        return self._wrap(set.__xor__(self, other))

    def __rxor__(self, other):
        return self._wrap(set.__rxor__(self, other))

    def __hash__(self):
        raise TypeError("unhashable type: 'FuelSet'")

    # -- Pickle compatibility with Python 2 ----------------------------------
    # Python 2 pickled FuelSet (a set subclass) using protocol 2's NEWOBJ to
    # create an empty instance, then BUILD to call __setstate__ with the
    # internal state.  The state is a tuple whose first element is a dict
    # mapping set elements to True (the internal representation of Python 2's
    # sets.Set).  Python 3's built-in set does not have __setstate__, so
    # unpickling fails without this method.

    def __setstate__(self, state):
        if isinstance(state, tuple):
            # State format: (dict_of_elements,) or (dict_of_elements, ...)
            if state and isinstance(state[0], dict):
                self.update(state[0].keys())
            else:
                for item in state:
                    if isinstance(item, dict):
                        self.update(item.keys())
        elif isinstance(state, dict):
            self.update(state.keys())

    def __reduce__(self):
        return (FuelSet, (list(self),))
