""" The BaseContainer class for use in instances of HR. """

from galeshapley import BasePlayer


class BaseContainer(BasePlayer):
    """A class to represent a base_container in an instance of HR. Also used as a
    parent class to ``Resource`` and ``Container``.

    Parameters
    ----------
    name : object
        An identifier. This should be unique and descriptive.
    capacity : int
        The maximum number of matches the base_container can have.
    _original_capacity : int
        A record of the player's original capacity in case it is altered when
        passed to a game.

    Attributes
    ----------
    prefs : list of Player
        The base_container's preferences. Defaults to ``None`` and is updated using
        the ``set_prefs`` method.
    _original_prefs : list of Player
        A record of the player's original preferences.
    pref_names : list
        A list of the names in ``prefs``. Updates with ``prefs`` via the
        ``set_prefs`` method.
    matching : list of Player
        The current matches of the base_container. An empty list if currently
        unsubscribed.
    """

    def __init__(self, name, capacity):

        super().__init__(name)
        self._capacity = capacity
        self._original_capacity = capacity
        self.matching = []

    def _match(self, part):
        """ Add ``part`` to the base_container's matching, and then sort it. """

        self.matching.append(part)
        self.matching.sort(key=self.prefs.index)

    def _unmatch(self, part):
        """ Remove ``part`` from the base_container's galeshapley. """

        matching = self.matching[:]
        matching.remove(part)
        self.matching = matching

    def oversubscribed_message(self):

        return (
            f"{self} is matched to {self.matching} which is over their "
            f"capacity of {self.capacity}."
        )

    def get_favourite(self):
        """Get the base_container's favourite part with whom they are not
        currently matched. If no such part exists, return ``None``."""

        for player in self.prefs:
            if player not in self.matching:
                return player

        return None

    def get_worst_match(self):
        """Get the player's worst current match. This assumes that the matching
        is in order of preference."""

        return self.matching[-1]

    def get_successors(self):
        """ Get the successors to the player's worst current match. """

        idx = self.prefs.index(self.get_worst_match())
        return self.prefs[idx + 1 :]

    def get_capacity(self):
        if callable(self._capacity):
            return self._capacity()
        else:
            return self._capacity

    def set_capacity(self, c):
        self._capacity = c

    def del_capacity(self):
        del self._capacity

    def check_if_match_is_unacceptable(self, **kwargs):
        """ Check the acceptability of the current matches. """

        issues = []
        for other in self.matching:
            if other not in self.prefs:
                issues.append(self.not_in_preferences_message(other))

        return issues

    def check_if_oversubscribed(self):
        """ Check whether the player has too many matches. """

        if len(self.matching) > self.capacity:
            return self.oversubscribed_message()

        return False

    capacity = property(get_capacity, set_capacity, del_capacity)