/*
 BINViz, Bidirectional Interactive Network Visualization
 Copyright (C) 2007  Benjamin Weyers, University of Michigan, Ann Arbor, MI, U.S.

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * @fileoverview Provides the PLUGIN class necessary for X
 * @author Benjamin Weyers, University of Duisburg-Essen, University of Michigan
 * @version 0.1
 */

/**
 * Constructor description
 * 
 * @constructor
 *  
 * @class Class description
 * 
 * @author Benjamin Weyers, University of Duisburg-Essen, University of Michigan
 * @version 0.1
 */
function MarimbaPlugin()
{
	this.htmlElement;
	this.graphView;
	this.marimbaNodeHash = new Array(new Object());
	
	this.currentDataTable = null;
	this.currentNode = null;
	this.currentParents = null;
	
	this.numberOfSamples;
	
	var numberValue = function(val) {
		if( isNaN(val) ) return false;
		else return true;}
	var bigger0 = function(val) {
		if ( !isNaN(val) && val > 0 ) return true;
		else return false;}
	var biggerequal0 = function(val) {
		if ( !isNaN(val) && val >= 0 ) return true;
		else return false;}
	var openInterval01 = function(val) {
		if ( !isNaN(val) && val > 0 && val < 1 ) return true;
		else return false;}
	var closeInterval01 = function(val) {
		if ( !isNaN(val) && val >= 0 && val <=1 ) return true;
		else return false;}
	var closeOpenInterval01 = function(val) {
		if ( !isNaN(val) && val >= 0 && val < 1 ) return true;
		else return false;}
	
	this.dist = [{'dist':"uniform",'param':		[{'name':'lower','con':bigger0,'value':'0.1','dep':{'param':''}},{'name':'upper','con':bigger0,'value':'0.1','dep':{'param':''}}]},
				 {'dist':"Cauchy",'param':		[{'name':'median','con':numberValue,'value':'0.1','dep':{'param':''}},{'name':'scale','con':bigger0,'value':'0.1','dep':{'param':''}}]},
				 {'dist':"Fisher_F",'param':	[{'name':'numdf','con':numberValue,'value':'0.1','dep':{'param':''}},{'name':'denomdf','con':numberValue,'value':'0.1','dep':{'param':''}}]},
				 {'dist':"Gumbel",'param':		[{'name':'median','con':numberValue,'value':'0.1','dep':{'param':''}},{'name':'scale','con':bigger0,'value':'0.1','dep':{'param':''}}]},
				 {'dist':"Laplace",'param':		[{'name':'mu','con':numberValue,'value':'0.1','dep':{'param':''}},{'name':'scale','con':bigger0,'value':'0.1','dep':{'param':''}}]},
				 {'dist':"Pareto",'param':		[{'name':'mode','con':bigger0,'value':'0.1','dep':{'param':''}},{'name':'shape','con':bigger0,'value':'0.1','dep':{'param':''}}]},
				 {'dist':"Poisson",'param':		[{'name':'rate','con':bigger0,'value':'0.1','dep':{'param':''}}]},
				 {'dist':"Rayleigh",'param':	[{'name':'mode','con':bigger0,'value':'0.1','dep':{'param':''}}]},
				 {'dist':"Student_t",'param':	[{'name':'df','con':bigger0,'value':'0.1','dep':{'param':''}}]},
				 {'dist':"Wald",'param':		[{'name':'median','con':bigger0,'value':'0.1','dep':{'param':''}},{'name':'scale','con':bigger0,'value':'0.1','dep':{'param':''}}]},
				 {'dist':"Weibull",'param':		[{'name':'scale','con':bigger0,'value':'0.1','dep':{'param':''}},{'name':'scale','con':bigger0,'value':'0.1','dep':{'param':''}}]},
				 {'dist':"Zipf",'param':		[{'name':'a','con':numberValue,'value':'0.1','dep':{'param':''}}]},
				 {'dist':"beta",'param':		[{'name':'mu','con':bigger0,'value':'0.1','dep':{'param':''}},{'name':'nu','con':bigger0,'value':'0.1','dep':{'param':''}}]},
				 {'dist':"binomial",'param':	[{'name':'trials','con':bigger0,'value':'0.1','dep':{'param':''}},{'name':'pr_success','con':closeInterval01,'value':'0.1','dep':{'param':''}}]},
				 {'dist':"chi_square",'param':	[{'name':'df','con':bigger0,'value':'0.1','dep':{'param':''}}]},
				 {'dist':"gamma",'param':		[{'name':'mu','con':bigger0,'value':'0.1','dep':{'param':''}}]},
				 {'dist':"geometric",'param':	[{'name':'pr_failure','con':closeOpenInterval01,'value':'0.1','dep':{'param':''}}]},
				 {'dist':"hypergeometric",'param':[{'name':'bad','con':bigger0,'value':'0.1','dep':{'param':''}},{'name':'good','con':bigger0},{'name':'sample','con':bigger0,'value':'0.1','dep':{'param':''}}]},
				 {'dist':"logarithmic",'param':	[{'name':'p','con':openInterval01,'value':'0.1','dep':{'param':''}}]},
				 {'dist':"logistic",'param':	[{'name':'mu','con':numberValue,'value':'0.1','dep':{'param':''}},{'name':'scale','con':bigger0,'value':'0.1','dep':{'param':''}}]},
				 {'dist':"lognormal",'param':	[{'name':'mean','con':numberValue,'value':'0.1','dep':{'param':''}},{'name':'sigma','con':bigger0,'value':'0.1','dep':{'param':''}}]},
				 {'dist':"negative_binomial",'param':[{'name':'r','con':openInterval01,'value':'0.1','dep':{'param':''}}]},
				 {'dist':"normal",'param':		[{'name':'mu','con':numberValue,'value':'0.1','dep':{'param':''}},{'name':'sigma','con':bigger0,'value':'0.1','dep':{'param':''}}]},
				 {'dist':"randint",'param':		[{'name':'lowint','con':bigger0,'value':'0.1','dep':{'param':''}},{'name':'nu','con':bigger0,'value':'0.1','dep':{'param':''}}]},
				 {'dist':"random",'param':		[]},
				 {'dist':"triangular",'param':	[{'name':'left','con':bigger0,'value':'0.1','dep':{'param':''}},{'name':'mode','con':bigger0,'value':'0.1','dep':{'param':''}},{'name':'right','con':bigger0,'value':'0.1','dep':{'param':''}}]},
				 {'dist':"von_Mises",'param':	[{'name':'Mean','con':bigger0,'value':'0.1','dep':{'param':''}},{'name':'shape','con':bigger0,'value':'0.1','dep':{'param':''}}]},
				 {'dist':"shuffel_Option",'param':[]},
				 {'dist':"in_simplex",'param':	[]},
				 {'dist':"in_sphere",'param':	[]},
				 {'dist':"initialize",'param':	[]},
				 {'dist':"on_simplex",'param':	[]},
				 {'dist':"on_sphere",'param':	[]},
				 {'dist':"permutation",'param':	[]}];
	this.paramInput = new Array(new Object());
	this.distHash = new Array(new Object());
	
	var result = new Object();
}

