from datetime	import datetime
import sys
import os

IS_INITIALIZED = False

class say:

	def __init__ (self,
		label	= ''		,
		verbose	= 0			,
		dryrun	= False		,
		timetag	= ''		,
		prefix	= '    '	,
	):

		global LABEL
		global VERBOSE
		global DRYRUN
		global TIMETAG
		global PREFIX
		global IS_INITIALIZED

		if IS_INITIALIZED:

			self.set_label	(LABEL   if label   == '    '	else label	)
			self.set_verbose(VERBOSE if verbose ==      0	else verbose)
			self.set_dryrun	(DRYRUN  if not dryrun			else dryrun	)
			self.set_timetag(TIMETAG if timetag ==     ''	else timetag)
			self.set_prefix	(PREFIX  if prefix  == '    '	else prefix )

		else:

			self.set_label	(label  )
			self.set_verbose(verbose)
			self.set_dryrun	(dryrun )
			self.set_timetag(timetag)
			self.set_prefix	(prefix )

			LABEL	= self.LABEL
			VERBOSE	= self.VERBOSE
			DRYRUN	= self.DRYRUN
			TIMETAG	= self.TIMETAG
			PREFIX	= self.PREFIX

			IS_INITIALIZED = True

	def set_label  (self,label  =''		): self.LABEL	= label
	def set_verbose(self,verbose=1		): self.VERBOSE = verbose
	def set_debug  (self,verbose=2		): self.VERBOSE	= verbose
	def set_dryrun (self,dryrun = True	): self.DRYRUN	= dryrun
	def set_timetag(self,timetag= ''  	): self.TIMETAG	= timetag
	def set_prefix (self,prefix	= ''  	): self.PREFIX	= prefix

	def message(self, message='', threshold=0, seiw=''):

		# Only if the VERBOSE level is higher than the
		# threshold, something is actually printed

		if self.VERBOSE >= threshold:
			if self.LABEL:
				if seiw != '':
					seiw = '-'+seiw
				date = ''
				if self.TIMETAG != '':
					date = datetime.now().strftime(self.TIMETAG)
				message_prefix = ['','DRYRUN '][self.DRYRUN]+date+'%'+self.LABEL+seiw+'- '
			else:		# If label is not defined, then just echo
				message_prefix = self.PREFIX

			sys.stderr.write(message_prefix+message+'\n')

	def message_bare(self,message,threshold):
		save = self.LABEL
		self.label = ''
		self.message(message,threshold)
		self.LABEL = save

	def warn(self,message,seiw='W'):			# Always echo to stderr
		self.message(message, self.VERBOSE, seiw)

	def warn_bare(self,message):				# Always echo to stderr
		self.message_bare(message, self.VERBOSE)

	def die(self,message='die',seiw='E',code=1):# Always echo to stderr; then quit with error code 1
		self.message(message, self.VERBOSE, seiw)
		sys.exit(code)

	def done(self,message='done',seiw='S'):		# Always echo to STDERR; then quit with error code 0
		self.message(message, self.VERBOSE, seiw)
		sys.exit(0)

	def yell(self,message,seiw='I'):			# Always echo to stderr
		self.message(message, self.VERBOSE, seiw)

	def yell_bare(self,message):				# Always echo to stderr
		self.message_bare(message, self.VERBOSE)

	def say(self,message,seiw='I'):				# Echo for every non-zero VERBOSE to stderr
		self.message(message, 1, seiw)

	def say_bare(self,message):					# Echo for every non-zero VERBOSE to stderr
		self.message_bare(message, 1)

	def debug(self,message,seiw='I'):			# Echo for every non-zero VERBOSE to stderr
		self.message(message, 2, seiw)

	def debug_bare(self,message):				# Echo for every non-zero VERBOSE to stderr
		self.message_bare(message, 2)


	def __repr__(self):
		return "say = isay(label='%s',verbose=%s,dryrun=%s,prefix='%s',timetag='%s')"%(self.LABEL,self.VERBOSE,self.DRYRUN,self.PREFIX,self.TIMETAG)

	def __str__(self):
		return "    label   : '%s'\n    verbose : %s\n    dry run : %s\n    time tag: '%s'\n    prefix  : '%s'"%	\
			(self.LABEL  if self.LABEL  else '(none)',
			 self.VERBOSE,
			 self.DRYRUN,
			 self.TIMETAG if self.TIMETAG else '(none)',
			 self.PREFIX)

