# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
# 
#   http://www.apache.org/licenses/LICENSE-2.0
# 
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.    

#XXXstroucki: for compatibility with python 2.5
from __future__ import with_statement

import ConfigParser
#import cPickle
import os
#import select
import signal
#import struct
import sys
#import threading
import time
import traceback
import types
import functools

from tashi.rpycservices import rpycservices
from tashi.rpycservices.rpyctypes import TashiException, Errors, InstanceState, HostState
from tashi.utils.timeout import *

def broken(oldFunc):
	"""Decorator that is used to mark a function as temporarily broken"""
	def newFunc(*args, **kw):
		raise RuntimeError("%s is broken!" % (oldFunc.__name__))
	if (oldFunc.__doc__ is None):
		newFunc.__doc__ = "[Broken]"
	else:
		newFunc.__doc__ = "[Broken] " + oldFunc.__doc__
	newFunc.__name__ = oldFunc.__name__
	newFunc.__module__ = oldFunc.__module__
	return newFunc

def deprecated(oldFunc):
	"""Decorator that is used to deprecate functions"""
	def newFunc(*args, **kw):
		raise RuntimeError("%s has been deprecated!" % (oldFunc.__name__))
	newFunc.__doc__ = "[Deprecated] " + str(oldFunc.__doc__)
	newFunc.__name__ = oldFunc.__name__
	newFunc.__module__ = oldFunc.__module__
	return newFunc

def logged(oldFunc):
	"""Decorator that is used to log a function's calls -- currently uses sys.stderr"""
	def newFunc(*args, **kw):
		logMsg = "%s(%s, %s) -> " % (oldFunc.__name__, str(args).strip("[]"), str(kw).strip("{}").replace(": ", "="))
		sys.stderr.write(logMsg)
		sys.stderr.flush()
		try:
			res = oldFunc(*args, **kw)
		except Exception, e:
			logMsg = "%s\n" % (str(e))
			sys.stderr.write(logMsg)
			sys.stderr.flush()
			raise
		logMsg = "%s\n" % (str(res))
		sys.stderr.write(logMsg)
		sys.stderr.flush()
	newFunc.__doc__ = oldFunc.__doc__
	newFunc.__name__ = oldFunc.__name__
	newFunc.__module__ = oldFunc.__module__
	return newFunc

def timed(oldFunc):
	"""Decorator that is used to time a function's execution"""
	def newFunc(*args, **kw):
		start = time.time()
		try:
			res = oldFunc(*args, **kw)
		finally:
			finish = time.time()
			print "%s: %f" % (oldFunc.__name__, finish-start)
		return res
	return newFunc

def editAndContinue(filespec, mod, name):
	def wrapper(oldFunc):
		persist = {}
		persist['lastMod'] = time.time()
		persist['oldFunc'] = oldFunc
		persist['func'] = oldFunc
		def newFunc(*args, **kw):
			modTime = os.stat(filespec)[8]
			if (modTime > persist['lastMod']):
				persist['lastMod'] = modTime
				space = {}
				exec ("import %s\nreload ( %s )" % (mod, mod)) in space
				persist['func'] = eval(mod + "." + name, space)
			return persist['func'](*args, **kw)
		return newFunc
	return wrapper

class failsafe(object):
	"""Class that attempts to make RPCs, but will fall back to a local object that implements the same methods"""
	def __attempt__(self, cur, fail):
		def newFunc(*args, **kw):
			try:
				return cur(*args, **kw)
			except:
				self.__dict__['__current_obj__'] = self.__dict__['__failsafe_obj__']
				return fail(*args, **kw)
		return newFunc
	
	@deprecated
	def __init__(self, obj):
		self.__dict__['__failsafe_obj__'] = obj
		self.__dict__['__current_obj__'] = obj
	
	def __update_current__(self, obj):
		self.__dict__['__current_obj__'] = obj
	
	def __getattr__(self, name):
		return self.__attempt__(getattr(self.__dict__['__current_obj__'], name), getattr(self.__dict__['__failsafe_obj__'], name))
	
	def __setattr__(self, name, value):
		return setattr(self.__dict__['__current_obj__'], name, value)
	
	def __delattr__(self, name):
		return delattr(self.__dict__['__current_obj__'], name)

