from xml.etree import ElementTree
import tkinterladder as ladder
import block_functions

def block_from_xml(IOlist,block):
	newblock = ladder.block()
	funcxml = block.find('function')
	#print funcxml.text
	if funcxml is None:
		raise Warning('bad xml in a block, no function name' + str(block))
	functxt = funcxml.text
	if block_functions.BLOCK_FUNCTION_DICT.has_key(functxt):
		newblock.function = block_functions.BLOCK_FUNCTION_DICT[functxt]()
	argsxml = block.find('arguments')
	for arg in argsxml.getchildren():
		newargument = None
		if arg.tag == 'item':
			if IOlist.has_key(arg.text):
				newargument = IOlist[arg.text]
			else:
				raise Warning('bad xml in a block\'s arguments.  Cannot resolve IO name: ' + arg.text)
		elif arg.tag == 'block':
			newargument = block_from_xml(IOlist,arg)
		else:
			raise Warning('bad xml in block\'s arguments.  Not an item or block')
		if newargument is not None:
			newblock.arguments.append(newargument)
	return newblock

def create_ladder(xmlfile):
	data = ElementTree.parse(xmlfile)

	ladderxml = data.getroot()
	#Set up IO
	IOxml = ladderxml.find('IO')
	IOlist = {}
	for item in IOxml.getchildren():
		value = None
		valuetxt=None
		newIO = None
		if item.tag != 'item':
			Warning('bad xml in the IO section: expected an <item>: '  + str(item.tag))
			continue
		namexml = item.find('name')
		typexml = item.find('type')
		descxml = item.find('desc')
		valuexml = item.find('value')

		#if (not namexml) and (not typexml):
			#raise Warning('bad xml in the IO section: missing name or type: '  + str(item.tag))
			#continue
		nametxt = namexml.text
		typetxt = typexml.text

		if not descxml:
			desctxt = ''
		else:
			desctxt = descxml.text

		if valuexml is not None:
			valuetxt = valuexml.text

		if typetxt=='int':
			value = int(valuetxt)
		elif typetxt=='str':
			value = str(valuetxt)
		elif typetxt=='bool':
			value = bool(valuetxt)
		else:
			value = valuetxt
		#print nametxt,
		newIO = ladder.IO(value,nametxt,typetxt,description=desctxt)
		#print newIO

		if newIO is not None:
			IOlist[nametxt] = newIO
	#print "-----"
	#rint IOlist
	#rint "-----"




	#Set up Rungs

	#Rungsxml = ladderxml.findall('Rung')
	Rungslist = ladderxml.findall('Rung')
	Rungs = [] 
	for rung in Rungslist:
	#for item in Rungsxml.getchildren():
		#print "addrung"
		newrung = ladder.rung()

		for rungside in rung.getchildren():
			for subitem in rungside.getchildren():
				block = None
				if subitem.tag != 'block':
					Warning('bad xml in Rung input section, excpeted a block' + str(subitem.tag))
					#print "error here", subitem.tag
					continue
				
				block = block_from_xml(IOlist,subitem)

				if block is not None:
					if rungside.tag == 'input':
						newrung.inputs.append(block)
					elif rungside.tag == 'output':
						newrung.outputs.append(block)
					else:
						Warning('bad xml in the Rung section, expected input or output block: ' + str(item.tag))
						pass


		
			continue
		Rungs.append(newrung)
	IOlist = IOlist.values()
	##print "---"
	#print Rungs
	#print "+++"
	return [Rungs, IOlist]

def io_to_xml(IO):
	itemxml = ElementTree.Element('item')
	namexml = ElementTree.SubElement(itemxml,'name')
	namexml.text = str(IO.name)
	typexml = ElementTree.SubElement(itemxml,'type')
	typexml.text = str(IO.typedesc)
	descxml = ElementTree.SubElement(itemxml,'description')
	descxml.text = str(IO.description)
	valuexml = ElementTree.SubElement(itemxml,'value')
	valuexml.text = str(IO.value)

	return itemxml

def block_to_xml(Block):
	itemxml = ElementTree.Element('block')
	functionxml = ElementTree.SubElement(itemxml,'function')
	functionxml.text = Block.function.name
	argumentsxml = ElementTree.SubElement(itemxml,'arguments')
	for arg in Block.arguments:
		if isinstance(arg,ladder.IO):#arg.__class__ == ladder.IO.__class__:
			argxml = ElementTree.SubElement(argumentsxml,'item')
			argxml.text = arg.name
		elif isinstance(arg,ladder.block):#arg.__class__ == ladder.block.__class__:
			argxml = block_to_xml(arg)
			argumentsxml.append(argxml)
		else:
			raise Exception('bad type' + str(ladder.IO.__class__) + " " + str(arg.__class__))
	return itemxml

def create_xml(Rungs,IO,filename):
	ladderxml = ElementTree.Element('ladder')
	#take care of IO
	IOxml = ElementTree.SubElement(ladderxml,'IO')
	for item in IO:
		itemxml = io_to_xml(item)
		IOxml.append(itemxml)

	#Set up Rungs
	for rung in Rungs:
		Rungxml = ElementTree.SubElement(ladderxml,'Rung')
		inputsxml = ElementTree.SubElement(Rungxml,'input')
		outputsxml = ElementTree.SubElement(Rungxml,'output')

		for block in rung.inputs:
			b = block_to_xml(block)
			inputsxml.append(b)
		for block in rung.outputs:
			b = block_to_xml(block)
			outputsxml.append(b)
	tree = ElementTree.ElementTree(ladderxml)
	tree.write(filename)
	return True