MarimbaPlugin.prototype = Object();

MarimbaPlugin.prototype.init=function(graphView, initData)
{
	this.graphView = graphView;
	this.graphView.registerItemChangeListener(this);
	this.htmlElement = this.createHtmlElement();
}

///////
// VIEW
///////

MarimbaPlugin.prototype.createHtmlElement=function()
{
	var div = document.createElement("div");
	this.table = document.createElement("table");
	div.appendChild(this.table);	
	
	this.distDiv = this.createDisertation()
	this.distDiv.appendChild(this.paramInput[0]["Cauchy"]);
	div.appendChild(this.distDiv);
	
	div.appendChild(this.createGlobalSettings());
	
	return div;
}

// CREATION of table
MarimbaPlugin.prototype.createColumnSet=function(nodeData, parents)
{
	if ( nodeData.getData() instanceof Array ) {
		var top = document.createElement("tr");
		var colgroup = document.createElement("colgroup");
		
		for ( var i = 0; i < parents.length; i++ ) {
			var col = document.createElement("col");
			col.setAttribute("width","20px");
			colgroup.appendChild(col);
			
			var c = document.createElement("th")
			c.appendChild(document.createTextNode(parents[i].getLabel()));
			top.appendChild(c);
		}

		for ( var i = 0; i < nodeData.getData().length; i++ ) {
			var col = document.createElement("col");
			col.setAttribute("width","40px");
			colgroup.appendChild(col);
			
			var c = document.createElement("th")
			c.appendChild(document.createTextNode(nodeData.getData()[i]));
			top.appendChild(c);
		}
		this.table.appendChild(colgroup);
		this.table.appendChild(top);
		return colgroup;
	} else {
		return null;
	}
}

