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 *

debug_mode = False

logger = Logger(logfile='observer.log', level=logging.INFO)

class StepNotReady(Exception):
    pass

def toposort(g, steps):
    reverse = {}

    for k,v in g.items():
        for rk in v:
            try:
                reverse[rk].append(k)
            except:
                reverse[rk]=k

    sources = []
    for k,v in g.items():
        if not reverse.has_key(k):
            sources.append(k)


    for k,v in reverse.iteritems():
        if (not v):
            sources.append(k)

    order = []
    marked = []

    while sources:
        n = sources.pop()
        try:
            for m in g[n]:
                if m not in marked:
                    sources.append(m)
                    marked.append(m)
        except KeyError:
            pass
        order.append(n)
    return order

class PlanetStackObserver:
    sync_steps = [SyncNetworks,SyncNetworkSlivers,SyncSites,SyncSitePrivileges,SyncSlices,SyncSliceMemberships,SyncSlivers,SyncSliverIps]

    def __init__(self):
        # The Condition object that gets signalled by Feefie events
        self.load_sync_steps()
        self.event_cond = threading.Condition()
        self.driver = OpenStackDriver()

    def wait_for_event(self, timeout):
        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_steps(self):
        dep_path = Config().observer_backend_dependency_graph
        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
            # This contains dependencies between backend records
            self.backend_dependency_graph = json.loads(open(backend_path).read())
        except Exception,e:
            # We can work without a backend graph
            self.backend_dependency_graph = {}

        provides_dict = {}
        for s in self.sync_steps:
            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:
                                    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, self.sync_steps)
        print "Order of steps=",self.ordered_steps
        self.load_run_times()
        

    def check_duration(self):
        try:
            if (duration > S.deadline):
                logger.info('Sync step %s missed deadline, took %.2f seconds'%(S.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[step.name]
        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):
        for failed_step in failed_steps:
            if (failed_step in self.dependency_graph[step.name]):
                raise StepNotReady

    def run(self):
        if not self.driver.enabled or not self.driver.has_openstack:
            return

        while True:
            try:
                logger.info('Waiting for event')
                tBeforeWait = time.time()
                self.wait_for_event(timeout=300)
                logger.info('Observer woke up')

                # Set of whole steps that failed
                failed_steps = []

                # Set of individual objects within steps that failed
                failed_step_objects = []

                for S in self.ordered_steps:
                    start_time=time.time()
                    
                    sync_step = S(driver=self.driver)
                    sync_step.dependencies = self.dependencies[sync_step.name]
                    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.add(sync_step)
                    except:
                        failed_steps.add(sync_step)

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

                            # ********* This is the actual sync step
                            failed_objects = sync_step(failed=failed_step_objects)


                            check_deadline(sync_step, duration)
                            failed_step_objects.extend(failed_objects)
                            self.update_run_time(sync_step)
                        except:
                            failed_steps.add(S)
                self.save_run_times()
            except:
                logger.log_exc("Exception in observer run loop")
                traceback.print_exc()
