
__author__ = 'Miroslav Bauer'


import zmq
import simplejson
from job import Job, JobParam
from resource import ResourceAgent

def toJob(jsonData):
	''' Converts job's json representation into Job object '''

	if 'runscript' not in jsonData:
		raise TypeError('Invalid format: runscript missing')
	if 'file' not in jsonData['runscript']:
		raise TypeError('Invalid format: runscript file missing')
	runscript  = jsonData['runscript']
	executable = runscript['file']
	deps       = runscript.get('required', [])
	reqEnv     = runscript.get('requires', {})	
	env        = jsonData.get('environment', {})
	prefRes    = jsonData.get('preferred', None)

	if 'parameters' not in jsonData:
		raise TypeError('Invalid format: parameters')
	params = jsonData['parameters']
	paramsDict = {}

	for param in params:
		if 'pos' not in param:
			raise TypeError('Invalid format: missing param pos')
		pos = param['pos']
		if pos in paramsDict:
			raise TypeError('Invalid format: multiple params with same pos')

		if 'type' not in param:
			raise TypeError('Invalid format: missing param type')
		ptype = param['type']

		if 'inout' not in param:
			raise TypeError('Invalid format: missing param inout')
		direction = param['inout']

		value = param.get('value', None)
		name  = param.get('name', None)

		paramsDict[pos] = JobParam(pos, ptype, direction, value, name)

	return Job(executable, paramsDict, deps, env, reqEnv, prefRes)

def toResources(jsonData, context):
	''' Converts resources json representation into dict(resourcename:ResourceAgent) '''
	resourcesDict = {}
	for name in jsonData.keys():
		if name in resourcesDict:
			raise TypeError('Duplicit declaration of resource: %s' % name)
		res = jsonData[name]
		enabled = int(res.get('enabled','1'))
		if not enabled: continue

		# Changed attribute name
		# TODO: Uncomment when updated on web side by Pavel
		#if 'jobbackend' not in res:
		if 'agent' not in res:
			raise TypeError('Invalid format: missing backend for %s' % name)
		# TODO: backend = res['backend']
		jobbackend = res['agent'].lower()

		if 'user' not in res:
			raise TypeError('Invalid format: missing user for %s' % name)
		user   = res['user']

		authmethod = res.get('authmethod', None)
		if not authmethod and jobbackend == 'ssh': authmethod = 'ssh'
		key    = None
		passwd = None

		if authmethod == 'ssh':
			if ('password' not in res) and ('key' not in res):
				raise TypeError('SSH key or password missing'\
						'for SSH backend for %s' % name)
			key    = res.get('key', None)
			passwd = res.get('password', None)

		auth = {}
		auth['user_id'] = user
		auth['method'] = authmethod
		if key:
			auth['key'] = key
		elif passwd:
			auth['pwd'] = passwd

		xfer = res.get('xfer', 'sftp')
		port = ''
		if 'port' not in res:
			if (authmethod and authmethod.startswith('ssh')) or jobbackend == 'ssh':
				port = ':22'
		else:
			port = ':%s' % res['port']

		if 'hostname' not in res:
			raise TypeError('Invalid format: missing hostname for %s' % name)
		if xfer == 'file': res['hostname'] = 'localhost'
		endpoint = '%s%s' % (res['hostname'], port)

		scratchdir = res.get('scratchdir', None)

		feats = {}
		feats['packages'] = res.get('packages', [])
		feats['os'] = res.get('os', [])
		feats['arch'] = res.get('arch', [])

		env = res.get('environment', {})

		resourcesDict[name] = ResourceAgent(context, name, enabled, endpoint, jobbackend,
					auth, xfer, env, scratchdir, feats)
	return resourcesDict

def createPoller(sockets):
	''' Creates zmq.Poller with sockets registered for polling '''
	poll = zmq.Poller()
	[ poll.register(s, zmq.POLLIN) for s in sockets ]	
	return poll


def flatten(array):
	return sum( ([x] if not isinstance(x, list) else flatten(x) for x in array), [] )

def stateToStr(statecode, stateMap):
	''' Converts state code to it's string representation '''
	for name, code in stateMap.items(): 
		if code == statecode: return name