MarimbaPlugin.prototype.createRows=function(nodeData, rows)
{
	for ( var i = 0; i < rows.length; i++ ) {
		var row = document.createElement("tr");
		var rowData = rows[i];
		for ( var j = 0; j < rowData.length; j++ ) {
			var th = document.createElement("th");
			th.appendChild(document.createTextNode(rowData[j]));
			row.appendChild(th);
		}
		for ( var j = 0; j < nodeData.getData().length; j++ ) {
			var th = document.createElement("th");
			var input = document.createElement("input");
			var data = this.marimbaNodeHash[0][nodeData.getId()].getTable();
			input.style.width = "40px";
			if ( data[i+1][j] == undefined ) data[i+1][j] = 0;
			input.value = data[i+1][j];
			input.indexX = i+1;
			input.indexY = j;
			
			input.onkeydown = function(){
				if ( isNaN(this.value) || this.value < 0 || this.value > 1 ) this.value = data[this.indexX][this.indexY];
				else data[this.indexX][this.indexY] = parseFloat(this.value);
			}
			
			input.onfocus = function(){
				this.select();
			}
			
			th.appendChild(input);
			row.appendChild(th);
		}
		this.table.appendChild(row);
	}	
}

MarimbaPlugin.prototype.createRowsArray=function(array, row, parents, index)
{
	if ( parents != null && !this.graphView.fixed ) {
		if ( index < parents.length - 1 ) {
			for ( var i = 0; i < parents[index].getData().length; i++ ) {
				row[index] = parents[index].getData()[i];
				array = this.createRowsArray(array, row, parents, index + 1);
				var temp = new Array();
				for ( var j = 0; j < index; j++ ) temp[j] = row[j];
				row = temp;
			}
			return array;
		} else {
			for ( var i = 0; i < parents[index].getData().length; i++ ) {
				row[index] = parents[index].getData()[i];
				array.push(row);
				var temp = new Array();
				for ( var j = 0; j < index; j++ ) temp[j] = row[j];
				row = temp;
			}
			return array;
		}
	}
}

MarimbaPlugin.prototype.closeTable=function()
{
	this.table = document.createElement("table");
	this.htmlElement.replaceChild(this.table, this.htmlElement.childNodes[0]);
}

// CREATION of disertation selection

