import logging

from abc import ABCMeta, abstractmethod
from threading import Event, Thread

from kyco.utils import listen_to

log = logging.getLogger('Kyco')

__all__ = ('KycoCoreNApp', 'KycoNApp')

class KycoNApp(Thread, metaclass=ABCMeta):
    """Base class for any KycoNApp to be developed."""
    __event = Event()
    EXECUTE_INTERVAL = 30

    def __init__(self, controller, **kwargs):
        """Go through all of the instance methods and selects those that have
        the events attribute, then creates a dict containing the event_name
        and the list of methods that are responsible for handling such event.

        At the end, the setUp method is called as a complement of the init
        process.
        """
        Thread.__init__(self, daemon=False)
        self.controller = controller
        self._listeners = {'kyco/core.shutdown': [self._shutdown_handler]}

        handler_methods = [getattr(self, method_name) for method_name in
                           dir(self) if method_name[0] != '_' and
                           callable(getattr(self, method_name)) and
                           hasattr(getattr(self, method_name), 'events')]

        # Building the listeners dictionary
        for method in handler_methods:
            for event_name in method.events:
                if event_name not in self._listeners:
                    self._listeners[event_name] = []
                self._listeners[event_name].append(method)

        # TODO: Load NApp data based on its json file
        # self.name is already used in Thread class. Other attribute should be
        # used

    def run(self):
        """This method will call the setup and the execute methos.

        It should not be overriden."""
        log.info("Running %s App", self.name)
        # TODO: If the setup method is blocking, then the execute method will
        #       never be called. Should we execute it inside a new thread?
        self.setup()
        self._execute_loop()

    @listen_to('kyco/core.shutdown')
    def _shutdown_handler(self, event):
        self.__event.set()
        self.shutdown()

    def _execute_loop(self):
        while(not self.__event.is_set()):
            self.execute()
            self.__event.wait(self.EXECUTE_INTERVAL)

    @abstractmethod
    def setup(self):
        """'Replaces' the 'init' method for the KycoApp subclass.

        The setup method is automatically called by the run method.
        Users shouldn't call this method directly."""
        pass

    @abstractmethod
    def execute(self):
        """Method executed in a loop until the signal 'kyco/core.shutdown'
        is received.

        The execute method is called by KycoNApp class.
        Users shouldn't call this method directly."""
        pass

    @abstractmethod
    def shutdown(self):
        """Called before the app is unloaded, before the controller is stopped.

        The user implementation of this method should do the necessary routine
        for the user App and also it is a good moment to break the loop of the
        execute method if it is in a loop.

        This methods is not going to be called directly, it is going to be
        called by the _shutdown_handler method when a KycoShutdownEvent is
        sent."""
        pass


class KycoCoreNApp(KycoNApp):
    """Base class for any KycoCoreNApp to be developed."""
    pass

@@ -316,34 +316,8 @@
 nt()
-%0A    EXECUTE_INTERVAL = 30
 %0A%0A  
@@ -852,16 +852,170 @@
 andler%5D%7D
+%0A        #: int: Seconds to sleep before next call to :meth:%60execute%60. If%0A        #: negative, run :meth:%60execute%60 only once.%0A        self.__interval = -1
 %0A%0A      
@@ -1734,16 +1734,554 @@
 # used%0A%0A
+    def execute_as_loop(self, interval):%0A        %22%22%22Run :meth:%60execute%60 within a loop. Call this method during setup.%0A%0A        By calling this method, the application does not need to worry about%0A        loop details such as sleeping and stopping the loop when%0A        :meth:%60shutdown%60 is called. Just call this method during :meth:%60setup%60%0A        and implement :meth:%60execute%60 as a single execution.%0A%0A        Args:%0A            interval (int): Seconds between each call to :meth:%60execute%60.%0A        %22%22%22%0A        self.__interval = interval%0A%0A
     def 
@@ -2635,102 +2635,87 @@
 elf.
-_
 execute
-_loop()%0A%0A    @listen_to('kyco/core.shutdown')%0A    def _shutdown_handler(
+()%0A        while self.__interval %3E 0 and not 
 self
-, 
+.__
 event
-):%0A
+.is_set():%0A    
     
@@ -2735,22 +2735,40 @@
 ent.
-set()%0A
+wait(self.__interval)%0A  
         
 self
@@ -2767,100 +2767,103 @@
     
+  
 self.
-shutdown()%0A%0A    def _execute_loop(self):%0A        while(not 
+execute()%0A%0A    @listen_to('kyco/core.shutdown')%0A    def _shutdown_handler(
 self
-.__
+, 
 event
-.is_set()):%0A    
+):%0A
     
@@ -2863,39 +2863,43 @@
 ):%0A        self.
-execute
+__event.set
 ()%0A            s
@@ -2897,51 +2897,22 @@
     
-    
 self.
-__event.wait(self.EXECUTE_INTERVAL
+shutdown(
 )%0A%0A 

Allow execute() to run only once