def nice_size( size, digits=1, base=2, space='', in_bytes=False, fraction=1 ):

	format = '%%.%df%s%%s'%(digits,space)

	if in_bytes:
		size = '%s'%size

	elif base == 10:
		if size >= fraction*10**12:
			size = format%(float(size)/10*12,'TB')
		elif size >= fraction*10**9:
			size = format%(float(size)/10**9,'GB')
		elif size >= fraction*10**6:
			size = format%(float(size)/10**6,'MB')
		elif size >= fraction*10**3:
			size = format%(float(size)/10**3,'kB')
		else:
			size = format%(size,'B')

	else:	# base 2
		if size >= fraction*2**40:
			size = format%(float(size)/2**40,'TiB')
		elif size >= fraction*2**30:
			size = format%(float(size)/2**30,'GiB')
		elif size >= fraction*2**20:
			size = format%(float(size)/2**20,'MiB')
		elif size >= fraction*2**10:
			size = format%(float(size)/2**10,'kiB')
		else:
			size = format%(size,'B')

	# ternary statement not supported prior to v3.5
	#size =  '%s'%size		   if not human_form	else	\
	#	'%.2f TiB'%(float(size)/TB) if size > TB	else	\
	#	'%.2f GiB'%(float(size)/GB) if size > GB	else	\
	#	'%.2f MiB'%(float(size)/MB) if size > MB	else	\
	#	'%.2f kiB'%(float(size)/kB) if size > kB	else	\
	#	'%s'%size

	return size.strip()

def nice_wsize( size, digits=1, base=2, in_bytes=False, fraction=1 ):
	return nice_size( size, digits, base, ' ', in_bytes, fraction )

def hide_env( spec ):

	import os

	match_name  = ''
	match_value = ''

	for name, value in os.environ.iteritems():
		n = len(value)
		if n != 0:

			# KLUDGE:
			# Checking for the existence of NFS mounts that are not on line,
			# will cause os.path.isdir to freeze the process until there is a
			# timeout. So we don't check for those.

			exists = value.find('/smeidb') == 0 or value.find('/smeidc/') == 0
			if not exists:
				exists = os.path.isdir(value)

			if exists:
				if spec.find(value) == 0:
					if n > len(match_value):
						match_name  = name
						match_value = value

	if match_name == '':
		rtn = spec
	else:
		rtn = '$'+match_name+spec[len(match_value):]

	return rtn

def which( program ):

	return (os.popen('which '+program+' 2> /dev/null').read().split('\n'))[0]

def run_cmd( cmd ):

	say_inst = say( '%s.%s'%('run_cmd',whoami()))
	say( cmd )
	log = (os.popen(cmd)).read()
	say( log )

	return log

def whoami():
	return sys._getframe(1).f_code.co_name

def count_instances( name, verbose ):

	say_inst = say( '%s.%s'%('count_instances',whoami()))

	#name = (os.path.split(argv[0]))[1]+' '+argv[1]
	say( 'checking process: %s'%name )

	proc = run_cmd( 'ps -efw | grep "'+name+'"', 0 )
	proc = proc.split('\n')

	cnt = 0
	for p in proc:
		#if p.find('python') != -1 and p.find(name) != -1:
		#if p.find(name) != -1:
		#if p.find(name) != -1 and p.find('grep') == -1:
		if name in p and not 'grep' in p:
			cnt += 1
			if verbose:
				sys.stderr.write( p+'\n' )

	debug( '%d'%cnt,'instance(s) running: %s'%name )

	return cnt

