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:
			user = Config().feefie_client_user
		except:
			user = 'pl'

		try:
			clid = Config().feefie_client_id
		except:
			clid = self.random_client_id()
			

		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 random_client_id(self):
		if (self.client_id):
			return self.client_id
		else:
			self.client_id = base64.urlsafe_b64encode(os.urandom(12))
			return self.client_id

	
	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:
			user = Config().feefie_client_user
		except:
			user = 'pl'

		try:
			clid = Config().feefie_client_id
		except:
			clid = self.random_client_id()

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