var treeScroller = {};
var frameMgr = {};

function FloatingFrameManager() {
  this.frameHolder  = $("floatingFrameHolder");
  this.frameInner   = this.frameHolder.getElementsByTagName("div")[0];
  this.currentFrame = this.frameInner.getElementsByTagName("div")[0];
  this.currentTitle = this.frameHolder.getElementsByTagName("h3")[0].innerHTML;
  this.frameStack   = [];
  this.animinfo     = [];
  this.timerID      = false;
    
  this.showFrame = function(title, frame) {
    if (this.currentFrame) {
      this.frameStack.push( { title : this.currentTitle, frame : this.currentFrame } );
      //this.fadeElement(this.currentFrame, -5);
      //this.currentFrame.style.display = "none";
    }
    this.currentFrame = frame;
    this.frameInner.appendChild(this.currentFrame);
    this.fadeElement(this.currentFrame, 5);
    this.frameHolder.getElementsByTagName("h3")[0].innerHTML = title;
  }
  
  this.hideFrame = function(frame) {
    if (frame == this.currentFrame) {
      //this.frameInner.removeChild(this.currentFrame);
      this.fadeElement(this.currentFrame, -5);
      
      if (this.frameStack.length > 0) {
        var lastinfo = this.frameStack.pop();
        this.frameHolder.getElementsByTagName("h3")[0].innerHTML = lastinfo.title;
        this.currentFrame = lastinfo.frame;
        this.currentFrame.style.zOrder = this.animinfo.length+2;
        
        //this.currentFrame.style.display = "";
        //this.fadeElement(this.currentFrame, 5);
      }
      else {
        this.currentFrame = false;
      }
    }
  }
  
  this.fadeElement = function(el, delta) {
    var j=0;
    for (var i=0; i<this.animinfo.length; i++) {
      if (this.animinfo[i] && this.animinfo[i].el && this.animinfo[i].el==el) {
        this.animinfo[i].delta = delta;
        this.animinfo[i].el.style.zOrder = this.animinfo.length;
        return;
      }
      if (!this.animinfo[i]) { j = i; }
    }
    if (!j) { j = this.animinfo.length; }
    
    var value=0;
    if (delta < 0) {
      value=100;
    }
    else {
      value=0;
    }
    this.setOpacity(el, value * 0.01);
    el.style.zOrder = this.animinfo.length+1;
    this.animinfo[j] = { el: el, value: value, delta: delta, fn:function(pos){ 	return ((-Math.cos(pos*Math.PI)/2) + 0.5); } };
  }
  
  this.timerCallback = function() {
  
    //var s = this.animinfo.length + " items : { ";
    //for (var i=0; i<this.animinfo.length; i++) { s += this.animinfo[i].value + ", "; }
    //s += "}";
    //document.title = s;
    
    for (var i=0; i<this.animinfo.length; i++) {
      if (this.animinfo[i] && this.animinfo[i].el) {
      
        var newvalue = this.animinfo[i].value + this.animinfo[i].delta;
        var finished = false;
        
        if (newvalue <= 0) {
          newvalue = 0;
          finished = true;
        }
        if (newvalue >= 100) {
          newvalue = 100;
          finished = true;
        }
  
        
        result = this.animinfo[i].fn(newvalue*0.01);
        this.setOpacity(this.animinfo[i].el, result);
        
        if (finished) {
          
          if (this.animinfo[i].delta < 0) {
            // Fully hidden
            this.animinfo[i].el.style.display = "none";
          }
          else {
            this.animinfo[i].el.style.display = "";
          }
          
          this.animinfo[i] = false;
        }
        else {
          
          this.animinfo[i].value = newvalue;
          this.animinfo[i].el.style.display = "";
          
        }
      }
    }
  }
  
  /*
	this.setOpacity = function(el,opacity) {
		if (opacity == 0 && el.style.visibility != "hidden") el.style.visibility = "hidden";
		else if (el.style.visibility != "visible") el.style.visibility = "visible";
		if (window.ActiveXObject) el.style.filter = "alpha(opacity=" + opacity*100 + ")";
		el.style.opacity = opacity;
	}*/
	
	this.setOpacity = function(el,opacity) {
		//if (opacity == 0 && el.style.display != "none") el.style.display = "none";
		//else el.style.display = "";
		if (window.ActiveXObject) el.style.filter = "alpha(opacity=" + opacity*100 + ")";
		el.style.opacity = opacity;
	}
  
  this.startTimer = function() {
    if (this.timerID) { this.stopTimer(); }
    this.timerID = setInterval(this.timerCallback.bind(this), 25);
  }
  
  this.stopTimer = function() {
    if (this.timerID && window && window.clearInterval) {
      window.clearInterval(this.timerID);
      this.timerID = false;
    }
  }
  
  this.startTimer();
}

