"""
This module contains a class that can keep a log of what files
below an arbitrary directory were processed in some way and
which were not.
"""

from sets import Set
from itertools import *
import os


class Error(Exception):
	pass


class FileSet(dict):
	def __init__(self, rootDir="", *args):
		dict.__init__(self, *args)
		self.rootDir = rootDir
		if not self.rootDir.endswith("/"):
			self.rootDir = self.rootDir+"/"

	def __sub__(self, other):
		return FileSet(izip(Set(self)-Set(other), repeat(None)))
	
	def setSetName(self, setName):
		for key in self:
			self[key] = setName
	
	def __str__(self):
		return "[%s]"%(', '.join([s for s in self]))

	def getFiles(self):
		return [os.path.join(self.rootDir, fName) 
			for fName in self]
	
	def getRootDir(self):
		return self.rootDir

	def relativize(self, fPath):
		if not fPath.startswith(self.rootDir):
			raise Error, "Illegal attempt to add %s under %s"%(fPath,
				self.rootDir)
		return fPath[len(self.rootDir):]
	
	def diffInPlace(self, other):
		for key in other:
			if self.has_key(key):
				del self[key]


class RelativeFileSet(FileSet):
	def __init__(self, rootDir, collectDir=None, setName="None"):
		FileSet.__init__(self, rootDir=rootDir)
		if collectDir is None:
			self.collectDir = rootDir
		else:
			self.collectDir = collectDir
		self.setName = setName
		self._collectNamesFromDir()

	def __repr__(self):
		return "FileSet('%s')"%self.rootDir

	def _collectNamesFromDir(self):
		for dirpath, dirnames, filenames in os.walk(self.collectDir):
			for fName in filenames:
				self[os.path.join(self.relativize(dirpath), fName)
					] = self.setName
	
	def getSetName(self):
		return self.setName


class DbFileSet(FileSet):
	def __init__(self, fdbName=None):
		"""fdbName contains lines of touchsetName relativePath pairs
		"""
		FileSet.__init__(self)
		if fdbName is not None:
			self._loadFdb(fdbName)
	
	def _loadFdb(self, fdbName):
		for line in open(fdbName):
			touchset, path = line.split(" ", 1)
			self[path.strip()] = touchset
	
	def save(self, fdbName):
		f = open(fdbName, "w")
		f.write("\n".join(["%s %s"%(touchset, path)
			for path, touchset in self.iteritems()]))
		f.write("\n")
		f.close()


def _test():
	dbSet = DbFileSet()
	before = RelativeFileSet("/home/msdemlei/projects/autoburner", 
		setName="init")
	dbSet.update(before)
	dbSet.save("whatever.procd")
	raw_input("Create a file and press enter")
	after = RelativeFileSet("/home/msdemlei/projects/autoburner", 
		setName="after")
	print after-before
	dbSet = DbFileSet("whatever.procd")
	change = after-dbSet
	print change
	change.setSetName("after")
	dbSet.update(change)
	dbSet.save("whatever.procd")


if __name__=="__main__":
	_test()