MarimbaPlugin.prototype.createDisertation=function()
{
	this.distSelector = document.createElement("select");
	var distLabel = document.createElement("span");
	distLabel.appendChild(document.createTextNode("Distribution: "));
	var t = this;
	for ( var i = 0; i < this.dist.length; i++ ) {
		var option = document.createElement("option");
		option.appendChild(document.createTextNode(this.dist[i].dist));
		this.distSelector.appendChild(option);
		this.distHash[0][this.dist[i].dist] = i;
		 
		var parameters = document.createElement("span");
		for ( var j = 0; j < this.dist[i].param.length; j++ ) {
			parameters.appendChild(document.createTextNode(" " + this.dist[i].param[j].name + ": "));
			var input = document.createElement("input");
			input.style.width="40px";
			input.param = this.dist[i].param[j];
			input.value = "---";
			input.con = this.dist[i].param[j].con;
			input.dep = this.dist[i].param[j].dep;
			input.defaultValue = "---";

			input.onblur = function() {
				var value = new Array();
				if ( this.con(this.value) && t.currentNode != null ) t.marimbaNodeHash[0][t.currentNode.getId()].setDistParam(this.param.name,this.value);
				else this.value = this.defaultValue;
			}
			
			input.onfocus = function(){
				this.select();
			}
			
			parameters.appendChild(input);
		}
		this.paramInput[0][this.dist[i].dist] = parameters;
		
		// change Listener
	}
	
	this.distSelector.onchange = function() {
		t.setInputFields(this.value);
	}
	
	var cont = document.createElement("div");
	cont.appendChild(distLabel);
	cont.appendChild(this.distSelector);
	
	return cont;
}

MarimbaPlugin.prototype.setInputFields=function(value)
{
	this.distDiv.removeChild(this.distDiv.childNodes[2]);
	this.distDiv.appendChild(this.paramInput[0][value]);
	if ( this.currentNode != null ) {
		this.marimbaNodeHash[0][this.currentNode.getId()].setDistribution(value);
		this.marimbaNodeHash[0][this.currentNode.getId()].distParams = new Array();
	}
}

MarimbaPlugin.prototype.createGlobalSettings=function()
{
	var div = document.createElement("div");
	var labelSamples = document.createElement("span");
	labelSamples.appendChild(document.createTextNode("Number of Observations: "));
	var inputSamples = document.createElement("input");
	var commit = document.createElement("button");
	commit.appendChild(document.createTextNode("Commit"));
	div.appendChild(labelSamples);
	div.appendChild(inputSamples);
	div.appendChild(commit);
	
	var t = this;
	inputSamples.onblur = function() {
		var numberValue = function(val) {
		if( isNaN(val) ) return false;
		else return true;}
		
		if ( numberValue(this.value) ) t.numberOfSamples = parseInt(this.value);
		else this.value = "";
	}
	
	inputSamples.onfocus = function(){
		this.select();
	}
	
	commit.onclick = function() {
		t.sendJSONObject();
	}
	
	return div;
}

////////
// MODEL
////////
MarimbaPlugin.prototype.resetTableData = function(nodeData, parents)
{
	var numberOfParentsStates = 1;
	var array = new Array(parents);
	
	for ( var i = 0; i < parents.length; i++ ) 
		numberOfParentsStates = numberOfParentsStates * parents[i].getData().length;
		
	for ( var i = 1; i <= numberOfParentsStates; i++ ) {
		array[i] = new Array();
		for ( var j = 0; j < nodeData.getData().length; j++ ) 
			array[i][j] = 0;
	}
	return array;
}

