#!/usr/bin/env python
import os
import sys
import time

# This script can be used to check an incoming FTP directory for new files
# and perform one-time-only work on them.

mtime_trigger_in_sec = 15       # Time in seconds since the last modification in a file 
                                # after which it is considered 'ready' and acted upon
poll_interval_in_sec = 5        # Poll directory every poll_interval_in_sec seconds

class FileCandidate:
    '''
    Each new file appearing in the monitored folder will get an instance of this class
    '''
    def __init__(self, folder, filename, callback):
        '''
        Constructor: takes folder and filename as well as callback to call when triggered
        '''
        self._triggered = False
        self._folder = folder
        self._filename = filename
        self._callback = callback
    def Check(self):
        '''
        Checks the mtime against the current time and if at least mtime_trigger_in_sec
        seconds old, triggers the action (one-time-only)
        '''
        if self._triggered:
            return
        currentMTIME = os.stat(self._folder + os.sep + self._filename).st_mtime
        if time.time() > currentMTIME + mtime_trigger_in_sec:
            self._triggered = True
            self._callback(self._folder + os.sep + self._filename)

def MonitorDirectoryForEternity(folder, callback):
    '''
    This function works by checking modification times of files inside a folder
    and triggering on files whose modification time is at least mtime_trigger_in_sec 
    seconds old. It checks the files inside the directory every poll_interval_in_sec 
    seconds.'''
    knownFiles = {}
    while True:
        fileList = os.listdir(folder)
        # if the callback moves the files to another directory, make sure we don't 
        # fill all the memory with FileCandidates
        for keyFilename in knownFiles.keys():
            if keyFilename not in fileList:
                del knownFiles[keyFilename]
        # Check for new files
        for filename in fileList:
            if not knownFiles.has_key(filename):
                knownFiles[filename] = FileCandidate(folder, filename, callback)
            else:
                knownFiles[filename].Check()
        time.sleep(poll_interval_in_sec)

def Callback(completePathAndFilename):
    print "Roaming Component call for file '%s'" % completePathAndFilename

def main():
    if len(sys.argv) != 2:
        sys.stderr.write('Usage: %s <directory>\n' % sys.argv[0])
        sys.exit(1)
    monitoredDir = os.path.dirname(sys.argv[1])
    if not os.path.isdir(monitoredDir):
        sys.stderr.write("'%s' is not a directory!\n" % monitoredDir)
        sys.exit(1)
    MonitorDirectoryForEternity(monitoredDir, Callback)

if __name__ == "__main__":
    main()
