<?
	require_once("site.phtml");
	require_once("incl_dobject.phtml");
	require_once("Sajax.php");

	//
	// Basic, useless Hierarchy
	//	
	class Hierarchy extends DebuggableObject {
		function Hierarchy() {
			$this->levels = array();
			$this->DebuggableObject();
		}
		
		function addLevel($level_n, $label, $form_field_id, $get_values_callback, $cur_value = "") {
			if (! preg_match("/[A-Za-z_]+[A-Za-z0-9_]*/", $form_field_id))
				$this->error("Invalid form field id \"$form_field_id\"");
			if (! function_exists($get_values_callback)) 
				$this->error("Unknown function \"$get_values_callback\"");
			
			$this->levels[$level_n] = array(
				"n" => $level_n,
				"label" => $label,
				"field_id" => $form_field_id,
				"callback" => $get_values_callback,
				"value" => $cur_value);
			sajax_export($get_values_callback);
		}
		
		function setTarget($type, $data_a = false, $data_b = false) {
			if ($type == "var") $type = "variable";
			
			if ($type == "variable") {
				$this->target_type = $type;
				$this->target_var = $data_a;
			} else {
				$this->error("setTarget(): \"$type\" is an unknown type");
			}
		}
		
		function setValue($n_or_id, $value) {
			if (is_numeric($n_or_id)) {
				$this->levels[$n_or_id]["value"] = $value;
				return true;
			} else {
				reset($this->levels);
				foreach ($this->levels as $lvl)
					if ($lvl["field_id"] == $n_or_id) {
						$this->levels[$lvl->n]["value"] = $value;
						return true;
					}
			}
		}
		
		// Assign current values for each of the levels, based on the contents of $array.
		function setValues($array) {
			foreach ($this->levels as $lvl) {
				$n = $lvl["n"];
				$id = $lvl["field_id"];
				if (! empty($array[$id]))
					$this->levels[$n]["value"] = $array[$id];
			}
		}
	}
	
	
	
	//
	// Basic select-oriented hierarchy
	//
	class SelectHierarchy extends Hierarchy {
		function SelectHierarchy() {
			$this->Hierarchy();	
		}
		
		function renderHeader() {
			$html = "<script><!--\n";
			$html.= "// Hierarchy Common JavaScript..\n";
			$html.= sajax_get_javascript();
			$html.= "// --></script>";
			return $html;
		}
		
		function renderLevel($n) {
			$this->debug("renderLevel($n)..");
			reset($this->levels);
			
			$n_plus_1 = $n + 1;
			$lvl = $this->levels[$n];
			$v_h = htmlspecialchars($lvl["value"]);
			$id = $lvl["field_id"];
			$html = "";
			
			$other_values_str = "";
			for ($i = $n - 1; $i >= 0; $i--) {
				$other_values_str .= "Select.get(\"" . $this->levels[$i]["field_id"]."\"), ";
			}
			
			// if we arent the final select..
			if ($n < count($this->levels)-1) 
				$next_action_str = "h_populate_" . $this->levels[$n_plus_1]["field_id"] . "();";
			else
				$next_action_str = "h_finalize();";
			
			$html .= "
				<script language=\"JavaScript\">
				<!--
				// populate $id with values.
				function h_populate_$id() {
					x_$lvl[callback]($other_values_str h_data_ready_$id);
				}
				// fill up the select
				function h_data_ready_$id(data) {
					Select.clear(\"$id\");
					Select.add(\"$id\", \"\", \"$lvl[label]\");
					for (var i in data) {
						Select.add(\"$id\", data[i]);
					}
				}
				// handle changes in $id
				function h_onchange_$id() {
					$next_action_str
				}
				// -->
				</script>
				
				<select name=\"$lvl[field_id]\" id=\"$lvl[field_id]\" value=\"$v_h\" onchange=\"h_onchange_$id();return true;\">
				<option value=\"\">$lvl[label]</option>
				</select>
				";

			return $html;
		}
		
		function renderFooter() {
			if (empty($this->target_type)) 
				$this->error("renderFooter(): no target type configured");
			if ($this->target_type != "variable")
				$this->error("renderFooter(): only target_type var ed");

			reset($this->levels);
			$concatter = array();
			for ($i = 0; $i < count($this->levels); $i++) {
				$concatter[] = "Select.get(\"" . $this->levels[$i]["field_id"]."\")";
			}
			$concat = ("+'%%%'+", $concatter);
			$first_id = $this->levels[0]["field_id"];
			return "
				<script>
				function h_finalize() {
					var e = elem('$this->target_var');
					if (typeof e == \"object\") {
						e.value = $concat;
					} else {
						e = $concat;
					}
				}
				setTimeout(\"h_populate_${first_id}()\", 150);
				</script>
				";
		}
		
		function render() {
			$n = 0;
			$html = $this->renderHeader();
			reset($this->levels);
			foreach ($this->levels as $lvl) {
				$html .= $this->renderLevel($n);
				$n++;
			}
			$html .= $this->renderFooter();
			return $html;
		}
		
		function handleRequest() {
			$this->debug("handleRequest()..");
			sajax_handle_client_request();
			return true;
		}
	}



	//
	// TreeHierarchy
	//
	class TreeHierarchy extends Hierarchy {
		function HtmlTreeHierarchy() {
			$this->Hierarchy();	
		}
		
		function renderHeader() {
			$html = "<script><!--";
			$html.= sajax_get_javascript();
			$html.= "
				
				var h_closed_img = '<img src=folder-closed.gif border=0>';
				var h_open_img = '<img src=folder-open.gif border=0>';
				
				function h_open_or_close(id, data_key) {
					var child_elem_id = 'h-child-' + id + data_key;
					var button_elem_id = 'h-button-' + id + data_key;
					var open_or_closed = elem(child_elem_id).getAttribute('hstatus');
					if (open_or_closed == 'open') {
						Element.hide(child_elem_id);
						Element.Class.remove(child_elem_id, 'h-open');
						Element.Class.add(child_elem_id, 'h-closed');
						// alert('Classes after closing.. ' + get_repr(Element.Class.get(child_elem_id)));
						elem(child_elem_id).setAttribute('hstatus', 'closed');
						elem(button_elem_id).innerHTML = h_closed_img;
					} else {
						eval('h_load_data_' + id + '(\'' + data_key + '\')');
						Element.show(child_elem_id);
						Element.Class.remove(child_elem_id, 'h-closed');
						Element.Class.add(child_elem_id, 'h-open');
						// alert('Classes after opening.. ' + get_repr(Element.Class.get(child_elem_id)));
						elem(child_elem_id).setAttribute('hstatus', 'open');
						elem(button_elem_id).innerHTML = h_open_img;
					}
				}
				
				function h_click(id, data_key) {
					// alert('h_click(id: ' + id + ' data: ' + data_key + ')');
					h_open_or_close(id, data_key);
				}
				
				function h_make_link(my_id, my_data_key, child_id, child_data_key) {
					var html = '';
					
					html = html + '<a hstatus=\"closed\" class=\"h-button\" id=\"h-button-' + child_id + child_data_key + '\" href=\"#\" onclick=\"h_click(\'' + child_id + '\',\'' + child_data_key + '\')\">';
					html = html + h_closed_img + '</a>';
					return html;
				}
				
				function h_make_empty_child(level, child_id, child_data_key) {
					return '<ul hstatus=\"closed\" class=\"h-closed h-tree-' + level + '\" id=\"h-child-' + child_id + child_data_key + '\"></ul>';
				}
				
				// --></script><div class=\"h-tree\">";
			return $html;
		}
		
		function renderLevel($n) {
			$this->debug("renderLevel($n)..");
			reset($this->levels);
			
			$n_plus_1 = $n + 1;
			$lvl = $this->levels[$n];
			$v_h = htmlspecialchars($lvl["value"]);
			$id = $lvl["field_id"];
			$callback = $lvl["callback"];
			
			$is_first = $n == 0 ? 1 : 0;
			$is_last = $n == count($this->levels)-1 ? 1 : 0;
			
			if (! $is_first) {
				$prev_id = $this->levels[$n-1]["field_id"];
				$prev_level = $n - 1;
			} else {
				$prev_id = "";
				$prev_level = 0;
			}
				
			if (! $is_last) {
				$next_id = $this->levels[$n+1]["field_id"];
				$next_level = $n+1;
			} else {
				$next_id = "";
				$next_level = 0;
			}
				
			$html = "<script><!--
			
			function h_load_data_$id(data_key) {
				if (! data_key)
					data_key = '';
				
				x_$callback(data_key, { callback: h_ready_cb_$id, extra_data: data_key });
			}
			
			function h_ready_cb_$id(data, this_data_key) {
				// populate the UL and build sub-ULs.
				
				var html = '';
				
				if (! this_data_key)
					this_data_key = '';
				
				for (var child_data_key in data) {
					var label = data[child_data_key];
					
					html = html + '<li> ';
					if (child_data_key != 0 && $is_last == 0) {
						html = html + h_make_link('$id', this_data_key, '$next_id', child_data_key);
					}
					html = html + label;
					if (child_data_key != 0 && $is_last == 0) {
						html = html + h_make_empty_child($next_level, '$next_id', child_data_key);
					}
				}
				
				elem('h-child-$id' + this_data_key).innerHTML = html;
			}
			
			// --></script>";
			
			if ($is_first)
				$html .= "<ul id=\"h-child-$id\" class=\"h-closed h-tree-0\"></ul>";
			
			return $html;
		}
		
		function renderFooter() {
			$first_id = $this->levels[0]["field_id"];
			$html = "<script><!--
			
			setTimeout('h_open_or_close(\'$first_id\', \'\');', 100);
			
			// --></script>
				</div>";
			return $html;
		}
		
		function render() {
			global $sajax_debug_mode;
			
			$n = 0;
			// $sajax_debug_mode = true;
			$html = $this->renderHeader();
			reset($this->levels);
			foreach ($this->levels as $lvl) {
				$html .= $this->renderLevel($n);
				$n++;
			}
			$html .= $this->renderFooter();
			return $html;
		}
		
		function handleRequest() {
			sajax_handle_client_request();
			return true;
		}
	}
?>
