import threading
import requests, json

from planetstack.config import Config
from observer.deleters import deleters

import os
import base64
from fofum import Fofum
import json

# decorator that marks dispatachable event methods    
def event(func):
    setattr(func, 'event', func.__name__)
    return func         

class EventHandler:
    # This code is currently not in use.
    def __init__(self):
        pass 

    @staticmethod
    def get_events():
        events = []
        for name in dir(EventHandler):
            attribute = getattr(EventHandler, name)
            if hasattr(attribute, 'event'):
                events.append(getattr(attribute, 'event'))
        return events

    def dispatch(self, event, *args, **kwds):
        if hasattr(self, event):
            return getattr(self, event)(*args, **kwds)
            
        
class EventSender:
    def __init__(self,user=None,clientid=None):
        try:
            clid = Config().feefie_client_id
            user = Config().feefie_client_user
        except:
            clid = 'planetstack_core_team'
            user = 'pl'

        self.fofum = Fofum(user=user)
        self.fofum.make(clid)

    def fire(self,**args):
        self.fofum.fire(json.dumps(args))

class EventListener:
    def __init__(self,wake_up=None):
        self.handler = EventHandler()
        self.wake_up = wake_up

    def handle_event(self, payload):
        payload_dict = json.loads(payload)

        try:
            deletion = payload_dict['deletion_flag']
            if (deletion):
                model = payload_dict['model']
                pk = payload_dict['pk']

                for deleter in deleters[model]:
                    deleter(pk)
        except:
            deletion = False

        if (not deletion and self.wake_up):
            self.wake_up()
        

    def run(self):
        # This is our unique client id, to be used when firing and receiving events
        # It needs to be generated once and placed in the config file

        try:
            clid = Config().feefie_client_id
            user = Config().feefie_client_user
        except:
            clid = 'planetstack_core_team'
            user = 'pl'

        f = Fofum(user=user)
        
        listener_thread = threading.Thread(target=f.listen_for_event,args=(clid,self.handle_event))
        listener_thread.start()