//////////
// PARSING
//////////
MarimbaPlugin.prototype.sendJSONObject=function()
{
	if (window.XMLHttpRequest) {
	   this.http = new XMLHttpRequest();
	} else if (window.ActiveXObject) {
	   this.http = new ActiveXObject("Microsoft.XMLHTTP");
	}
	this.http.open("POST", "http://helab.bioinformatics.med.umich.edu/bsnonline/test.php", true);
	this.http.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
	
	var edges = this.graphView.currentGraph.getEdges();
	var nodes = this.graphView.currentGraph.getNodes();
	
	// global variables
	var jsonString = "{\"observations\":\"" + this.numberOfSamples + "\",";
	
	// nodes
	jsonString += "\"nodes\":["
	
	for ( var i = 0; i < nodes.length; i++ ) {
		var parents = this.graphView.currentGraph.getParents(nodes[i]);
		var children = this.graphView.currentGraph.getChildren(nodes[i]);
		
		if ( this.marimbaNodeHash[0][nodes[i].getId()] == null ) {
			this.marimbaNodeHash[0][nodes[i].getId()] = new MarimbaNode(nodes[i]);
			this.marimbaNodeHash[0][nodes[i].getId()].setTable(this.resetTableData(nodes[i], parents));
			this.marimbaNodeHash[0][nodes[i].getId()].setDistribution("uniform");
		}
				
		if ( i != nodes.length - 1 ) 
			jsonString += this.marimbaNodeHash[0][nodes[i].getId()].asJsonObject(parents, children, ";") + ",";
		else 
			jsonString += this.marimbaNodeHash[0][nodes[i].getId()].asJsonObject(parents, children, ";");
	}
	
	// edges
	jsonString += "],\"edges\":[";
	
	for ( var i = 0; i < edges.length; i++ ) {
		if ( i != edges.length - 1)
			jsonString += "{\"nodeId1\":\"" + edges[i].getNodeId1() + "\",\"nodeId2\":\"" + edges[i].getNodeId2() + "\",\"type\":\"" + edges[i].getType() + "\"},";
		else 
			jsonString += "{\"nodeId1\":\"" + edges[i].getNodeId1() + "\",\"nodeId2\":\"" + edges[i].getNodeId2() + "\",\"type\":\"" + edges[i].getType() + "\"}";
	}
	
	jsonString += "]}";
	
	this.http.send("json=" + jsonString);	
}

///////////
// LISTENER
///////////

