import sys
import os
import win32con
#import win32api

#////////////////////////////////////////////////////////////////////////////////////////////////////

def PSSE_Version_List():
	versions = dict()
	try:
		r = psspy.psseversion()
		active_majorVersion = r[1]
		assert(type(active_majorVersion) == int)
		versions[active_majorVersion] = None
	except:
		pass
	versionRange = range(29, 33+1)
	for k in versionRange:
		try:
			s = Get_PSSE_Path(k)
			versions[k] = None
		except:
			pass
	try:
		r = sorted(versions.keys())
		assert(len(r) > 0)
		r.reverse()
		return r
	except:
		raise Exception('Could not find a PSS/E version')

#////////////////////////////////////////////////////////////////////////////////////////////////////

def Get_PSSE_Path(version=None):
	
	if (version is None):
		availableVersions = PSSE_Version_List()
		version = max(availableVersions)
	
	programFilePaths = list()
	for s in ["PROGRAMFILES", "PROGRAMFILES(X86)"]:
		try: programFilePaths.append(os.environ[s])
		except: pass
	programFilePaths.append("C:\\Program Files")
	
	for s in programFilePaths:
		testPath = os.path.abspath(os.path.join(s, "PTI\\PSSE%i" % version))
		if (os.path.isdir(testPath)): return testPath.lower()
	
	raise Exception('Could not find PSS/E')

#////////////////////////////////////////////////////////////////////////////////////////////////////

def activate_license(fileName):
	try:
		err = psspy.activate_license(fileName)
		assert(err == 0)
	except:
		try:
			fileName = os.path.split(fileName)[-1]
			fileName = os.path.splitext(fileName)[0].upper()
			ver = psspy.psseversion()[1]
			keyPath = ('SOFTWARE', 'PTI', 'License')
			kh = win32con.HKEY_LOCAL_MACHINE
			rkFlags = win32con.KEY_ENUMERATE_SUB_KEYS | win32con.KEY_QUERY_VALUE | win32con.KEY_SET_VALUE
			for subKey in keyPath:
				kh = win32api.RegOpenKeyEx(kh, subKey, 0, rkFlags)
			b, a = win32api.RegQueryValueEx(kh, 'PSSE%i' % ver)
			win32api.RegSetValueEx(kh, fileName, 0, a, b)
		except:
			pass

#////////////////////////////////////////////////////////////////////////////////////////////////////

def AddImportPath(pathToAdd):
	s = os.path.abspath(pathToAdd).upper()
	
	if not os.path.isdir(s):
		return False
	
	assert(os.path.exists(s))
	
	if (s not in [os.path.abspath(y).upper() for y in sys.path]):
		sys.path.append(s)
	
	if (s not in [os.path.abspath(y).upper() for y in (os.environ['PATH'].split(';'))]):
		if (os.environ['PATH'] == ''):
			os.environ['PATH'] = s
		else:
			os.environ['PATH'] = ';'.join([os.environ['PATH'], s])
	
	return True

#////////////////////////////////////////////////////////////////////////////////////////////////////

def Import_PSSE():
	availableVersions = PSSE_Version_List()
	for version in availableVersions:
		try:
			PSSE_path = Get_PSSE_Path(version)
			backup1 = os.environ["PATH"]
			backup2 = sys.path[:]
			try:
				assert(AddImportPath(os.path.join(PSSE_path, 'PSSBIN')))
				assert(AddImportPath(os.path.join(PSSE_path, 'PSSLIB')))
				return __import__('psspy')
			except:
				os.environ['PATH'] = backup1
				sys.path = backup2
		except:
			pass
	raise Exception('Could not import PSS/E')

psspy = Import_PSSE()
_f = psspy._f
_i = psspy._i
_s = psspy._s

#///////////////////////////////////////////////////////////////////////////////

def Redirect_PSSE(fileName, redirectPrompt=True, redirectProgress=True, redirectReport=True, redirectAlert=True, append=False):
	if (fileName is None):
		q = 0
	else:
		q = {True: 2, False: 0}[append]
	if (fileName is None):
		fileName = ''
	fileName = str(fileName)
	a = {True: 2, False: 1}
	b = {True: fileName, False: ''}
	if (fileName.upper() == 'NUL'):
		b[True] = ''
		a[True] = 6
	c = [
		(psspy.prompt_output, redirectPrompt),
		(psspy.progress_output, redirectProgress),
		(psspy.report_output, redirectReport),
		(psspy.alert_output, redirectAlert),
		]
	for f, v in c:
		err = f(a[v], b[v], [q, 0])
		assert(err == 0)
	
def Unredirect_PSSE(): Redirect_PSSE(None, False, False, False, False)

def defargs(dv, n, *more):
	nn = len(more) / 2
	assert(nn * 2 == len(more))
	r = [dv] * n
	for k in xrange(nn):
		i = more[k * 2]
		v = more[k * 2 + 1]
		assert(isinstance(i, int))
		assert(i >= 0 and i < n)
		r[i] = v
	return r
		
