#Created by dan december 2011.  www.danomagnum.com
#from ttk import Label, Button#, Checkbutton, Style
import tkSimpleDialog
import block_functions


functionlist = block_functions.BLOCK_FUNCTION_LIST
itemlist = [] #need to fill this in to add stuff I guess

class Fault(Exception):
	pass

class IO(object):
	def __init__(self,value,name,typedesc,input=False,description=""):
		self.latched = False
		self.input = input
		self.typedesc = typedesc
		self.set(value)
		self.name=name

		self.description = description

	def delifparent(self,parent):
		displays = self.display[:]
		for d in displays:
			if d.master == parent:
				#I am a child of you, so I wll delete myself
				self.display.remove(d)
				d.destroy()
		if not self.display:
			del(self)

	def set(self,value=0):
		if self.latched:
			return False
		if self.typedesc == 'bool':
			if isinstance(value,bool) or value == 1 or value == 0:
				self.value = bool(value)
			else:
				raise Fault('Value tried to be set to something not a bool')
		else:
			self.value = value
		return True

	def latchon(self):
		self.latched = True
		if self.typedesc == 'bool':
			self.value = True

	def latchoff(self):
		self.latched = True
		if self.typedesc == 'bool':
			self.value = False

	def unlatch(self):
		self.latched = False


	def status(self):
		return self.value

	def __nonzero__(self):#evaluates the decision block
		if self.value:
			return True
		else:
			return False

	def __repr__(self):
		return str(self.value) + ' ' + self.name
	def __eq__(self,n):
		return self.value == n
	def __lt__(self,n):
		return self.value < n
	def __gt__(self,n):
		return self.value > n
	def __ge__(self,n):
		return self.value >= n
	def __le__(self,n):
		return self.value <= n
	def __trunc__(self):
		return self.value
	def __int__(self):
		try:
			i = int(self.value)
		except:
			i = 0
		return i
	def toggle(self):
		if self.latched == False:
			self.value = not self.value


	def properties(self):
		ds = self.name + "\n" + str(self.value) + "\n"
		ds += "Force: "
		if self.latched:
			ds += "on"
		else:
			ds += "off"
		ds += "\nDescription:" + self.description
		return ds



class block(object):
	def __init__(self,function = block_functions.DEFAULT,parent=None,output=False,rung=None):
		self.faulted = False
		self.function = function()
		self.name = self.function.name
		self.arguments = []
		#self.display = None
		#self.frm2 = None
		self.rung=rung
		#self.popupparent = None
		#if parent:
		#	#self.display_new(parent)
		#if output:
		#	#self.display_update_output()
		#else:
		#	#self.display_update()


	def status(self):
		return self.function.on(*self.arguments)

	def run(self,on=True):
		try:
			if on:
				self.function.on(*self.arguments)
			else:
				self.function.off(*self.arguments)
			self.faulted = False
		except:
			self.faulted = True
			raise
		
	def __nonzero__(self):#evaluates the decision block
		return self.status()


	def properties(self):
		ds = self.function.properties() + "\n\n"
		return ds


class rung(object):
	def __init__(self):
		self.inputs = []
		self.outputs = []

	def run(self):
		conds = map(lambda x:x.status(),self.inputs)
		if all(conds) or not self.inputs:
			map(lambda x:x.run(),self.outputs)
		else:
			map(lambda x:x.run(on=False),self.outputs)
			

def closeblock(bit):
	b = block()
	b.arguments.append(bit)
	return b


if __name__ == '__main__':
	I1 = create_binary_array(10,'I1:0/')

	b1 = block()
	b1.function = func_and
	b1.arguments.append(I1[0])
	b1.arguments.append(I1[1])
	I1[0].set(True)
	I1[1].set(True)


	a = value_word(0)

	out1 = block()
	out1.function = func_add
	out1.arguments.append(a)
	out1.arguments.append(1)

	out1.run()

	r = rung()
	r.inputs += [b1]
	r.outputs += [out1]

	r.run()

	I1[0].set(False)
	r.run()