MarimbaPlugin.prototype.nodePropertyChangedPerformed=function(nodeData){
	if ( nodeData.isActive() ) {
		// RESET input fields for distribution
		for ( var i = 0; i < this.dist.length; i++ ) {
			var params = this.paramInput[0][this.dist[i].dist];
			//alert(params.childNodes.length);
			for ( var j = 1; j < params.childNodes.length; j+=2 ) {
	    		params.childNodes[j].value = "---";
			}
		}
		
		this.currentNode = nodeData;
		var parents = this.graphView.currentGraph.getParents(nodeData);
		
		// IF node has PARENTS
		if ( parents != null && parents.length > 0 && nodeData.getData().length > 0 ) { 
			// CHECK if parents have states
			var temp = true;
			for ( var i = 0; i < parents.length; i++ ) if ( parents[i].getData().length < 1 ) temp = false;
			
			if ( temp ) {
				this.currentParents = parents;
				
				// CREATE data structure if nessecary
				if ( this.marimbaNodeHash[0][nodeData.getId()] == null || this.marimbaNodeHash[0][nodeData.getId()] == undefined ) this.marimbaNodeHash[0][nodeData.getId()] = new MarimbaNode(nodeData);
				var array = this.marimbaNodeHash[0][nodeData.getId()].getTable();
				var inputs = this.paramInput[0][this.marimbaNodeHash[0][nodeData.getId()].getDistribution()];
				
				if ( array == null ) {
					this.marimbaNodeHash[0][nodeData.getId()].setTable(this.resetTableData(nodeData, parents));
					this.marimbaNodeHash[0][nodeData.getId()].setDistribution("uniform");
					this.distSelector.selectedIndex = 0;
					this.setInputFields("uniform");
				} else {
					
					// SET distribution values from marimba node to view
					this.distSelector.selectedIndex = this.distHash[0][this.marimbaNodeHash[0][nodeData.getId()].getDistribution()];
					
					for ( var i = 0; i < inputs.length; i++ ) {
						for ( var k = 0; k < this.marimbaNodeHash[0][nodeData.getId()].getDistParams().length; k++ ) {
							if ( inputs[i].childNodes[0] == this.marimbaNodeHash[0][nodeData.getId()].getDistParams()[k].name ) {
								inputs[i].childNodes[1].value = this.marimbaNodeHash[0][nodeData.getId()].getDistParams()[k].value;
							}
						}
					}
					this.setInputFields(this.marimbaNodeHash[0][nodeData.getId()].getDistribution());
					
					// SET new data to data structure
					if ( parents.length != array[0].length) {
						this.marimbaNodeHash[0][nodeData.getId()].setTable(this.resetTableData(nodeData, parents));
						var inputs = this.paramInput[0][this.marimbaNodeHash[0][nodeData.getId()].getDistribution()];
					} else {
						var temp = true;
						var oldParents = array[0];
						for ( var i = 0; i < parents.length; i++ ) {
							var temp2 = false;
							for ( var j = 0; j < oldParents.length; j++ ) 
								if ( parents[i].getId() == oldParents[j].getId() ) temp2 = true;
							temp = temp2 && temp;
						}
						if ( !temp ) this.resetTableData(nodeData, parents);
					}
				}
				
				// CREATE table
				this.closeTable();
				this.createColumnSet(nodeData, parents);
				this.createRows(nodeData, this.createRowsArray(new Array(), new Array(), parents, 0));
				for ( var i = 0; i < parents.length; i++ ) parents[i].highlight();
				
			}
			
		// IF node has NO PARENTS
		} else {			
			if ( this.marimbaNodeHash[0][nodeData.getId()] == null || this.marimbaNodeHash[0][nodeData.getId()] == undefined ) this.marimbaNodeHash[0][nodeData.getId()] = new MarimbaNode(nodeData);
			var array = this.marimbaNodeHash[0][nodeData.getId()].getTable();
			var inputs = this.paramInput[0][this.marimbaNodeHash[0][nodeData.getId()].getDistribution()];
			
			if ( array == null ) {
				if ( this.marimbaNodeHash[0][nodeData.getId()] == null || this.marimbaNodeHash[0][nodeData.getId()] == undefined )	
						this.marimbaNodeHash[0][nodeData.getId()] = new MarimbaNode(nodeData);
				this.marimbaNodeHash[0][nodeData.getId()].setTable(this.resetTableData(nodeData, parents));
				this.marimbaNodeHash[0][nodeData.getId()].setDistribution("uniform");
			} else {
				this.distSelector.selectedIndex = this.distHash[0][this.marimbaNodeHash[0][nodeData.getId()].getDistribution()];
					
				for ( var i = 0; i < inputs.length; i++ ) {
					for ( var k = 0; k < this.marimbaNodeHash[0][nodeData.getId()].getDistParams().length; k++ ) {
						if ( inputs[i].childNodes[0] == this.marimbaNodeHash[0][nodeData.getId()].getDistParams()[k].name ) 
							inputs[i].childNodes[1].value = this.marimbaNodeHash[0][nodeData.getId()].getDistParams()[k].value;
					}
				}
				this.setInputFields(this.marimbaNodeHash[0][nodeData.getId()].getDistribution());
			}
		}
	} else {
		this.closeTable();
		this.currentNode = null;
	}
	
}


MarimbaPlugin.prototype.delNodeEventPerformed=function(nodeData)
{
	if ( this.currentNode != null ) {
		var array = this.tableHash[0][this.currentNode.getId()];
		if ( nodeData.getId() == this.currentNode.getId() ) {
			this.closeTable();
			this.tableHash[0][this.currentNode.getId()] = null;
		} else {
			alert(this.graphView.currentGraph.getParents(this.currentNode).length + " " + this.currentNode.isActive() );
			this.closeTable();
			this.nodePropertyChangedPerformed(this.currentNode);
		}
	}
}

MarimbaPlugin.prototype.newEdgeSetPerformed=function(newEdgeSet){}
MarimbaPlugin.prototype.addNodeEventPerformed=function(nodeData){
	this.marimbaNodeHash[0][nodeData.getId()] = new MarimbaNode(nodeData);
}
MarimbaPlugin.prototype.addEdgeEventPerformed=function(edgeData){}
MarimbaPlugin.prototype.delEdgeEventPerformed=function(edgeData){}
MarimbaPlugin.prototype.replaceEdgeEventPerformed=function(oldEdgeData, newEdgeData){}
MarimbaPlugin.prototype.currentEdgeSetChangedPerformed=function(currentEdgeSet){}
MarimbaPlugin.prototype.edgePropertyChangedPerformed=function(edgeData){}

