
import copy
import decisiondiagram_core

DecisionDiagram = decisiondiagram_core.DecisionDiagram

def evaluate(dd, assignment):
	new_dd = copy.copy(dd)
	new_dd.evaluate(assignment)
	return new_dd

def merge(dd_list):
	new_dd = DecisionDiagram()
	for i in range(len(dd_list)):
		new_dd.merge(dd_list[i])
	return new_dd

def ite(ddc, ddv_list):
	def getID(val):
		return val[0]
	new_dd = 0
	if ddc.isConst():
		return ddv_list[getID(ddc.getVal(dict()))]
	else:
		dds = list()
		vars = list(ddc.vars())
		for val in range(ddc.var_dict[vars[0]]):
			sub_ddv_list = list()
			for dd in ddv_list:
				sub_ddv_list.append(evaluate(dd, {vars[0]:val}))
			dds.append(ite(evaluate(ddc, {vars[0]:val}), sub_ddv_list))
		new_dd = merge(dds)
		new_dd.setRoot(new_dd.addNewNode(vars[0], tuple(new_dd.getRoot()), ddc.var_dict[vars[0]]))
	return new_dd

def combine_more(dd_list):
	new_dd = dd_list[len(dd_list)-1]
	for i in range(len(dd_list)-2, -1, -1):
		new_dd = combine(dd_list[i], new_dd)
	return new_dd

def combine(dd1, dd2):
	if dd1.isConst():
		new_dd = copy.copy(dd2)
		new_dd.attach_left(dd1.getVal(dict()))
	elif dd2.isConst():
		new_dd = copy.copy(dd1)
		new_dd.attach_right(dd2.getVal(dict()))
	else:
		dds = list()
		vars = list(dd1.vars())
		for val in range(dd1.var_dict[vars[0]]):
			dds.append(combine(evaluate(dd1, {vars[0]:val}), evaluate(dd2, {vars[0]:val})))
		new_dd = merge(dds)
		new_dd.setRoot(new_dd.addNewNode(vars[0], tuple(new_dd.getRoot()), dd1.var_dict[vars[0]]))
	return new_dd

def reorder(dd, order):
	old_dd = dd
	order.reverse()
	for var in order:
		bound = old_dd.var_dict[var]
		tmpdd = []
		for i in range(bound):
			tmpdd.append(evaluate(old_dd, {var:i}))
		new_dd = merge(tmpdd)
		
		new_dd.setRoot(new_dd.addNewNode(var, tuple(new_dd.getRoot()), old_dd.var_dict[var]))
		old_dd = new_dd
	return new_dd