class reference(object):
	"""Class used to create a replacable reference to an object"""
	@deprecated
	def __init__(self, obj):
		self.__dict__['__real_obj__'] = obj
	
	def __update__(self, obj):
		self.__dict__['__real_obj__'] = obj
	
	def __getattr__(self, name):
		return getattr(self.__dict__['__real_obj__'], name)
	
	def __setattr__(self, name, value):
		return setattr(self.__dict__['__real_obj__'], name, value)
	
	def __delattr__(self, name):
		return delattr(self.__dict__['__real_obj__'], name)

def signalHandler(signalNumber):
	"""Used to denote a particular function as the signal handler for a 
	   specific signal"""
	def __decorator(function):
		signal.signal(signalNumber, function)
		return function
	return __decorator

def boolean(value):
	"""Convert a variable to a boolean"""
	if (type(value) == types.BooleanType):
		return value
	if (type(value) == types.IntType):
		return (value != 0)

	# See if it can be expressed as a string
	try:
		value = str(value)
	except:
		raise ValueError

	lowercaseValue = value.lower()
	if lowercaseValue in ['yes', 'true', '1']:
		return True
	elif lowercaseValue in ['no', 'false', '0']:
		return False
	else:
		raise ValueError

def instantiateImplementation(className, *args):
	"""Create an instance of an object with the given class name and list 
	   of args to __init__"""
	if (className.rfind(".") != -1):
		package = className[:className.rfind(".")]
		cmd = "import %s\n" % (package)
	else:
		cmd = ""
	cmd += "_obj = %s(*args)\n" % (className)
	exec cmd in locals()
	# XXXstroucki: this is correct, even though pydev complains
	return _obj

def convertExceptions(oldFunc):
	"""This converts any exception type into a TashiException so that 
	   it can be passed over an RPC"""
	def newFunc(*args, **kw):
		try:
			return oldFunc(*args, **kw)
		except TashiException:
			raise
		except:
			self = args[0]
			if (self.convertExceptions):
				raise TashiException(d={'errno':Errors.ConvertedException, 'msg': traceback.format_exc(10)})
			raise
	return newFunc

def getConfig(additionalNames=[], additionalFiles=[]):
	"""Creates many permutations of a list of locations to look for config 
	   files and then loads them"""
	config = ConfigParser.ConfigParser()
	baseLocations = ['/usr/local/tashi/etc/', '/usr/share/tashi/', '/etc/tashi/', os.path.expanduser('~/.tashi/')]
	names = ['Tashi'] + additionalNames
	names = reduce(lambda x, y: x + [y+"Defaults", y], names, [])
	allLocations = reduce(lambda x, y: x + reduce(lambda z, a: z + [y + a + ".cfg"], names, []), baseLocations, []) + additionalFiles
	configFiles = config.read(allLocations)
	if (len(configFiles) == 0):
		raise Exception("No config file could be found: %s" % (str(allLocations)))
	return (config, configFiles)

def __getShellFn():
	try:
		from IPython.Shell import IPShellEmbed
		return (1, IPShellEmbed)
	except ImportError:
		import IPython
		return (2, IPython.embed)

def debugConsole(globalDict):
	"""A debugging console that optionally uses pysh"""
	def realDebugConsole(globalDict):
		try :
			import atexit
			(calltype, shellfn) = __getShellFn()
			def resetConsole():
# XXXpipe: make input window sane
				(__stdin, stdout) = os.popen2("reset")
				stdout.read()
			atexit.register(resetConsole)
			if calltype == 1:
				dbgshell=shellfn(user_ns=globalDict)
				dbgshell()
			elif calltype == 2:
				dbgshell=shellfn
				dbgshell(user_ns=globalDict)
		except Exception, e:
			CONSOLE_TEXT=">>> "
			inputline = " " 
			while (inputline != ""):
				sys.stdout.write(CONSOLE_TEXT)
				inputline = sys.stdin.readline()
				try:
					exec(inputline) in globalDict
				except Exception, e:
					sys.stdout.write(str(e) + "\n")

		os._exit(0)

	if (os.getenv("DEBUG", "0") == "1"):
		threading.Thread(name="debugConsole", target=lambda: realDebugConsole(globalDict)).start()

