# Path: kotori/vendor/ilaundry/node/bricks.py
# class BinaryInputPort(object):
# 
#     def __init__(self, portname, signal=None):
#         self.portname = portname
#         self.signal = signal
# 
#         # detect edge on port
#         self.gpio = GpioInput(self.portname, self.sensor_on)
# 
#     def sensor_on(self, port):
#         print("DEBUG: Port {0} EVENT".format(self.portname))
# 
#         # signal sensor-on
#         if self.signal:
#             self.signal.set(True)
# 
#     # currently defunct
#     """
#     def sensor_off(self, port):
#         print "SENSOR OFF:", port
# 
#         # signal sensor-off
#         if self.callback:
#             self.callback(False)
#     """
# 
# class BinaryOutputPort(object):
# 
#     # TODO: handle different ports, not only GPIO
# 
#     #HIGH = 1
#     #LOW = 2
#     #BLINK = 3
# 
#     def __init__(self, portname):
#         self.portname = portname
#         #self.flavor = flavor or self.HIGH
#         self.gpio = GpioOutput(self.portname)
# 
#         #self.modifier = modifier
# 
#     def set(self, *args, **kwargs):
#         print("DEBUG: Port {0} ON".format(self.portname))
#         self.gpio.on()
# 
#         # signal gpio port
#         #if self.flavor == self.HIGH:
#         #elif self.flavor == self.BLINK:
# 
#     def unset(self):
#         print("DEBUG: Port {0} OFF".format(self.portname))
# 
#         #self.transition_stop()
# 
#         # signal gpio port
#         self.gpio.off()
# 
# class TimedBinarySemaphore(object):
# 
#     def __init__(self, holdtime=None, callback=None):
#         self.holdtime = holdtime
#         self.callback = callback
#         self.timer = None
# 
#     def set(self, *args, **kwargs):
#         #print "SEMAPHORE SET:  ", self.port
# 
#         # signal actor-on
#         if self.callback:
#             self.callback(True, *args, **kwargs)
# 
#         # start/reset timer for motion-off signal
#         if self.holdtime:
#             #print "SEMAPHORE SET:  ", self.port, "holding for {0} seconds".format(self.holdtime)
#             if self.timer and not self.timer.called:
#                 self.timer.cancel()
#             self.timer = reactor.callLater(self.holdtime, self.unset)
# 
#     def unset(self, *args, **kwargs):
#         #print "SEMAPHORE UNSET:", self.port
# 
#         # signal sensor-off
#         if self.callback:
#             self.callback(False, *args, **kwargs)
# 
# class Blinker(object):
# 
#     def __init__(self, port, interval=0.5):
#         self.port = port
#         self.interval = interval
#         self.state = None
#         self.transition = None
# 
#     def set(self, *args, **kwargs):
#         self.blink()
# 
#     def unset(self):
#         self.transition_stop()
#         self.port.unset()
# 
#     def blink(self):
#         self.transition_stop()
#         self.transition = LoopingCall(self.blink_task)
#         self.transition.start(self.interval)
# 
#     def transition_stop(self):
#         if self.transition and self.transition.running:
#             self.transition.stop()
# 
#     def blink_task(self):
#         if self.state:
#             self.state = False
#             self.port.set()
#         else:
#             self.state = True
#             self.port.unset()
# 
# class BinaryTopicSignal(object):
#     """Receives a signal from bus network and signals receiver (actor/port) accordingly"""
# 
#     def __init__(self, bus, topic, signal):
#         self.bus = bus
#         self.topic = topic
#         self.signal = signal
#         self.bus.subscribe(self.topic, self.process_event)
# 
#     def process_event(self, topic, state):
#         if state:
#             self.signal.set()
#         else:
#             self.signal.unset()


from kotori.vendor.ilaundry.node.bricks import BinaryInputPort, BinaryOutputPort, TimedBinarySemaphore, Blinker, BinaryTopicSignal
    def state_for_display(state):
        return state and 'enabled' or 'disabled'

    def run_filters(self, state):
        if self.event_filters:
            for event_filter in self.event_filters:
                state = event_filter(state)
        return state

    def publish(self, name, data):
        payload = {'node_id': self.node_id}
        payload.update(data)
        self.bus.publish(name, payload)


class ActivityMonitor(FeatureBase):

    def start(self, holdtime):
        """
        Feature for detecting activity of arbitrary creatures and reacting on that.

        - When triggered:
            - Turn LED into slow blinking mode
            - Publish "activity(True)" message to bus network
        - After "holdtime":
            - Turn LED off
            - Publish "activity(False)" message to bus network
        """

        # define a slow blinking light (default interval 0.5s)

