// Artificial cell (PointProcess with NET_RECEIVE that calls net_event)
// with specific parameters

begintemplate ArtCell
public name, ms, is_art, index
public classname, save_class

public create1, tobj, change

strdef name, tstr
objref ms, tobj, nil, this, all

proc init() {
	created_ = 0
	$o1.name(name)
	ms = new MechanismStandard(name)
	if (numarg() == 2) {
		name = $s2
	}else{
		ms.name(name)
	}
	ms.in($o1)
	is_art = 1
	index = -1
}

proc classname() {
	ms.name($s1)
	sprint($s1, "%s_%s", name, $s1)
}

proc save_class() {
	classname(tstr)
	$o1.printf("\nbegintemplate %s\n", tstr)
	$o1.printf("public pp, connect2target, x, y, z, position, is_art\n")
	$o1.printf("objref pp\n")
	$o1.printf("proc init() {\n")
	ms.name(tstr)
	$o1.printf("  pp = new %s()\n", tstr)
	synbody($o1)
	$o1.printf("}\n")
	$o1.printf("func is_art() { return 1 }\n")
	$o1.printf("obfunc connect2target() { localobj nc\n  nc = new NetCon(pp, $o1)\n  if (numarg() == 2) { $o2 = nc }\n  return nc\n}\n")
	$o1.printf("proc position(){x=$1  y=$2  z=$3}")
	classname(tstr)
	$o1.printf("\nendtemplate %s\n", tstr)
}

proc synbody() {local i, j, size
	tobj = new MechanismStandard(tstr)
	for i=0,tobj.count-1 {
		size = tobj.name(tstr, i)
	    for j=0, size-1 {
		if (tobj.get(tstr, j) != ms.get(tstr, j)) {
			if (size == 1) {
$o1.printf("    pp.%s = %g\n", tstr, ms.get(tstr, j))
			}else{   
$o1.printf("    pp.%s[%d] = %g\n", tstr, j, ms.get(tstr, j))
			}
		}
	    }
	}
}

proc create1() {
	created_ = 1
	classname(tstr)
	sprint(tstr, "%s.tobj = new %s()", this, tstr)
	execute(tstr)
	$o1 = tobj
	tobj = nil
	ms.out($o1.pp)
}

proc change() {local i
	if (created_) {
		if (all == nil) {
			classname(tstr)
			all = new List(tstr)
		}
		for i=0, all.count-1 {
			ms.out(all.object(i).pp)
		}
	}
}

endtemplate ArtCell

// A list of ArtCell's
begintemplate ArtCellGUI
public name, save, save_data, map, actypelist, hb
external ArtCell, valid_name_syntax
strdef name, tstr, tstr1
objref this, tobj, tobj1, mslist, actypelist, vb, hb, d

proc init() {local i
	actypelist = new List()
	possible_targets() // mslist is a list of MechanismStandards
	build()
	if (numarg() == 0) {
		map()
	}
}

proc map() {
	sprint(tstr, "%s", this)
	if (numarg() > 1) {
		hb.map(tstr, $2,$3,$4,$5)
	}else{
		hb.map(tstr)
	}
}

proc possible_targets() {
	mslist = new List()
	//figure out which PointProcesses can be targets of a NetCon
	tobj = new MechanismType(1) // all point processes
	for i=0, tobj.count-1 {
		if (tobj.is_netcon_target(i) && tobj.has_net_event(i) != 0) {
			tobj.select(i)
			tobj.selected(tstr)
			mslist.append(new MechanismStandard(tstr))
		}
	}
}

proc build() {
	hb = new HBox(3)
	hb.priority(999)
	hb.save("save()")
	hb.intercept(1)
	hb.ref(this)
	vb = new VBox(3)
	vb.intercept(1)
	xpanel("")
	xmenu("New")
		for i=0, mslist.count-1 {
			mslist.object(i).name(tstr)
			sprint(tstr1, "newstype(%d)", i)
			xbutton(tstr, tstr1)
		}
	xmenu()
	xlabel("Using Current Selection...")
	xbutton("Rename", "rename()")
	xbutton("Clone", "clone()")
	xbutton("Remove", "remove()")
	xlabel("Artificial Cell types")
	xpanel()
	actypelist.browser("", "name")
	actypelist.select_action("selstype(hoc_ac_)")
	vb.intercept(0)
	vb.map()
	d = new Deck(3)
	d.intercept(1)
	xpanel("")
	xlabel("Variables for selected Cell type appear here")
	xpanel()
	d.intercept(0)
	d.map()
	d.flip_to(0)
	hb.intercept(0)
}

proc append() {local i
	actypelist.append(new ArtCell($o1, $s2))
	dinsert(actypelist.count-1)
	selstype(actypelist.count-1)
}

proc newstype() {local i
	actypelist.append(new ArtCell(mslist.object($1)))
	dinsert(actypelist.count-1)
	selstype(actypelist.count-1)
}

proc dinsert() {
	d.intercept(1)
	tobj = actypelist.object($1)
	sprint(tstr, "%s.change()", tobj)
	tobj.ms.action(tstr)
	tobj.ms.name(tstr)
	sprint(tstr, "%s  -- %s", tobj.name, tstr)
	tobj.ms.panel(tstr)
	d.intercept(0)
	d.move_last($1)
}
proc rename() { local i
	i = actypelist.selected
	if (i == -1) return
	tobj = actypelist.object(i)
	tstr = tobj.name
	while (string_dialog("Rename the artificial cell type", tstr)) {
		if (valid_name_syntax(tstr, 1)) {
			tobj.name = tstr
			break
		}
	}
	actypelist.remove(i)
	actypelist.insrt(i, tobj)
	d.remove(i)
	dinsert(i)
	selstype(i)
}

proc clone() {local i
	i = actypelist.selected
	if (i == -1) return
	tobj = actypelist.object(i)
	actypelist.append(new ArtCell(tobj.ms, tobj.name))
	dinsert(actypelist.count-1)
	selstype(actypelist.count-1)
}

proc remove() {local i
	i = actypelist.selected
	if (i == -1) return
	actypelist.remove(i)
	d.remove(i)
	selstype(-1)
	objref tobj
}
proc selstype() {
	if ($1 == -1) {
		d.flip_to(-1)
		return
	}
	d.flip_to($1)
	actypelist.select($1)
}

proc save() {
	hb.save("load_file(\"netbild.hoc\")\n}")
	save_data(hb, "ocbox_")
	hb.save("{")
}
proc save_data() {
	sprint(tstr, "%s = new ArtCellGUI(1)", $s2)  $o1.save(tstr)
	sprint(tstr, "{object_push(%s)}", $s2) $o1.save(tstr)
	for i = 0, actypelist.count -1 {
		tobj = actypelist.object(i)
		$o1.save("{")
		tobj.ms.save("tobj")
		$o1.save("}")
		sprint(tstr, "{append(tobj, \"%s\")}", tobj.name)
		$o1.save(tstr)
	}
	$o1.save("{object_pop()}")
}
endtemplate ArtCellGUI