def stringPartition(s, field):
	index = s.find(field)
	if (index == -1):
		return (s, "", "")
	l = s[:index]
	sep = s[index:index+len(field)]
	r = s[index+len(field):]
	return (l, sep, r)

def scrubString(s, allowed="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_."):
	ns = ""
	for c in s:
		if (c in allowed):
			ns = ns + c
	return ns

class Connection:

	def __init__(self, host, port, authAndEncrypt=False, credentials=None):
		self.host = host
		self.port = port
		self.credentials = credentials
		self.authAndEncrypt = authAndEncrypt
		self.connection = None
		# XXXstroucki some thing may still depend on this (client)
		self.username = None
		if credentials is not None:
			self.username = credentials[0]

	def __connect(self):
		# create new connection

		username = None
		password = None

		if self.credentials is not None:
			username = self.credentials[0]
			password = self.credentials[1]

		if self.authAndEncrypt:
			if username is None:
				username = raw_input("Enter Username:")

			if password is None:
				password = raw_input("Enter Password:")

			if self.credentials != (username, password):
				self.credentials = (username, password)

			client = rpycservices.client(self.host, self.port, username=username, password=password)
		else:
			client = rpycservices.client(self.host, self.port)

		self.connection = client


	def __do(self, name, *args, **kwargs):
		if self.connection is None:
			self.__connect()

		threadname = "%s:%s" % (self.host, self.port)
		# XXXstroucki: Use 10 second timeout, ok?
		# XXXstroucki: does this fn touch the network?
		t = TimeoutThread(getattr, (self.connection, name, None))
		threading.Thread(name=threadname, target=t.run).start()

		try:
			remotefn = t.wait(timeout=10)
		except TimeoutException:
			self.connection = None
			raise

		try:
			if callable(remotefn):
				# XXXstroucki: Use 10 second timeout, ok?
				t = TimeoutThread(remotefn, args, kwargs)
				threading.Thread(name=threadname, target=t.run).start()
				returns = t.wait(timeout=10.0)

			else:
				raise TashiException({'msg':'%s not callable' % name})

		except:
			self.connection = None
			raise

		# if we get a remote exception, raise it locally
		if (type(returns) is Exception) or \
		  (type(returns) is TashiException):
			raise returns

		return returns

	def __getattr__(self, name):
		return functools.partial(self.__do, name)


def createClient(config):
	cfgHost = config.get('Client', 'clusterManagerHost')
	cfgPort = config.get('Client', 'clusterManagerPort')
	#XXXstroucki nothing uses timeout right now
	#cfgTimeout = config.get('Client', 'clusterManagerTimeout')
	host = os.getenv('TASHI_CM_HOST', cfgHost)
	port = os.getenv('TASHI_CM_PORT', cfgPort)
	#XXXstroucki nothing uses timeout right now
	#timeout = float(os.getenv('TASHI_CM_TIMEOUT', cfgTimeout)) * 1000.0

	authAndEncrypt = boolean(config.get('Security', 'authAndEncrypt'))
	if authAndEncrypt:
		username = config.get('AccessClusterManager', 'username')
		password = config.get('AccessClusterManager', 'password')
		client = Connection(host, port, authAndEncrypt, (username, password))

	else:
		client = Connection(host, port)

	return client

def enumToStringDict(cls):
	d = {}
	for i in cls.__dict__:
		if (type(cls.__dict__[i]) is int):
			d[cls.__dict__[i]] = i
	return d

def humanReadable(size):
	suffixes = [("B",2**10), ("K",2**20), ("M",2**30), ("G",2**40), ("T",2**50)]
	for suf, lim in suffixes:
		if size > lim:
			continue
		else:
			return round(size/float(lim/2**10),2).__str__()+suf


vmStates = enumToStringDict(InstanceState)
hostStates = enumToStringDict(HostState)
