import platform
from MetadataService.Component import Component
import os
from platform import is_or_is_below

def is_valid_filename_encoding(filename):
	# Check whether the filename is valid-encoded
	import locale
	from MetadataService.common import transcode
	enc = locale.getpreferredencoding()
	try: transcode(filename,enc,enc,forced=True)
	except: return False
	return True


class _VolumeExpert(Component):

	user_stoplist = None

	def __init__(self,stoplist):
		assert type(stoplist) is list
		Component.__init__(self,public_interface=None)
		self.set_component_name("VolumeExpert")
		self.user_stoplist = stoplist
		self.rebuild_caches()
		
		
# 	def get_mounted_mountpoints(self):
		""" Returns a list of mountpoints for each mounted volume."""
# 		return get_mounted_mountpoints()
	
	def is_appropriate(self,filename):
		""" Returns True if a filename should be indexed.  Use this in the crawlers and wherever you need to confirm whether to pass a file to the FilesystemCrawler queues or not. """
		
		# files/dirs/volume mountpoints in stoplist or database path not appropriate
		for path in self.cache_stoplist:
			if is_or_is_below(filename,path): return False
		# backup files and directories not appropriate
		if filename.endswith('~') or '~/' in filename: return False
		# hidden directories not appropriate
		if '/.' in filename: return False
		# symlinks not appropriate
		if os.path.islink(filename): return False
		# invalid encoding is not appropriate as well
		if not is_valid_filename_encoding(filename):
			self.log.warning("%s has an invalid encoding", filename)
			return False
		
		if os.path.isfile(filename) or os.path.isdir(filename): return True # this should exclude all sockets, fifos and device nodes
		return False
		
# 	def get_appropriate_mountpoints(self):
# 		return [ l for l in self.get_mounted_mountpoints() if self.is_appropriate(l) ]

	cache_guid_to_mountpoint = {}
	cache_currently_known_volumes = {}
	cache_stoplist = []
	
	def rebuild_caches(self):
		builtin_stoplist = ["/tmp","/var/tmp","/usr/tmp","/dev"]
 		self.cache_stoplist = builtin_stoplist + self.user_stoplist
		self.cache_currently_known_volumes = platform.get_currently_known_volumes()
		self.cache_guid_to_mountpoint = {}
		mtab = platform.get_mtab()
		for guid,vr in self.cache_currently_known_volumes.iteritems():
			for record in mtab.records:
				if record.device_file == vr.current_device_file:
					self.cache_guid_to_mountpoint[guid] = record.mountpoint

	def get_mountpoint(self,guid):
		assert type(guid) is str and len(guid) > 0
		### return the mountpoint for a volume GUID
		try: return self.cache_guid_to_mountpoint[guid]
		except KeyError: return None
		
	def get_guid_for_mountpoint(self,mountpoint):
		assert type(mountpoint) is str and len(mountpoint) > 0
		### return the mountpoint for a volume GUID
		for guid,mp in self.cache_guid_to_mountpoint.iteritems():
			if mp == mountpoint: return guid
		return None
		
	def get_currently_known_volumes(self):
		return self.cache_currently_known_volumes
		
		
def VolumeExpert(stoplist):
	if not VolumeExpert.__dict__.has_key("instance"):
		VolumeExpert.instance = _VolumeExpert(stoplist)
	return VolumeExpert.instance
