#!/usr/bin/env python

# shoot me... pre f10 systems get pyinotify 0.7, f10 gets 0.8, much of 0.7 is depricated.
import sys, time, os
import pyinotify
from subprocess import call
from daemon import Daemon
from hashlib import sha256
from burncheck import addkey, readkey, checkallkeys

if 'L1A_DVD' in os.environ.keys():
	l1advd_dir = os.environ['L1A_DVD']
elif os.path.exists('/hafb/l1a/2_dvd'):
	l1advd_dir = '/hafb/l1a/2_dvd'
else:
	print 'L1A_DVD environment variable not set and /hafb/l1a/2_dvd not found.'
	sys.exit(1)

if 'L1A_DVDGZ' in os.environ.keys():
	l1advdgz_dir = os.environ['L1A_DVDGZ']
elif os.path.exists('/hafb/l1a/4_dvdgz'):
	l1advdgz_dir = '/hafb/l1a/4_dvdgz'
else:
	print 'L1A_DVDGZ environment variable not set and /hafb/l1a/4_dvdgz not found.'
	sys.exit(1)

directories = [l1advd_dir, l1advdgz_dir]
recursive = False 

class ProcessFiles(pyinotify.ProcessEvent):
	def process_IN_CLOSE_WRITE(self, event):
		if event.path == directories[0]:
			if event.name.split('.').pop() == 'buf':
				# this needs to consider that files may be moved back from 3_hold, rather than watching hold and
				# checking move events to and from, just assume that if it is in SHA256SUM that it came from 3_hold

				# also need to consider that tmpBurn files are moved in and out of this directory, if you ctrl-c
				# a l1a_dvd then restart it quickly, the inotify queue will still be working to read keys and 
				# addkey/readkey do not appear to be sane regarding exceptions, so i'll have to fix that there
				# this is a temporary fix
				try:
					findchecksum = readkey(event.name, os.path.join(event.path,'SHA256SUM'))
				except IOError:
					findchecksum = 1

				if findchecksum == 0 and os.path.exists(os.path.join(event.path,event.name)):
					checksum = sha256(open(os.path.join(event.path,event.name)).read()).hexdigest()
					addkey(os.path.join(event.path, 'SHA256SUM'), checksum, event.name)
				else:
					if findchecksum == 1:
						print "IOError reading key for file %s" % event.name
					elif findchecksum == 0:
						print "File not found: %s" % event.name
					else:
						print "File present, no IO Error, yet something went wrong..."
				
		if event.path == directories[1]:
			# also need to consider gzipped files being moved in from 5_attic, look for checksum.

			# check for buffer file, or l1a_dvd.txt and compress them
			if event.name.split('.').pop() == 'buf' or event.name == 'l1a_dvd.txt':
				status = call(['gzip', '-f',os.path.join(event.path,event.name)])

			# ignore l1a_dvd.txt.gz
			if event.name.split('.').pop() == 'gz' and not 'txt' in event.name.split('.'):
				findchecksum = readkey(event.name, os.path.join(event.path, 'SHA256SUM-compressed'))
				if findchecksum != 0:
					print 'WARNING: checksum already exists for', event.name
					print '         appending anyways'

				checksum = sha256(open(os.path.join(event.path,event.name)).read()).hexdigest()
				addkey(os.path.join(event.path, 'SHA256SUM-compressed'), checksum, event.name)

	def process_IN_MOVED_TO(self,event):
		self.process_IN_CLOSE_WRITE(event)




class LOneADaemon(Daemon):
	wm = pyinotify.WatchManager()
	# * other event codes can be added to the mask with | operator
	# * man inotify for a list of masks
	# * make sure to override the processevent definition in the class ProcessFiles for new masks
	try:
		mask = pyinotify.EventsCodes.IN_CLOSE_WRITE | pyinotify.EventsCodes.IN_MOVED_TO | pyinotify.EventsCodes.IN_MOVED_FROM
	except AttributeError:
		# 0.8 bootstrap
		mask = pyinotify.IN_CLOSE_WRITE | pyinotify.IN_MOVED_TO | pyinotify.IN_MOVED_FROM

	notifier = pyinotify.Notifier(wm, ProcessFiles())
	# add watch directories
	# add_watch takes a string or list of strings
	wdd = wm.add_watch(directories, mask, rec=recursive)

	def run(self):

		while True:
			self.notifier.process_events()
			if self.notifier.check_events():
				self.notifier.read_events()

if __name__ == "__main__":

	if os.path.exists('/tmp/l1a-daemon.pid'):
		# pid is there, see if it is running, if so, bail, if not, clean up
		pidfile = open('/tmp/l1a-daemon.pid','r')
		# get rid of the pesky newline
		pidnum = int(pidfile.read())
		# won't work if there is no procfs, but hey, this is Linux, right?
		if os.path.exists('/proc/'+str(pidnum)):
			# make sure that it is actually l1adaemon.py running.
			# it could have died and a new process is in its place
			procpid = open('/proc/'+str(pidnum)+'/cmdline','r')
			cmdline = procpid.read()
			if cmdline.find('l1adaemon') != -1:
				print "WARNING: l1adaemon.py is already running, bailing"
				sys.exit(2)
			# pidfile exists, but there was a mysterious death, moving along

		# cleaning up then
		os.remove('/tmp/l1a-daemon.pid')
		
	if os.path.exists('/home/soft/l1adaemon.txt'):
		os.remove('/home/soft/l1adaemon.txt')

		
	daemon = LOneADaemon('/tmp/l1a-daemon.pid',stdout='/home/soft/l1adaemon.txt',stderr='/home/soft/l1adaemon.txt')
	if len(sys.argv) == 2:
		if 'start' == sys.argv[1]:
			print 'Checking SHA256SUM'
			checkallkeys(os.path.join(directories[0],'SHA256SUM'))
			print 'Checking SHA256SUM-compressed'
			checkallkeys(os.path.join(directories[1],'SHA256SUM-compressed'))
			daemon.start()
		elif 'stop' == sys.argv[1]:
			daemon.notifier.stop()
			daemon.stop()
		elif 'restart' == sys.argv[1]:
			daemon.restart()
		else:
			print "Unknown command"
			sys.exit(2)
		sys.exit(0)
	else:
		print "usage: %s start|stop|restart" % sys.argv[0]
		sys.exit(2)
