class Attribute(object):
    value = None
    validators = []

    def __init__(self, entity, **kwargs):
        self.entity = entity
        for key, value in kwargs.iteritems():
            if hasattr(self, key):
                setattr(self, key, value)
        
    def __cmp__(self, other):
        if self.value > other:
            return 1
        elif self.value < other:
            return -1
        else:
            return 0
            
    def use(self, mod = 0, times = 1):
        """
        Uses the attribute, returning whatever is yielded by using it `value` times, and adjusting accordingly.
        """
        return (self.value * times) + mod
    
    def validate(self):
        """
        Runs validators on the attribute, which 
        """
        for validator in self.validators:
            validator(self)
        

class ClassicAttribute(Attribute):
    maximum = None
    minimum = None
        
    def _validate_value(self):
        """
        Enforces that `value` not exceed `maximum`, nor fall below `minimum`.
        """
        if self.maximum and self.value > self.maximum:
            self.value = self.maximum
        elif self.minimum and self.value < self.minimum:
            self.value = self.minimum
        
    def _validate_max(self):
        if self.maximum and self.minimum and self.maximum < self.minimum:
            self.maximum = self.minimum
            
    def _validate_min(self):
        if self.maximum and self.minimum and self.maximum < self.minimum:
            self.minimum = self.maximum
            
    def __setattr__(self, name, value):
        super(ClassicAttribute, self).__setattr__(name, value)
        if name == 'value':
            self._validate_value()
        elif name == 'maximum':
            self._validate_max()
        elif name == 'minimum':
            self._validate_min()
        
class CurrencyAttribute(Attribute):
    yield = 0 # amount generated by expending 1 value.

    def use(self, **kwargs):
        self.value -= kwargs.get('times', 1)
        return ((self.yield + kwargs.get('pre_mod', 0)) * kwargs.get('times', 1)) + kwargs.get('post_mod', 0)
        
class DerivedAttributed(Attribute):
    """
    Attribute whose value is consistently derived from another attribute.
    """
    attrs = None
    setter = None
    value = self.use()
        
    def use(self, **kwargs):
        """
        Updates `value` and returns it accordingly to the modifications.
        """
        self.value = self.setter(self.attrs)
        return (self.value * kwargs.get('times', 1)) + kwargs.get('mod')
