from .. import weapons


def create_feature(**params):
    """Create a new subclass of ``Feature`` with given default parameters.
    
    Useful for features that haven't been entered into the ``features.py``
    file yet.
    
    Parameters
    ----------
    params : optional
      Saved as attributes of the new class.
    
    Returns
    -------
    NewFeature
      New feature class, subclass of ``Feature``, with given params.
    """
    NewFeature = type('UnknownFeature', (Feature,), params)
    return NewFeature


class Feature():
    """
    Provide full text of rules in documentation
    """
    name = "Generic Feature"
    source = ''  # race, class, background, etc.
    spells_known = ()
    spells_prepared = ()
    needs_implementation = False  # Set to True if need to find way to compute stats

    def __eq__(self, other):
        return (self.name == other.name) and (self.source == other.source)

    def __hash__(self):
        return 0

    def __str__(self):
        return self.name

    def __repr__(self):
        return "\"{:s}\"".format(self.name)
    
    def weapon_func(self, weapon: weapons.Weapon, **kwargs):
        """
        Updates weapon based on the Feature property

        Parameters
        ----------
        weapon
           The weapon to be tested for special bonuses
        kwargs
           Any other key-word arguments the function may require

        Returns
        -------
        weapon
            Updated weapon (perhaps changed damage bonus, etc.)

        """
        return weapon

    def AC_func(self, char, **kwargs):
        """
        Return the alternative AC from having this feat

        The character will take max AC from all available feats / standard AC,
        so the default is to output very low AC

        Parameters
        ----------
        char
           Character object, to check for necessary abilities, etc.
        kwargs
           Any other key-word arguments the function may require

        Returns
        -------
        AC : integer armor class from this feature
        """
        return -100


class FeatureSelector(Feature):
    """
    A feature with multiple possible choices.
    """
    options = dict()

    def __init__(self, feature_choices=[]):
        keep_source = self.source
        # Look for matching feature_choices
        for selection in feature_choices:
            if selection.lower() in self.options():
                new_feat = self.options[selection.lower()]
                self.__dict__.update(new_feat.__dict__)
                new_feat.__init__(self)
                break
        self.source = keep_source