function MarimbaNode(nodeData){
	this.nodeData = nodeData;
	this.table = null;
	this.id = nodeData.getId();
	this.label = nodeData.getLabel();
	this.dist = "uniform";
	this.distParams = new Array();
}

MarimbaNode.prototype = new Object();

MarimbaNode.prototype.setTable=function(table)
{
	this.table = table;
}

MarimbaNode.prototype.getTable=function()
{
	return this.table;
}

MarimbaNode.prototype.setDistribution=function(dist)
{
	this.dist = dist;
}

MarimbaNode.prototype.getDistribution=function()
{
	return this.dist;
}

MarimbaNode.prototype.setDistParam=function(name, value)
{
	temp = true
	for ( var i = 0; i < this.distParams.length; i++ )
		if ( this.distParams[i].name == name ) temp = false;
	if ( temp ) this.distParams.push({'name':name,'value':value});
	else this.replaceParam(name, value);
}

MarimbaNode.prototype.getDistParams=function()
{
	return this.distParams;
}

MarimbaNode.prototype.getLabel=function()
{
	return this.label;
}

MarimbaNode.prototype.getId=function()
{
	return this.id;
}

MarimbaNode.prototype.replaceParam=function(name, value)
{
	for ( var i = 0; i < this.distParams.length; i++ )
		if ( this.distParams[i].name == name ) this.distParams[i].value = value;
}

MarimbaNode.prototype.asJsonObject=function(parents, children, newLine)
{
	result = new String();
	result += "{" + "\"id\":\"" + this.nodeData.getId() + "\",\"label\":\"" + this.nodeData.getLabel() + "\",";
	result += "\"distribution\":\"" + this.dist + "\",\"distParams\":[";
	for ( var i = 0; i < this.distParams.length; i++ ) {
		if ( i != this.distParams.length ) 
			result += "{\"" + this.distParams[i].name + "\":\"" + this.distParams[i].value + "\"},";
		else 
			result += "{\"" + this.distParams[i].name + "\":\"" + this.distParams[i].value + "\"}";
	}
	result += "],";
	result += "\"table\":\"" + this.getNodeTableString(this.nodeData, parents, children, newLine) + "\"}";
	
	return result;
}

MarimbaNode.prototype.getNodeTableString = function(node, parents, children, newLine)
{
	var resultString = "";
	var rowsData = this.createRowsArray(new Array(), new Array(), parents, 0);
	var values = this.getTable();
	
	if ( rowsData != null ) {
		for ( var i = 0; i < rowsData.length; i++ ) {
			for ( var j = 0; j < rowsData[i].length; j++ ) {
				if ( j != rowsData[i].length - 1 ) resultString += (rowsData[i][j] + ",");
				else resultString += (rowsData[i][j] + ";");
			}
			for ( var j = 0; j < values[i + 1].length; j++ ) {
				if ( j != values[i + 1].length - 1 ) resultString += (values[i + 1][j] + ",");
				else resultString += (values[i + 1][j] + newLine + newLine);
			}
		}
	}

	return resultString;
}

MarimbaNode.prototype.createRowsArray=function(array, row, parents, index)
{
	if ( parents != null && parents.length > 0 ) {
		if ( index < parents.length - 1 ) {
			for ( var i = 0; i < parents[index].getData().length; i++ ) {
				row[index] = parents[index].getData()[i];
				array = this.createRowsArray(array, row, parents, index + 1);
				var temp = new Array();
				for ( var j = 0; j < index; j++ ) temp[j] = row[j];
				row = temp;
			}
			return array;
		} else {
			for ( var i = 0; i < parents[index].getData().length; i++ ) {
				row[index] = parents[index].getData()[i];
				array.push(row);
				var temp = new Array();
				for ( var j = 0; j < index; j++ ) temp[j] = row[j];
				row = temp;
			}
			return array;
		}
	}
}