import abc


class PhoneContext:
    """Keeps track of current state of phone"""
    def __init__(self, state):
        self.set_state(state)

    def set_state(self, state):
        """changes state and prints out new state"""
        print("Setting current state to: " + str(state))
        self.state = state

    def notification(self):
        """calls """
        self.state.notify()


class PhoneState(metaclass=abc.ABCMeta):
    """Phone state interface"""
    @abc.abstractmethod
    def notify(self):
        pass


class SilentPhoneState(PhoneState):
    """Implementation when phone is on silent"""
    def notify(self):
        print("...")

    def __repr__(self):
        return "Silent"


class VibratePhoneState(PhoneState):
    """Implementation when phone is on vibrate"""
    def notify(self):
        print("Bzzz")

    def __repr__(self):
        return "Vibrate"


class RingerPhoneState(PhoneState):
    """Implementation when phone ringer is on"""
    def notify(self):
        print("Ring, ring, ring")

    def __repr__(self):
        return "Ringer"


def main():
    # create context with ringer on and handle notification
    ringer_state = RingerPhoneState()
    context = PhoneContext(ringer_state)
    context.notification()

    # change current state to vibrate and handle notification
    vibrate_state = VibratePhoneState()
    context.set_state(vibrate_state)
    context.notification()

    # change current state to silent and handle notification
    silent_state = SilentPhoneState()
    context.set_state(silent_state)
    context.notification()


if __name__ == "__main__":
    main()