# Path: kotori/vendor/ilaundry/node/bricks.py
# class BinaryInputPort(object):
# 
#     def __init__(self, portname, signal=None):
#         self.portname = portname
#         self.signal = signal
# 
#         # detect edge on port
#         self.gpio = GpioInput(self.portname, self.sensor_on)
# 
#     def sensor_on(self, port):
#         print("DEBUG: Port {0} EVENT".format(self.portname))
# 
#         # signal sensor-on
#         if self.signal:
#             self.signal.set(True)
# 
#     # currently defunct
#     """
#     def sensor_off(self, port):
#         print "SENSOR OFF:", port
# 
#         # signal sensor-off
#         if self.callback:
#             self.callback(False)
#     """
# 
# class BinaryOutputPort(object):
# 
#     # TODO: handle different ports, not only GPIO
# 
#     #HIGH = 1
#     #LOW = 2
#     #BLINK = 3
# 
#     def __init__(self, portname):
#         self.portname = portname
#         #self.flavor = flavor or self.HIGH
#         self.gpio = GpioOutput(self.portname)
# 
#         #self.modifier = modifier
# 
#     def set(self, *args, **kwargs):
#         print("DEBUG: Port {0} ON".format(self.portname))
#         self.gpio.on()
# 
#         # signal gpio port
#         #if self.flavor == self.HIGH:
#         #elif self.flavor == self.BLINK:
# 
#     def unset(self):
#         print("DEBUG: Port {0} OFF".format(self.portname))
# 
#         #self.transition_stop()
# 
#         # signal gpio port
#         self.gpio.off()
# 
# class TimedBinarySemaphore(object):
# 
#     def __init__(self, holdtime=None, callback=None):
#         self.holdtime = holdtime
#         self.callback = callback
#         self.timer = None
# 
#     def set(self, *args, **kwargs):
#         #print "SEMAPHORE SET:  ", self.port
# 
#         # signal actor-on
#         if self.callback:
#             self.callback(True, *args, **kwargs)
# 
#         # start/reset timer for motion-off signal
#         if self.holdtime:
#             #print "SEMAPHORE SET:  ", self.port, "holding for {0} seconds".format(self.holdtime)
#             if self.timer and not self.timer.called:
#                 self.timer.cancel()
#             self.timer = reactor.callLater(self.holdtime, self.unset)
# 
#     def unset(self, *args, **kwargs):
#         #print "SEMAPHORE UNSET:", self.port
# 
#         # signal sensor-off
#         if self.callback:
#             self.callback(False, *args, **kwargs)
# 
# class Blinker(object):
# 
#     def __init__(self, port, interval=0.5):
#         self.port = port
#         self.interval = interval
#         self.state = None
#         self.transition = None
# 
#     def set(self, *args, **kwargs):
#         self.blink()
# 
#     def unset(self):
#         self.transition_stop()
#         self.port.unset()
# 
#     def blink(self):
#         self.transition_stop()
#         self.transition = LoopingCall(self.blink_task)
#         self.transition.start(self.interval)
# 
#     def transition_stop(self):
#         if self.transition and self.transition.running:
#             self.transition.stop()
# 
#     def blink_task(self):
#         if self.state:
#             self.state = False
#             self.port.set()
#         else:
#             self.state = True
#             self.port.unset()
# 
# class BinaryTopicSignal(object):
#     """Receives a signal from bus network and signals receiver (actor/port) accordingly"""
# 
#     def __init__(self, bus, topic, signal):
#         self.bus = bus
#         self.topic = topic
#         self.signal = signal
#         self.bus.subscribe(self.topic, self.process_event)
# 
#     def process_event(self, topic, state):
#         if state:
#             self.signal.set()
#         else:
#             self.signal.unset()


# Path: kotori/vendor/ilaundry/node/feature.py
from kotori.vendor.ilaundry.node.bricks import BinaryInputPort, BinaryOutputPort, TimedBinarySemaphore, Blinker, BinaryTopicSignal

    def state_for_display(state):
        return state and 'enabled' or 'disabled'

    def run_filters(self, state):
        if self.event_filters:
            for event_filter in self.event_filters:
                state = event_filter(state)
        return state

    def publish(self, name, data):
        payload = {'node_id': self.node_id}
        payload.update(data)
        self.bus.publish(name, payload)


class ActivityMonitor(FeatureBase):

    def start(self, holdtime):
        """
        Feature for detecting activity of arbitrary creatures and reacting on that.

        - When triggered:
            - Turn LED into slow blinking mode
            - Publish "activity(True)" message to bus network
        - After "holdtime":
            - Turn LED off
            - Publish "activity(False)" message to bus network
        """

        # define a slow blinking light (default interval 0.5s)

        self.blinking_light = Blinker(SignalLight(self.PORT_LED))