import os, sys
import threading, Queue
import pyinotify

from bazjunk.path import makedirs
from bazbase import db, conversion, cache, structure

MAX_THREADS = 5

queue = Queue.PriorityQueue()
started = False

def error_path(ename, pn, format, rev):
    return os.path.join(cache.cache_dir(), ename,
                        '__%s.%s.%s.error' % (pn, format, rev))

def render_from_queue():
    while True:
        neg_priority, ename, propname, format = queue.get()
        with db.begin_transaction():
            e = structure.get_element(ename)
            try:
                rendering = conversion.render(e, propname, format)
            except Exception, e:
                # !!!! This is the wrong place to do this?
                rev = db.get_revision()
                # This stuff is bazki-specific and should be there.
                if format.startswith('.'):
                    propfmt = propname + format
                else:
                    propfmt = "%s>%s" % (propname, format)
                with open(error_path(ename, propname, format, rev),
                          'w') as fil:
                    fil.write('<a href="../_/%s/%s" class="error">%s</a>'
                              % (ename, propfmt, type(e).__name__))

def start_render(ename, propnames, format, priority=0):
    global started
    if not started:
        # TODO(xavid): race
        started = True
        for x in xrange(MAX_THREADS):
            t = threading.Thread(target=render_from_queue)
            t.daemon = True
            t.start()

    for pn in propnames:
        currpn = pn
        currformat = format
        if '>' in pn:
            currpn, currformat = pn.split('>', 1)
        queue.put((-priority, ename, currpn, currformat))

def wait_for_render(ename, propnames, format):
    result_map = {}
    wm = pyinotify.WatchManager()
    dir = os.path.join(cache.cache_dir(), ename)
    makedirs(dir)
    wdd = wm.add_watch(dir, pyinotify.IN_CLOSE_WRITE | pyinotify.IN_MOVED_TO)
    notifier = pyinotify.Notifier(wm)
    # Is this the right place to get this???
    rev = db.get_revision()
    try:
        while True:
            for pn in propnames:
                currpn = pn
                currformat = format
                if '>' in pn:
                    currpn, currformat = pn.split('>', 1)
                rendering = conversion.cached(ename, currpn, currformat)
                if rendering is not None:
                    result_map[pn] = rendering
                else:
                    epath = error_path(ename, currpn, currformat, rev)
                    try:
                        with open(epath) as fil:
                            result_map[pn] = fil.read()
                    except IOError:
                        pass
            if result_map:
                return result_map
            # If nothing, wait for an event.
            notifier.check_events()
    finally:
        notifier.stop()
