/**
 * Class for rendering a tree
 */
function tree(id, treeservlet)
{
  /* The tree id */
  this.id = id;
  
  /* Servlet for this tree */
  this.servlet = "";
  this.renderer = "";
  this.target = "";
  this.page = "";
  this.params = "guid,descr,href,checked,target,color";
  this.template = "<a href=\"$href$\" target=\"$target$\" $dnd$ ondblclick=\"toggleNode('$id$', '$tree$');\" class=\"$cssclass$\" title=\"$alttext$\" nowrap=\"nowrap\" style=\"$color$\">$descr$</a>";
  this.childindent = "16px";
  this.nodeattributes = "";
  this.styles = new Array();
  this.nodes = new Array();

  var _node = new treenode();
  _node.id = id;
  _node.level = -1;
  _node.parentid = "";
  
  this.nodes[id] = _node;
  
  /**
   * get renderer
   */
  this.getrenderer = function()
  {
    return getObject(this.renderer, 0);
  }
  
  this.numNodes = function()
  {
    _i = 0;
  
    for (_id in this.nodes)
      _i++;
      
    return _i;
  }
   
  /**
   *  Add subtree to given parent
   */
  this.addsubtree = function (nodeid, root)
  {
    var _cb = function(_this, xmldata)
    {
      var _openlater = new Array();
    
      /* Remove loading ... */
      var _loading = document.getElementById("loading");
      if (_loading)
      { 
        _loading.parentNode.removeChild(_loading);
      }
      
      var _lockmgr = getObject("lockmgr");
      var _lockid = "tree_" + _this.id + "_node_" + nodeid;
    
      _lockmgr.unlock(_lockid);
      
      _rootElement = xmldata.documentElement;
    
      var _containernode = _this.id + "_" + nodeid;
      var _containerchilds = _containernode + "_childs";
  
      var _container = document.getElementById(_containernode);
      
      if (!_this.nodes[nodeid])
      {
        var _nodeElement = new treenode();
        _nodeElement.create(_this.id, _this.id, _rootElement, _this.nodes.length);

        document.getElementById(_containernode).innerHTML = _this.getrenderer().paint(_nodeElement, _this.styles, _this.template);
      }
  
      if (!_rootElement.firstChild) return;
      
      var _idx = 0;
      var _child = _rootElement.firstChild;
      do
      {
        var _nodeElement = new treenode();
        _nodeElement.create(_this.id, nodeid, _child, _idx);
        
        var _node = _this.getrenderer().createcontainer(_nodeElement, 1, _this.childindent);
        _node.innerHTML = _this.getrenderer().paint(_nodeElement, _this.styles, _this.template);
        
        if (_nodeElement.selected)
        {
          // Prototype of scrolling to right category ...
          window.scrollTo(0, _this.numNodes() * 16 - screen_height() + 32);
        }
        
        _container.appendChild(_node);
        
        if (_nodeElement.open=="true")
          _openlater[_openlater.length] = _nodeElement.guid;
        
        _child = _child.nextSibling;
        _idx++;
      }
      while (_child!=null);
      
      var _toggle = false;
      if (root && _this.nodes[nodeid].open != "true")
        _toggle = true;
        
      _this.getrenderer().repaint(_this.nodes[nodeid], _this.styles, _toggle);
      
      for (i=0; i<_openlater.length; i++)
      {
        togglenode(_this.id, _openlater[i], false);
      }
    }
    
    _container = document.getElementById(this.id + "_" + nodeid);
    
    if (_container)
    {
      var _loading = document.createElement("div");
      
      _loading.style.margin = "-1px";
      _loading.style.padding = "0px";
      // _loading.style.backgroundColor = "#EEEEEE";
      _loading.style.border = "1px outset #CCCCCC";
      _loading.style.color = "#000000";
      
      if (this.nodes[nodeid]
          && this.nodes[nodeid].childcount
          && this.nodes[nodeid].childcount > 0)
        _loading.style.height = (this.nodes[nodeid].childcount*16) + "px";
      
      _loading.id = "loading";
      _loading.innerHTML = "<center>Loading ...</center>";
      
      _container.appendChild(_loading);
    }
    
    if (this.servlet.match(/\?/)) _c = "&"; else _c = "?";
    
    var _url = this.servlet + _c + "root=" + nodeid + "&params=" + this.params + "&action=open&target=" + this.target + "&page=" + this.page;
    if (root)
       _url += "&setstatus=false";
    
    var _lockmgr = getObject("lockmgr");
    var _lockid = "tree_" + this.id + "_node_" + nodeid;
       
    if (!_lockmgr.islocked(_lockid))
    {
      _lockmgr.lock(_lockid);
      sendrequest(_url, _cb, this);
    }
  }
  
  /**
   * Check if the current tree available
   */
  this.isrendered = function(nodeid, withchildren)
  {
    return this.getrenderer().isrendered(this.nodes[nodeid], withchildren);
  }
  
  /**
   * Toggle state of a rendered node
   */
  this.togglestate = function (nodeid)
  {
    var _rc = this.getrenderer().repaint(this.nodes[nodeid], this.styles, true);
    this.setopened(nodeid, _rc);
  }
  
  
  /**
   * Send the state of a tree node to server
   */
  this.setopened = function (nodeid, opened)
  {
    if (this.servlet.match(/\?/)) _c = "&"; else _c = "?";
    var _url = this.servlet + _c + "root=" + nodeid + "&action=";
  
    if (opened)
    {
      _url += "open";
      
      if (!navigator.userAgent.match(/MSIE/))
        sendrequesta(_url);
    }
    else
    {
      _url += "close";
      sendrequesta(_url);
    }
  }
}

