# Path: controller/actor.py
# class PoupoolActor(pykka.ThreadingActor):
# 
#     def __init__(self):
#         super().__init__()
#         self._proxy = self.actor_ref.proxy()
#         self.__timer = None
# 
#     def on_failure(self, exception_type, exception_value, traceback):
#         # The actor is going to die
#         logger.fatal(exception_type, exception_value, traceback)
# 
#     def on_stop(self):
#         self.do_cancel()
# 
#     def get_actor(self, name):
#         fsm = pykka.ActorRegistry.get_by_class_name(name)
#         if fsm:
#             return fsm[0].proxy()
#         logger.critical("Actor %s not found!!!" % name)
#         return None
# 
#     def __do_cancel(self):
#         if self.__timer:
#             self.__timer.cancel()
#             self.__timer = None
# 
#     def do_cancel(self):
#         self.__do_cancel()
# 
#     def do_delay(self, delay, method, *args, **kwargs):
#         assert type(method) == str
#         assert delay >= 0
#         # Stop an already running timer
#         self.__do_cancel()
#         func = getattr(self._proxy, method)
#         if delay > 0:
#             self.__timer = Timer(delay, func.defer, *args, **kwargs)
#             self.__timer.start()
#         else:
#             func.defer(*args, **kwargs)
# 
# Path: controller/actor.py
# class PoupoolModel(Machine):
# 
#     def __init__(self, *args, **kwargs):
#         kwargs.setdefault("before_state_change", []).extend(["do_cancel", self.__update_state_time])
#         super().__init__(
#             auto_transitions=False,
#             ignore_invalid_triggers=True,
#             *args,
#             **kwargs
#         )
#         self.__state_time = None
# 
#     def __update_state_time(self):
#         self.__state_time = datetime.now()
# 
#     def get_time_in_state(self):
#         return datetime.now() - self.__state_time


import logging
from .actor import PoupoolActor
from .actor import PoupoolModel
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

# from transitions.extensions import GraphMachine as Machine

logger = logging.getLogger(__name__)


class Light(PoupoolActor):

    STATE_REFRESH_DELAY = 10

    states = ["halt", "on"]

    def __init__(self, encoder, devices):
        super().__init__()
        self.__encoder = encoder
        self.__devices = devices
        # Initialize the state machine
        self.__machine = PoupoolModel(model=self, states=Light.states, initial="halt")

        self.__machine.add_transition("on", "halt", "on")
        self.__machine.add_transition("halt", "on", "halt")

    def on_enter_halt(self):
        logger.info("Entering halt state")
        self.__encoder.light_state("halt")
        self.__devices.get_valve("light").off()


# Path: controller/actor.py
# class PoupoolActor(pykka.ThreadingActor):
# 
#     def __init__(self):
#         super().__init__()
#         self._proxy = self.actor_ref.proxy()
#         self.__timer = None
# 
#     def on_failure(self, exception_type, exception_value, traceback):
#         # The actor is going to die
#         logger.fatal(exception_type, exception_value, traceback)
# 
#     def on_stop(self):
#         self.do_cancel()
# 
#     def get_actor(self, name):
#         fsm = pykka.ActorRegistry.get_by_class_name(name)
#         if fsm:
#             return fsm[0].proxy()
#         logger.critical("Actor %s not found!!!" % name)
#         return None
# 
#     def __do_cancel(self):
#         if self.__timer:
#             self.__timer.cancel()
#             self.__timer = None
# 
#     def do_cancel(self):
#         self.__do_cancel()
# 
#     def do_delay(self, delay, method, *args, **kwargs):
#         assert type(method) == str
#         assert delay >= 0
#         # Stop an already running timer
#         self.__do_cancel()
#         func = getattr(self._proxy, method)
#         if delay > 0:
#             self.__timer = Timer(delay, func.defer, *args, **kwargs)
#             self.__timer.start()
#         else:
#             func.defer(*args, **kwargs)
# 
# Path: controller/actor.py
# class PoupoolModel(Machine):
# 
#     def __init__(self, *args, **kwargs):
#         kwargs.setdefault("before_state_change", []).extend(["do_cancel", self.__update_state_time])
#         super().__init__(
#             auto_transitions=False,
#             ignore_invalid_triggers=True,
#             *args,
#             **kwargs
#         )
#         self.__state_time = None
# 
#     def __update_state_time(self):
#         self.__state_time = datetime.now()
# 
#     def get_time_in_state(self):
#         return datetime.now() - self.__state_time


# Path: controller/light.py
import logging
from .actor import PoupoolActor
from .actor import PoupoolModel

# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

# from transitions.extensions import GraphMachine as Machine

logger = logging.getLogger(__name__)


class Light(PoupoolActor):

    STATE_REFRESH_DELAY = 10

    states = ["halt", "on"]

    def __init__(self, encoder, devices):
        super().__init__()
        self.__encoder = encoder
        self.__devices = devices
        # Initialize the state machine
        self.__machine = PoupoolModel(model=self, states=Light.states, initial="halt")

        self.__machine.add_transition("on", "halt", "on")
        self.__machine.add_transition("halt", "on", "halt")

    def on_enter_halt(self):
        logger.info("Entering halt state")
        self.__encoder.light_state("halt")
        self.__devices.get_valve("light").off()


    def on_enter_on(self):