import os
import imp
import inspect
import time
import traceback
import commands
import threading
import json

from datetime import datetime
from collections import defaultdict
from core.models import *
from django.db.models import F, Q
#from openstack.manager import OpenStackManager
from openstack.driver import OpenStackDriver
from util.logger import Logger, logging, logger
#from timeout import timeout
from planetstack.config import Config
from observer.steps import *
from syncstep import SyncStep
from toposort import toposort

debug_mode = False

logger = Logger(level=logging.INFO)

class StepNotReady(Exception):
    pass

class NoOpDriver:
    def __init__(self):
         self.enabled = True

class PlanetStackObserver:
    #sync_steps = [SyncNetworks,SyncNetworkSlivers,SyncSites,SyncSitePrivileges,SyncSlices,SyncSliceMemberships,SyncSlivers,SyncSliverIps,SyncExternalRoutes,SyncUsers,SyncRoles,SyncNodes,SyncImages,GarbageCollector]
    sync_steps = []

    def __init__(self):
        # The Condition object that gets signalled by Feefie events
        self.step_lookup = {}
        self.load_sync_step_modules()
        self.load_sync_steps()
        self.event_cond = threading.Condition()


        self.driver_kind = getattr(Config(), "observer_driver", "openstack")
        if self.driver_kind=="openstack":
            self.driver = OpenStackDriver()
        else:
            self.driver = NoOpDriver()

    def wait_for_event(self, timeout):
        logger.info('Waiting for event')
        self.event_cond.acquire()
        self.event_cond.wait(timeout)
        self.event_cond.release()

    def wake_up(self):
        logger.info('Wake up routine called. Event cond %r'%self.event_cond)
        self.event_cond.acquire()
        self.event_cond.notify()
        self.event_cond.release()

    def load_sync_step_modules(self, step_dir=None):
        if step_dir is None:
            if hasattr(Config(), "observer_steps_dir"):
                step_dir = Config().observer_steps_dir
            else:
                step_dir = "/opt/planetstack/observer/steps"

        for fn in os.listdir(step_dir):
            pathname = os.path.join(step_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 SyncStep 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, SyncStep) and hasattr(c,"provides") and (c not in self.sync_steps):
                        self.sync_steps.append(c)
        logger.info('loaded sync steps: %s' % ",".join([x.__name__ for x in self.sync_steps]))
        # print 'loaded sync steps: %s' % ",".join([x.__name__ for x in self.sync_steps])

    def load_sync_steps(self):
        dep_path = Config().observer_dependency_graph
        logger.info('Loading model dependency graph from %s' % dep_path)
        try:
            # This contains dependencies between records, not sync steps
            self.model_dependency_graph = json.loads(open(dep_path).read())
        except Exception,e:
            raise e

        try:
            backend_path = Config().observer_pl_dependency_graph
            logger.info('Loading backend dependency graph from %s' % backend_path)
            # This contains dependencies between backend records
            self.backend_dependency_graph = json.loads(open(backend_path).read())
        except Exception,e:
            logger.info('Backend dependency graph not loaded')
            # We can work without a backend graph
            self.backend_dependency_graph = {}

        provides_dict = {}
        for s in self.sync_steps:
            self.step_lookup[s.__name__] = s 
            for m in s.provides:
                try:
                    provides_dict[m.__name__].append(s.__name__)
                except KeyError:
                    provides_dict[m.__name__]=[s.__name__]

                
        step_graph = {}
        for k,v in self.model_dependency_graph.iteritems():
            try:
                for source in provides_dict[k]:
                    for m in v:
                        try:
                            for dest in provides_dict[m]:
                                # no deps, pass
                                try:
                                    if (dest not in step_graph[source]):
                                        step_graph[source].append(dest)
                                except:
                                    step_graph[source]=[dest]
                        except KeyError:
                            pass
                    
            except KeyError:
                pass
                # no dependencies, pass
        
        #import pdb
        #pdb.set_trace()
        if (self.backend_dependency_graph):
            backend_dict = {}
            for s in self.sync_steps:
                for m in s.serves:
                    backend_dict[m]=s.__name__
                    
            for k,v in backend_dependency_graph.iteritems():
                try:
                    source = backend_dict[k]
                    for m in v:
                        try:
                            dest = backend_dict[m]
                        except KeyError:
                            # no deps, pass
                            pass
                        step_graph[source]=dest
                        
                except KeyError:
                    pass
                    # no dependencies, pass

        dependency_graph = step_graph

        self.ordered_steps = toposort(dependency_graph, map(lambda s:s.__name__,self.sync_steps))
        print "Order of steps=",self.ordered_steps
        self.load_run_times()
        

    def check_duration(self, step, duration):
        try:
            if (duration > step.deadline):
                logger.info('Sync step %s missed deadline, took %.2f seconds'%(step.name,duration))
        except AttributeError:
            # S doesn't have a deadline
            pass

    def update_run_time(self, step):
        self.last_run_times[step.__name__]=time.time()

    def check_schedule(self, step):
        time_since_last_run = time.time() - self.last_run_times.get(step.__name__, 0)
        try:
            if (time_since_last_run < step.requested_interval):
                raise StepNotReady
        except AttributeError:
            logger.info('Step %s does not have requested_interval set'%step.__name__)
            raise StepNotReady
    
    def load_run_times(self):
        try:
            jrun_times = open('/tmp/observer_run_times').read()
            self.last_run_times = json.loads(jrun_times)
        except:
            self.last_run_times={}
            for e in self.ordered_steps:
                self.last_run_times[e]=0


    def save_run_times(self):
        run_times = json.dumps(self.last_run_times)
        open('/tmp/observer_run_times','w').write(run_times)

    def check_class_dependency(self, step, failed_steps):
        step.dependenices = []
        for obj in step.provides:
            step.dependenices.extend(self.model_dependency_graph.get(obj.__name__, []))
        for failed_step in failed_steps:
            if (failed_step in step.dependencies):
                raise StepNotReady


    def run_steps(self):
        try:
            logger.info('Observer run steps')

            # Set of whole steps that failed
            failed_steps = []

            # Set of individual objects within steps that failed
            failed_step_objects = set()

            for S in self.ordered_steps:
                step = self.step_lookup[S]
                start_time=time.time()
                
                sync_step = step(driver=self.driver)
                sync_step.__name__ = step.__name__
                sync_step.dependencies = []
                try:
                    mlist = sync_step.provides
                    
                    for m in mlist:
                        sync_step.dependencies.extend(self.model_dependency_graph[m.__name__])
                except KeyError:
                    pass
                sync_step.debug_mode = debug_mode

                should_run = False
                try:
                    # Various checks that decide whether
                    # this step runs or not
                    self.check_class_dependency(sync_step, failed_steps) # dont run Slices if Sites failed
                    self.check_schedule(sync_step) # dont run sync_network_routes if time since last run < 1 hour
                    should_run = True
                except StepNotReady:
                    logging.info('Step not ready: %s'%sync_step.__name__)
                    failed_steps.append(sync_step)
                except:
                    failed_steps.append(sync_step)

                if (should_run):
                    try:
                        duration=time.time() - start_time

                        logger.info('Executing step %s' % sync_step.__name__)

                        # ********* This is the actual sync step
                        #import pdb
                        #pdb.set_trace()
                        failed_objects = sync_step(failed=list(failed_step_objects))


                        self.check_duration(sync_step, duration)
                        if failed_objects:
                            failed_step_objects.update(failed_objects)
                        self.update_run_time(sync_step)
                    except:
                        failed_steps.append(S)
            self.save_run_times()
        except:
            logger.log_exc("Exception in observer run loop")
            traceback.print_exc()

    def run(self):
        try:
            logger.info('Observer start run loop')
            if not self.driver.enabled:
                return
            if (self.driver_kind=="openstack") and (not self.driver.has_openstack):
                return

            while True:
                try:  
                    self.wait_for_event(timeout=30)       
                except: 
                    logger.log_exc("Exception in observer wait for event") 
                    traceback.print_exc()

                try: 
                    self.run_steps()            
                except: 
                    logger.log_exc("Exception in observer run steps")
                    traceback.print_exc()
        except:
            logger.log_exc("Exception in observer run loop")
            traceback.print_exc()
