import threading
import requests, json

from planetstack.config import Config
from observer.deleter import Deleter

import uuid
import os
import imp
import inspect
import base64
from fofum import Fofum
import json
import traceback

random_client_id=None
def get_random_client_id():
    global random_client_id

    if (random_client_id is None) and os.path.exists("/opt/planetstack/random_client_id"):
        # try to use the last one we used, if we saved it
        try:
            random_client_id = open("/opt/planetstack/random_client_id","r").readline().strip()
            print "get_random_client_id: loaded %s" % random_client_id
        except:
            print "get_random_client_id: failed to read /opt/planetstack/random_client_id"

    if random_client_id is None:
        random_client_id = base64.urlsafe_b64encode(os.urandom(12))
        print "get_random_client_id: generated new id %s" % random_client_id

        # try to save it for later (XXX: could race with another client here)
        try:
            open("/opt/planetstack/random_client_id","w").write("%s\n" % random_client_id)
        except:
            print "get_random_client_id: failed to write /opt/planetstack/random_client_id"

    return random_client_id

# 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 = get_random_client_id()
                        print "EventSender: no feefie_client_id configured. Using random id %s" % clid

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

	def fire(self,**kwargs):
                kwargs["uuid"] = str(uuid.uuid1())
		self.fofum.fire(json.dumps(kwargs))

class EventListener:
	def __init__(self,wake_up=None):
		self.handler = EventHandler()
		self.wake_up = wake_up
                self.deleters = {}
                self.load_deleter_modules()

        def load_deleter_modules(self, deleter_dir=None):
            if deleter_dir is None:
                if hasattr(Config(), "observer_deleters_dir"):
                    deleter_dir = Config().observer_deleters_dir
                else:
                    deleter_dir = "/opt/planetstack/observer/deleters"

            for fn in os.listdir(deleter_dir):
                pathname = os.path.join(deleter_dir,fn)
                if os.path.isfile(pathname) and fn.endswith(".py") and (fn!="__init__.py"):
                    module = imp.load_source(fn[:-3],pathname)
                    for classname in dir(module):
                        c = getattr(module, classname, None)

                        # make sure 'c' is a descendent of Deleter and has a
                        # provides field (this eliminates the abstract base classes
                        # since they don't have a provides)

                        if inspect.isclass(c) and issubclass(c, Deleter) and hasattr(c,"model") and c.model!=None:
                            modelName = c.model
                            if not modelName in self.deleters:
                                self.deleters[modelName] = []
                            if not (c in self.deleters[modelName]):
                                self.deleters[modelName].append(c)
            print 'loaded deleters: %s' % ",".join(self.deleters.keys())


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

		try:
			deletion = payload_dict.get('delete_flag', False)
			if (deletion):
				model = payload_dict['model']
				pk = payload_dict['pk']
                                model_dict = payload_dict['model_dict']

				for deleter in self.deleters[model]:
                                        try:
   					    deleter()(pk, model_dict)
                                        except:
                                            # something is silently eating these
                                            # exceptions...
                                            traceback.print_exc()
                                            raise

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

		try:
			clid = Config().feefie_client_id
		except:
			clid = get_random_client_id()
                        print "EventListener: no feefie_client_id configured. Using random id %s" % clid

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