/**
  Auteur : Eric Jeunieaux
  Voir http://xulfr.org/wiki/RessourcesLibs/TreeViewComplet
 */


  var gView;
 
  function nsTreeView(){
  }
 
  nsTreeView.prototype = {
 
  /****************************** View general methods *******************************/
  	selection : null,
  	rowCount  : null,
  	treebox   : null,
  	widget    : null,
 
  	getRowCount : function(){
  		return this.abslList.length;
  	},
 
  	getRowProperties : function getRowProperties(index, prop){
  //		dump( "ENTER FUNCTION ----> " + this.toString() + ".getRowProperties(aRowIndx, aClmnId)\n" );
  //		dump( "EXIT FUNCTION  <---- " + this.toString() + ".getRowProperties(aRowIndx, aClmnId)\n" );
  	},
 
  	getCellProperties : function getCellProperties(index, column, prop){
  //		dump( "ENTER FUNCTION ----> " + this.toString() + ".getCellProperties(aRowIndx, aClmnId, aPrprList)\n" );
  //		dump( "EXIT FUNCTION  <---- " + this.toString() + ".getCellProperties(aRowIndx, aClmnId, aPrprList)\n" );
  	},
 
  	getColumnProperties : function getColumnProperties(column, elem, prop){
  //		dump( "ENTER FUNCTION ----> " + this.toString() + ".getColumnProperties(aClmnId, aPrprList)\n" );
  //		dump( "EXIT FUNCTION  <---- " + this.toString() + ".getColumnProperties(aClmnId, aPrprList)\n" );
  	},
 
  	isContainer : function isContainer(index){
  //		dump( "ENTER FUNCTION ----> " + this.toString() + ".isContainer(aRowIndx)\n" );
  		var bool;
  		var item = this.getItemAtIndex(index);
  		if(item !== null){
  			bool = item.isCntn;
  		}else{
  			throw 0x80004003; // Components.results.NS_ERROR_NULL_POINTER;
  		}
  //		dump( "EXIT FUNCTION  <---- " + this.toString() + ".isContainer(aRowIndx)\n" );
    		return bool;
  	},
 
  	isContainerOpen : function isContainerOpen(index){
  //		dump( "ENTER FUNCTION ----> " + this.toString() + ".isContainerOpen(aRowIndx)\n" );
    		var bool;
  		var item = this.getItemAtIndex(index);
  		if(item !== null){
  			bool = item.isOpen;
  		}else{
  			throw 0x80004003; // Components.results.NS_ERROR_NULL_POINTER;
  		}
  //		dump( "EXIT FUNCTION  <---- " + this.toString() + ".isContainerOpen(aRowIndx)\n" );
    		return bool;
  	},

  	isContainerEmpty: function isContainerEmpty(index){
  //		dump( "ENTER FUNCTION ----> " + this.toString() + ".isContainerEmpty(aRowIndx)\n" );
  		var bool;
  		var item = this.getItemAtIndex(index);
  		if(item !== null){
  			if(item.chld.length > 0){
  				bool = false;
  			}else{
  				bool = true;
  			}
  		}else{
  			throw 0x80004003; // Components.results.NS_ERROR_NULL_POINTER;
  		}
  //		dump( "EXIT FUNCTION  <---- " + this.toString() + ".isContainerEmpty(aRowIndx)\n" );
    		return bool;
  	},

  	isSeparator : function isSeparator(index){
  //		dump( "ENTER FUNCTION ----> " + this.toString() + ".isSeparator(aRowIndx)\n" );
  //		dump( "EXIT FUNCTION  <---- " + this.toString() + ".isSeparator(aRowIndx)\n" );
  		return false;
  	},

  	isSorted : function isSorted(){
  		return false;
  	},
  /*
  	// did not implemented yet!
  	canDropOn : function canDropOn(index){
  		dump( "ENTER FUNCTION ----> " + this.toString() + ".canDrop(aIndx, aOrnt)\n" );
  		dump( "EXIT FUNCTION  <---- " + this.toString() + ".canDrop(aIndx, aOrnt)\n" );
  		return false;
  	},

  	canDropBeforeAfter : function canDropBeforeAfter(index, before){
  		return false;
  	},
   */
  	drop : function drop(index, orientation){
  //		dump( "ENTER FUNCTION ----> " + this.toString() + ".drop(index, orientation)\n" );
  //		dump( "EXIT FUNCTION  <---- " + this.toString() + ".drop(index, orientation)\n" );
  	},

  	getParentIndex: function getParentIndex(index){
  //		dump( "ENTER FUNCTION ----> " + this.toString() + ".getParentIndex(index)\n" );
  		var prnt = null;
  		var item = this.getItemAtIndex(index);
  		if(item !== null){
  			var prntItem = this.abslList[item.parent];
  			if(prntItem !== null){
  				prnt = item.parent - item.offSet;
  			}else{
  				throw 0x80004003; // Components.results.NS_ERROR_NULL_POINTER;
  			}
  		}else{
  			throw 0x80004003; // Components.results.NS_ERROR_NULL_POINTER;
  		}
  //		dump( "getParentIndex(" + index + ") == " + prnt + "\n" );
  //		dump( "EXIT FUNCTION  <---- " + this.toString() + ".getParentIndex(index)\n" );
  		return prnt;
  	},

  	//HasNextSibling is used to determine if the row at rowIndex has a nextSibling
  	//that occurs *after* the index specified by afterIndex.
  	hasNextSibling: function hasNextSibling(index, after){
  //		dump( "ENTER FUNCTION ----> " + this.toString() + ".hasNextSibling(index, after)\n" );
  		var bool = false;

  		var item = this.getItemAtIndex(index);
  		if(item !== null){
  			if(item.parent !== null){
  				var afterItem = this.getItemAtIndex(after);
  				var prntItem  = this.abslList[item.parent];
  				if(afterItem !== null && prntItem !== null){
  					var lastSibling = prntItem.chld[prntItem.chld.length - 1];
  					if(lastSibling.index > afterItem.index){
  						bool = true;
  					}
  				}
  			}
  		}else{
  			throw 0x80004003; // Components.results.NS_ERROR_NULL_POINTER;
  		}
  		//dump( "hasNextSibling(" + index + "," + after + ")\t== " + bool + "\n" );
  //		dump( "EXIT FUNCTION  <---- " + this.toString() + ".hasNextSibling(index, after)\n" );
  		return bool;
  	},

  	getLevel: function getLevel(index) {
  //		dump( "ENTER FUNCTION ----> " + this.toString() + ".getLevel(index)\n" );
  		var lvl;
  		var item = this.getItemAtIndex(index);
  		if(item !== null){
  			lvl = item.level;
  		}else{
  			throw 0x80004003; // Components.results.NS_ERROR_NULL_POINTER;
  		}
  //		dump( "EXIT FUNCTION <---- " + this.toString() + ".getLevel(index)\n" );
  		return lvl;
  	},

  	getImageSrc: function getImageSrc(index, column){
  //		dump( "ENTER FUNCTION ----> " + this.toString() + ".getImageSrc(aRowIndx, aClmnId)\n" );
  //		dump( "EXIT FUNCTION  <---- " + this.toString() + ".getImageSrc(aRowIndx, aClmnId)\n" );
  	},

  	getProgressMode : function getProgressMode(index,column){
  //		dump( "ENTER FUNCTION ----> " + this.toString() + ".getProgressMode(aRowIndx, aClmnId)\n" );
  //		dump( "EXIT FUNCTION  <---- " + this.toString() + ".getProgressMode(aRowIndx, aClmnId)\n" );
  	},

  	getCellValue: function getCellValue(index, column){
  //		dump( "ENTER FUNCTION ----> " + this.toString() + ".getCellValue(aRowIndx, aClmnId)\n" );
  //		dump( "EXIT FUNCTION  <---- " + this.toString() + ".getCellValue(aRowIndx, aClmnId)\n" );
  	},

  	getCellText: function getCellText(index, column){
  //		dump( "ENTER FUNCTION ----> " + this.toString() + ".getCellText(aRowIndx, aClmnId)\n" );
  		var val = null;
  		if(column == "col_0"){
  			var item = this.getItemAtIndex(index);
  			if(item !== null){
  				val = item.uri;
  			}
  		}
  //		dump( "EXIT FUNCTION  <---- " + this.toString() + ".getCellText(aRowIndx, aClmnId)\n" );
  		return val;
  	},

  	setTree: function setTree(treeBox){
  //	  	dump( "ENTER FUNCTION ----> " + this.toString() + ".setCellValue(aTree)\n" );
  	  	this.treeBox = treeBox;
  	  	if (!treeBox){
  	  		this.selection = null;
  	  	}
  //	  	dump( "EXIT FUNCTION  <---- " + this.toString() + ".setCellValue(aTree)\n" );
  	},

  	cycleHeader : function cycleHeader(col, elem){
  //		dump( "ENTER FUNCTION ----> " + this.toString() + ".cycleHeader(aClmnId)\n" );
  //		dump( "EXIT FUNCTION  <---- " + this.toString() + ".cycleHeader(aClmnId)\n" );
  	},

  	selectionChanged : function selectionChanged(){
  //		dump( "ENTER FUNCTION ----> " + this.toString() + ".selectionChanged()\n" );
  //		dump( "EXIT FUNCTION  <---- " + this.toString() + ".selectionChanged()\n" );
  	},

  	cycleCell: function cycleCell(index, column){
  //		dump( "ENTER FUNCTION ----> " + this.toString() + ".cycleCell(aRowIndx, aClmnId)\n" );
  //		dump( "EXIT FUNCTION  <---- " + this.toString() + ".cycleCell(aRowIndx, aClmnId)\n" );
  	},

  	isEditable: function isEditable(index, column){
  //		dump( "ENTER FUNCTION ----> " + this.toString() + ".isEditable(aRowIndx, aClmnId)\n" );
  //		dump( "EXIT FUNCTION  <---- " + this.toString() + ".isEditable(aRowIndx, aClmnId)\n" );
    		return false;
    	},

  	performAction: function performAction(action){
  //		dump( "ENTER FUNCTION ----> " + this.toString() + ".performAction(aActn)\n" );
  //		dump( "EXIT FUNCTION  <---- " + this.toString() + ".performAction(aActn)\n" );
  	},

  	performActionOnCell: function performActionOnCell(action, index, column){
  //		dump( "ENTER FUNCTION ----> " + this.toString() + ".performActionOnCell(aActn, aRowIndx, aClmnId)\n" );
  //		dump( "EXIT FUNCTION  <---- " + this.toString() + ".performActionOnCell(aActn, aRowIndx, aClmnId)\n" );
  	},

  	toggleOpenState: function toggleOpenState(index){
  //		dump( "ENTER FUNCTION ----> " + this.toString() + ".toggleOpenState(index)\n" );
  		var item = this.getItemAtIndex(index);
  		if(item !== null){
  			if(item.isOpen === true){
  				this.collapse(index, item);
  			}else{
  				this.expand(index, item);
  			}
  			item.isOpen = !item.isOpen;
  		}else{
  			throw 0x80004003; // Components.results.NS_ERROR_NULL_POINTER;
  		}
  //		dump( "EXIT FUNCTION  <---- " + this.toString() + ".toggleOpenState(index)\n" );
  	},

  	toString : function(){
  		return "[TEST View]";
  	},

  /****************************** View specific methods *******************************/
  	abslList : null,

  	intl : function(aAbslList){
  		this.abslList = aAbslList;
  		this.rowCount = aAbslList.length;
  	},

  	getItemAtIndex : function(aIndex){
  //		dump( "ENTER FUNCTION ----> " + this.toString() + ".getItemAtIndex(aIndex)\n" );
  		var item = null;

  		if(aIndex < this.abslList.length){
  			var indx;
  			var offSet = 0;

  			item = this.abslList[aIndex];
  			while((item.offSet - offSet) !== 0){
  				offSet = item.offSet;
  				indx   = aIndex + item.offSet;
  				item   = this.abslList[indx];
  			}
  		}
  //		dump( "EXIT FUNCTION  <---- " + this.toString() + ".getItemAtIndex(aIndex)\n" );
  		return item;
  	},

  	countCollapsedRows : function(aItem){
  //		dump( "ENTER FUNCTION ----> " + this.toString() + ".countCollapsedRows(aItem)\n" );

  		var chldNmbr = 0;
  		if(aItem.isCntn === true && aItem.isOpen === true){
  			for(var i = 0; i < aItem.chld.length; ++i){
  				++chldNmbr;
  				chldNmbr += this.countCollapsedRows(aItem.chld[i]);
  			}
  		}
  //		dump( "EXIT FUNCTION  <---- " + this.toString() + ".countCollapsedRows(aItem)\n" );
  		return chldNmbr;
  	},

  	collapse : function(aIndex, aItem){
  //		dump( "ENTER FUNCTION ----> " + this.toString() + ".collapse(aIndex, aItem)\n" );
  			var indx;

  			var offSet = this.countCollapsedRows(aItem);
  			if(offSet > 0){
  				indx = aIndex + aItem.offSet + 1;
  				for(var i = indx; i < this.abslList.length; ++i){
  					this.abslList[i].offSet += offSet;
  				}

  				this.treeBox.rowCountChanged(aIndex, -offSet);
  				//this.rowCount -= offSet;

  			}

  //		dump( "EXIT FUNCTION  <---- " + this.toString() + ".collapse(aIndex, aItem)\n" );
  	},

  	countExpandedRows : function(aItem){
  //		dump( "ENTER FUNCTION ----> " + this.toString() + ".countExpandedRows(aItem)\n" );

  		var chldNmbr = 0;
  		for(var i = 0; i < aItem.chld.length; ++i){
  			++chldNmbr;
  			if(aItem.chld[i].isCntn === true && aItem.chld[i].isOpen === true){
  				chldNmbr += this.countExpandedRows(aItem.chld[i]);
  			}
  		}
  //		dump( "EXIT FUNCTION  <---- " + this.toString() + ".countExpandedRows(aItem)\n" );
  		return chldNmbr;
  	},


  	expand : function(aIndex, aItem){
  //		dump( "ENTER FUNCTION ----> " + this.toString() + ".expand(aIndex, aItem)\n" );
  			var indx;

  			var offSet = this.countExpandedRows(aItem);
  			if(offSet > 0){
  				indx = aIndex + aItem.offSet + 1;
  				for(var i = indx; i < this.abslList.length; ++i){
  					this.abslList[i].offSet -= offSet;
  				}

  				this.treeBox.rowCountChanged(aIndex, offSet);
  				//this.rowCount -= offSet;
  			}

  //		dump( "EXIT FUNCTION  <---- " + this.toString() + ".expand(aIndex, aItem)\n" );
  	},

  	addItemAfter : function(aIndx){
  //		dump( "ENTER FUNCTION ----> " + this.toString() + ".addItem(aIndx)\n" );

  //		dump( "EXIT FUNCTION  <---- " + this.toString() + ".addItem(aIndx)\n" );
  	},

  	removeItem : function(){
  //		dump( "ENTER FUNCTION ----> " + this.toString() + ".removeItem()\n" );

  //		dump( "EXIT FUNCTION  <---- " + this.toString() + ".removeItem()\n" );
  	},

  	dumpAbslList : function(){
  //		dump( "ENTER FUNCTION ----> " + this.toString() + ".dumpAbslList()\n" );

  	    dump("\n\n");

  	    for(var i = 0; i < this.abslList.length; ++i){
  			dump( i                                  + "\t" +
  			      "uri    = " + this.abslList[i].uri    + "\t" +
  			      "offset = " + this.abslList[i].offSet + "\t" +
  			      "isOpen = " + this.abslList[i].isOpen + "\t" +
  			      "parent = " + this.abslList[i].parent + "\n");
  		}

  	    dump("\n\n");

  //		dump( "EXIT FUNCTION  <---- " + this.toString() + ".dumpAbslList()\n" );
  	}

  };


  function dumpAbslList(){
  //		dump( "ENTER FUNCTION ----> " + this.toString() + ".dumpAbslList()\n" );
  		gView.dumpAbslList();
  //		dump( "EXIT FUNCTION  <---- " + this.toString() + ".dumpAbslList()\n" );
  }


  function intl() {
  	dump( "ENTER FUNCTION ----> intl()\n" );

  	var k = 0;
  	var rltvList = new Array();
  	var abslList = new Array();

  	var prntLvl_1 = 0;
  	var prntLvl_2;

  	for(var i = 0; i < 3; ++i){
  		rltvList[i] = {
  			uri    : ("item " + i ),
  			index  : k,
  			chld   : new Array(),
  			isOpen : true,
  			isCntn : true,
  			level  : 0,
  			parent : null,
  			offSet : 0
  		}

  		abslList[k] = rltvList[i];
  		prntLvl_1 = k;
  		++k;

  		for(var j = 0; j < 3; ++j){
  			rltvList[i].chld[j] = {
  				uri    : ("item " + i + "." + j),
  				index  : k,
  				chld   : new Array(),
  				isOpen : true,
  				isCntn : true,
  				level  : 1,
  				parent : prntLvl_1,
  				offSet : 0
  			}

  			abslList[k] = rltvList[i].chld[j];
  		    prntLvl_2 = k;
  			++k;

  			for(var h = 0; h < 3; ++h){
  				rltvList[[i].chld[[j].chld[[h] = {
  					uri    : ("item " + i + "." + j + "." + h),
  					index  : k,
  					chld   : new Array(),
  					isOpen : false,
  					isCntn : false,
  					level  : 2,
  					parent : prntLvl_2,
  					offSet : 0
  				}

  				abslList[[k] = rltvList[[i].chld[[j].chld[[h];
  				++k;
  			}
  		}

  	}

  	gView = new nsTreeView();
  	gView.intl(abslList);

  	var tree = document.getElementById("treeTest");
  	tree.view = gView;

  	dump( "EXIT FUNCTION  <---- intl()\n" );
  }


