#!/usr/bin/env python
import os, sys
from FSEvents import *
from pest import django_pest, nose_pest, runtests_pest, custom_pest

def find_tester(path, test_cmd):
    return os.path.exists(os.path.join(path, test_cmd))

def make_pest(path, test_cmd=None):
    pest = None
    
    if test_cmd is not None:
        pest = custom_pest.CustomPest(root=path)
        pest.set_command(test_cmd)
    elif find_tester(path, runtests_pest.CMD):
        pest = runtests_pest.RunTestsPest(root=path)
    elif find_tester(path, django_pest.CMD):
        pest = django_pest.DjangoPest(root=path)
    
    return pest
    
def analyze_changes(path, pest):
    if pest.has_changed():
        pest.run_tests()
           
def watch(stream):
    FSEventStreamScheduleWithRunLoop(stream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode)
    assert FSEventStreamStart(stream), "Failed to start stream"
    timer = CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + 1.0, 1.0, 0, 
                                 0, lambda timer, stream: FSEventStreamFlushAsync(stream), stream)
    CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, kCFRunLoopDefaultMode)
    try:
        CFRunLoopRun()
    finally:
        FSEventStreamStop(stream)
        FSEventStreamInvalidate(stream)
        FSEventStreamRelease(stream)
    
def pester(callback, path, pest):
    stream = FSEventStreamCreate(kCFAllocatorDefault,               # allocator 
                                  lambda *x: callback(path, pest),  # callback  
                                  path,                             # my path
                                  [path],                           # paths to watch
                                  kFSEventStreamEventIdSinceNow,    # since_when
                                  1.0,                              # latency   
                                  0)                                # flags     
    assert stream, "ERROR: FSEVentStreamCreate() => NULL"
    callback(path, pest)
    watch(stream)
    
def get_test_command(test_args):
    if len(test_args) > 0:
        return " ".join(test_args)
    return None
    
if __name__ == '__main__':
    path = os.path.abspath(os.curdir)
    pest = make_pest(path, get_test_command(sys.argv[1:]))
   
    if pest:
		pester(analyze_changes, path, pest)
    else:
		print "Could not find any tests to run, exiting."