function TreeScroller() {
  var scroller;
  
  this.outerframe = document.getElementById("floatingFrameHolder").getElementsByTagName("div")[0].getElementsByTagName("div")[0];
  //this.outerframe = document.createElement("div");
  //this.outerframe.className = "floatingFrameInner";
  this.outerframe.style.cssText = "background:black; overflow: hidden;";
  
  this.innerframe = document.createElement("div");
  this.innerframe.style.cssText = "position: absolute; width: 30px; height: 30px; background: blue; border: 2px solid red;";
  
  this.outerframe.appendChild(this.innerframe);
  
  
  this.onscroll = function(scrollpos, scrollinfo, mousepos) {
    var w = (this.outerframe.offsetWidth-8)  * scrollinfo.pagesize.x;
    var h = (this.outerframe.offsetHeight-8)  * scrollinfo.pagesize.y;
    if (w<0) { w = (this.outerframe.offsetWidth-4); }
    if (h<0) { h = (this.outerframe.offsetHeight-4); }
    
    h = (this.outerframe.offsetHeight-8)  * (this.scroller.attach.offsetHeight) / (this.scroller.vscroll.scrollHeight + this.scroller.hscroll.offsetHeight);
    
    
    var pos = MapPoint( scrollpos, scrollinfo.scrollrange, {min:{x:0,y:0},avg:{x:0,y:0},max:{x:w,y:h}});
    l = pos.x; t = pos.y;
    
    /*
    var s0  = "w = " + w + " , h = " + h + "l = " + l + " , t = " + t + "<br /> ps: x=" + scrollinfo.pagesize.x + ", y=" + scrollinfo.pagesize.y;

    var s1 = "X : " + scrollinfo.scrollrange.min.x + " , " + scrollinfo.scrollrange.avg.x + " , " + scrollinfo.scrollrange.max.x + "<br />";
        s1 +=         scrollinfo.mouserange.min.x  + " , " + scrollinfo.mouserange.avg.x  + " , " + scrollinfo.mouserange.max.x  + "<br />";
        s1 +=         mousepos.x + " => " + scrollpos.x;
        
    var s2 = "Y : " + scrollinfo.scrollrange.min.y + " , " + scrollinfo.scrollrange.avg.y + " , " + scrollinfo.scrollrange.max.y + "<br />";
        s2 +=         scrollinfo.mouserange.min.y  + " , " + scrollinfo.mouserange.avg.y  + " , " + scrollinfo.mouserange.max.y  + "<br />";
        s2 +=         mousepos.y + " => " + scrollpos.y;
        s2 += "<br />" + scrollpos.ydebug
                    
    $("footer").innerHTML = "<table border=\"1\" style=\"width: 100%; table-layout: fixed\"><tr><td><code>" + s0 + "</code></td><td><code>" + s1 + "</code></td><td><code>" + s2 + "</code></td></tr></table>";
    */
    
    /*
    this.innerframe.style.left   = l + "px";
    this.innerframe.style.top    = t + "px";
    this.innerframe.style.width  = w + "px";
    this.innerframe.style.height = h + "px";
    */
    
    var sh  = scrollinfo.scrollrange.max.y - scrollinfo.scrollrange.min.y;
    var sy  = scrollpos.y - scrollinfo.scrollrange.min.y;
    var eh  = (this.scroller.vscroll.offsetHeight + this.scroller.hscroll.offsetHeight) / (this.scroller.vscroll.scrollHeight + this.scroller.hscroll.offsetHeight);
    if (eh<0) { eh = 0; } if (eh>1) { eh=1; }
    var th  = this.outerframe.offsetHeight-4-23;
    var tsy = th * eh;
    if ( isNaN(tsy) || (tsy < 8) ) tsy = 8;
    var ty  = (sy/sh) * (th-tsy);
    
    if (isNaN(ty) || (ty < 0)) ty = 0;
    if (ty + tsy > this.outerframe.offsetHeight-4-23) { tsy = this.outerframe.offsetHeight-4-23 - ty; }
    
    //document.title = /*"Y = " + (ty) + " to " + (ty+tsy) +*/ " [max : " + (this.outerframe.offsetHeight-4) + "]";
    
    var sw  = scrollinfo.scrollrange.max.x - scrollinfo.scrollrange.min.x;
    var sx  = scrollpos.x - scrollinfo.scrollrange.min.x;
    var ew  = scrollinfo.pagesize.x;
    
    var tw  = this.outerframe.offsetWidth-4;
    var tsx = tw * ew;
    if ( (isNaN(tsx)) || (tsx < 8) ) tsx = 8;
    var tx  = (sx/sw) * (tw-tsx);
    
    if (isNaN(tx) || (tx < 0)) tx = 0;
    
    this.innerframe.style.top    = ty  + "px";
    this.innerframe.style.height = tsy + "px";
    this.innerframe.style.left   = tx  + "px";
    this.innerframe.style.width  = tsx + "px";
    
    //frameMgr.timerCallback();
  }
  
  this.onscrollstart = function() {
    
    //frameMgr.showFrame("Scroll Position", this.outerframe);
    //frameMgr.timerCallback();
    
    var scrollinfo = this.scroller.getScrollInfo();
    
    var sh  = scrollinfo.scrollrange.max.y - scrollinfo.scrollrange.min.y;
    var sy  = scrollinfo.scrollpos.y - scrollinfo.scrollrange.min.y;
    var eh  = (this.scroller.vscroll.offsetHeight + this.scroller.hscroll.offsetHeight) / (this.scroller.vscroll.scrollHeight + this.scroller.hscroll.offsetHeight);
    if (eh<0) { eh = 0; } if (eh>1) { eh=1; }
    
    var th  = this.outerframe.offsetHeight-4-23;
    var tsy = th * eh;
    if ( isNaN(tsy) || (tsy < 8) ) tsy = 8;
    var ty  = (sy/sh) * (th-tsy);
    
    if (isNaN(ty) || (ty < 0)) ty = 0;
    if (ty + tsy > this.outerframe.offsetHeight-4-23) { tsy = this.outerframe.offsetHeight-4-23 - ty; }
    
    //document.title = "Y = " + (100*(sy/sh)) + "%";
    
    var sw  = scrollinfo.scrollrange.max.x - scrollinfo.scrollrange.min.x;
    var sx  = scrollinfo.scrollpos.x - scrollinfo.scrollrange.min.x;
    var ew  = scrollinfo.pagesize.x;
    
    var tw  = this.outerframe.offsetWidth-4;
    var tsx = tw * ew;
    if ( (isNaN(tsx)) || (tsx < 8) ) tsx = 8;
    var tx  = (sx/sw) * (tw-tsx);
    
    if (isNaN(tx) || (tx < 0)) tx = 0;
        
    //alert( [ty,tsy,tx,tsx].join(", "));
    
    this.innerframe.style.top    = ty  + "px";
    this.innerframe.style.height = tsy + "px";
    this.innerframe.style.left   = tx  + "px";
    this.innerframe.style.width  = tsx + "px";
        
  }
  
  this.onscrollend = function() {
    //frameMgr.hideFrame(this.outerframe);
  }
  
  this.scroller = new ElementScroller(
                                  $("treeframe"),
                                  $("treeframe-children"),
                                  $("treeframe-inner"),
                                  { cookiename : "treescrollpos",
                                    onstartscroll : this.onscrollstart.bind(this),
                                    onendscroll   : this.onscrollend.bind(this),
                                    onscroll      : this.onscroll.bind(this)
                                  }
                                 );
                                 
  this.onscrollstart();
}

addEvent(window, "load", function() { 
  frameMgr = new FloatingFrameManager();
  treeScroller = new TreeScroller();
}, false);