function treenode()
{
  this.create = function (treeid, parentid, xmldata, index)
  {
    this.tree = treeid;
    this.parentid = parentid;
    var _tree = getObject("tree", treeid);
    
    /* Fill object with default attributes */
    _tmp = getObject('tree', treeid).nodeattributes.split(" ");
    for (i=0; i<_tmp.length; i++)
    {
      _tmppair = _tmp[i].split("=");
      this[_tmppair[0]] = _tmppair[1];
    }
    
    /* Make attributes an array, if it is a string */
    if (typeof xmldata == "string")
    {
      _tmp = Attributes.split(" ");
      xmldata = new Array();

      for (i=0; i<_tmp.length; i++)
      {
        _tmppair = _tmp[i].split("=");
        xmldata[_tmppair[0]] = _tmppair[1];
      }
    }

    /* Make attributes an array, if it is an xml element */
    if (typeof xmldata == "object" && xmldata.attributes)
    {
      var _tmp = new Array();

      for (i=0; i<xmldata.attributes.length; i++)
      {
        _tmp[xmldata.attributes[i].nodeName] = xmldata.attributes[i].nodeValue;
      }

      xmldata = _tmp;
    }

    /* Merge attributes to element */
    for (key in xmldata) 
    {
      this[key] = xmldata[key].replace(/\n/, "");
    }
    
    if (this.guid)
      this.id = this.guid;


    if (treeid==parentid && !_tree.servlet.match(/jsessionid/))
      this.open="true";
    if (parentid=="" || !_tree.nodes[parentid])
    {
      this.level = 0;
      this.last = true;
    }
    else
    {
      parente = _tree.nodes[parentid];
      
      this.level = parente.level + 1;
      if (index>=parente.childcount-1) this.last = true; else this.last = false;
    }
 
    this.cid = this.tree + "_" + this.id;
  
    _tree.nodes[this.id] = this;
  }
  
  this.render = function(template)
  {
    var _keyregex = /\$([\w\_]+)\$/;
    var terminator = 256;
    
    while (_keyregex.test(template) && terminator>0)
    {
      _result = _keyregex.exec(template);

      _replace = "\\$" + _result[1] + "\\$";
      _replacereg = new RegExp(_replace, "g");

      if (this[_result[1]])
        _value = this[_result[1]];
      else
        _value = "";
        
//      if (_result[1]=='descr'
//          && _value && _value!=null && ! _value.charAt(0) == '<')
      
      if (_result[1]=='descr' 
          && _value && _value!=null)
      {
         var _found=_value.indexOf(' ');
         while (_found>=0)
         {
            _value=_value.substr(0,_found)+'&nbsp;'+_value.substring(_found+1)  
            _found=_value.indexOf(' ',_found+6);
         }
      }
      
      if (_result[1]=='alttext' && (_value==null || _value==''))
        _value=this['descr'];
      template = template.replace(_replacereg, _value);

      terminator--;
    }
    
    return template;
  }
}

/* togglenode is the easiest way to access the tree ... */
function togglenode(treeid, nodeid, root)
{
  var _containernode = treeid + "_" + nodeid;
  var _containerchilds = _containernode + "_childs";
  
  var _tree = getObject("tree", treeid);
  
  _container = document.getElementById(treeid + "_" + nodeid);
  if (!_container)
  {
    _nodeElement = new treenode();
    _nodeElement.id = nodeid;
    _nodeElement.tree = treeid;
    _nodeElement.level = 0;
    _nodeElement.parentid = treeid;
        
    _container = _tree.getrenderer().createcontainer(_nodeElement, 0, 0);
    _container.innerHTML = "";
        
    document.getElementById(treeid).appendChild(_container);
  }

  if (_tree.isrendered(nodeid, true))
    _tree.togglestate(nodeid);
  else
    _tree.addsubtree(nodeid, root, true);
}



/* togglenode is the easiest way to access the tree ... */
function togglenode2(treeid, nodeid, root, open)
{
  togglenode(treeid, nodeid, root);
  
  var _tree = getObject("tree", treeid);

  if (open == true)
    _tree.togglestate(nodeid);
}

