/* Copyright (c) 1997-2006
   Ewgenij Gawrilow, Michael Joswig (Technische Universitaet Berlin, Germany)
   http://www.math.tu-berlin.de/polymake,  mailto:polymake@math.tu-berlin.de

   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 2, or (at your option) any
   later version: http://www.gnu.org/licenses/gpl.txt.

   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.
*/

function getLayers(l) {
   if (! l.layers) {
      l.layers=new Array;
      for (var i=0; i<l.childNodes.length; ++i) {
         var c=l.childNodes[i];
	 if (c.nodeName == "DIV") l.layers.push(c);
      }
   }
   return l.layers;
}

function getImage(l) {
   for (var i=0; i<l.childNodes.length; ++i) {
      if (l.childNodes[i].nodeName == "A") {
	 l=l.childNodes[i];
	 for (var j=0; j<l.childNodes.length; ++j) {
	    if (l.childNodes[j].nodeName == "IMG")
	       return l.childNodes[j];
	 }
      }
   }
   return null;
}

function getSelect(l) {
   for (var i=0; i<l.childNodes.length; ++i) {
      if (l.childNodes[i].nodeName == "FORM") {
	 l=l.childNodes[i];
	 for (var j=0; j<l.childNodes.length; ++j) {
	    if (l.childNodes[j].nodeName == "SELECT")
	       return l.childNodes[j];
	 }
      }
   }
   return null;
}

function scroll_start(dir) {
   var y=this.pane.offsetTop;  var h=this.pane.expandedHeight;
   if (dir<0 ? y+h > this.navBottom : y < 0) {
      this.timeoutId=this.win.setTimeout("top.Nav.scroll_glide("+dir+")", this.scrollDelay);
   }
}

function move_pane(me, delta) {
   var y=me.pane.offsetTop;  var h=me.pane.expandedHeight;
   if (delta<0) {
      if (y+delta+h < me.navBottom) {
	 me.pane.style.top=(me.navBottom-h) + "px";
	 return false;
      }
   } else {
      if (y+delta > 0) {
	 me.pane.style.top="0px";
	 return false;
      }
   }
   me.pane.style.top=(me.pane.offsetTop+delta) + "px";
   return true;
}

function scroll_glide(dir) {
   if (this.timeoutId) {
      this.win.clearTimeout(this.timeoutId);
      this.timeoutId=undefined;
   }
   if (move_pane(this, dir*this.scrollStep))
      this.timeoutId=this.win.setTimeout("top.Nav.scroll_glide("+dir+")", this.scrollTimer);
}

function scroll_click(delta) {
   this.scroll_stop();
   move_pane(this, delta*this.navBottom);
}

function scroll_stop() {
   if (this.timeoutId) {
      this.win.clearTimeout(this.timeoutId);
      this.timeoutId=undefined;
   }
}

function check_scroll_active(me) {
   if (!me.noScroll) {
      var nav=me.pane;
      if (nav.expandedHeight <= me.navBottom) {
	 nav.style.top="0px";
	 me.scroll_arrows.style.visibility="hidden";
      } else {
	 var excess = nav.expandedHeight - me.navBottom;
	 var bottom_gap = excess + nav.offsetTop;
	 if (bottom_gap < 0) nav.style.top=(nav.offsetTop-bottom_gap) + "px";
	 me.scroll_arrows.style.visibility="visible";
      }
   }
}

function inhibit_scroll() {
   this.noScroll=1;
   this.pane.style.top="0px";
   this.scroll_arrows.style.visibility="hidden";
}

function tell_expand() {
   window.status= this.containingLayer.isExpanded ? "Collapse subtopics" : "Expand subtopics";
   return true;
}

function highlight_on(elem) {
   var s=elem.style;
   s.borderStyle="dotted";
   s.borderColor="red";
   s.borderWidth="1px";
}

function highlight_off(elem) {
   var s=elem.style;
   s.borderStyle="none";
}

function topic_highlight_on(topic) {
   highlight_on(topic.getElementsByTagName("a")[0]);
}

function topic_highlight_off(topic) {
   highlight_off(topic.getElementsByTagName("a")[0]);
}

function toggle_me() {
   var nav=top.Nav;
   nav.highlight_off();
   nav.toggle(this.containingLayer, this);
   return false;
}

function change_me() {
   var nav=top.Nav;
   nav.highlight_off();
   if (this.selectedIndex != this.containingLayer.isExpanded)
      nav.change(this.containingLayer, this.selectedIndex);
   return false;
}

function highlight(level, chooser) {
   var l = this.pane;
   var y = l.offsetTop;
   var layers = getLayers(l);
   var descend= chooser !== undefined ? chooser : level;
   for (var i=0; i<descend.length; ++i) {
      l=layers[descend[i] + l.firstSubtopic];
      if (chooser !== undefined && i==descend.length-1) {
	 descend=level[l.isExpanded ? l.isExpanded-1 : 0];
	 chooser=undefined;
      }
      if (i<descend.length-1) {
	 if (l.selector) {
	    var selectedIndex=descend[++i]+1;
	    if (l.isExpanded != selectedIndex) {
	       this.change(l,selectedIndex);  y=undefined;
	       l.selector.selectedIndex=selectedIndex;
	    }
	    l=(getLayers(l))[selectedIndex];
	 } else if (!l.isExpanded) {
	    this.toggle(l);  y=undefined;
	 }
      }
      if (y !== undefined) y+=l.offsetTop;
      layers = getLayers(l);
   }
   if (this.hlTopic) topic_highlight_off(this.hlTopic);
   this.hlTopic= layers && layers.length ? layers[0] : l;
   topic_highlight_on(this.hlTopic);
   if (y != undefined) {
      if (y<0 || (y += this.hlTopic.offsetHeight - this.navBottom)>0) {
	 this.pane.style.top=(this.pane.offsetTop-y) + "px";
	 check_scroll_active(this);
      }
   }
}

function choose_content(URLs, chooser) {
   var l = this.pane;
   var layers = getLayers(l);
   for (var i=0; i<chooser.length; ++i) {
      l=layers[chooser[i] + l.firstSubtopic];
      layers = getLayers(l);
   }
   if (l.isExpanded) {
      top.gotoURL(contents, URLs[l.isExpanded-1]);
      return false;
   } else {
      return true;
   }
}

function init_layer(l, w, expand_now) {
   var layers = getLayers(l);
   var x=0; var y=0;
   var own_topic;
   if (layers.length) {
      if (l.arrow === undefined)
	 l.arrow = getImage(l);
      if (l.arrow) {
	 own_topic = layers[0];
	 l.isExpanded = expand_now || this.saved_state && this.saved_state.shift();
	 if (expand_now) {	// called from toggle, own_topic is already visible
	    l.arrow.src = this.arrowCollapse;
	 } else {
	    if (l.isExpanded) l.arrow.src = this.arrowCollapse;
	    var link = (l.getElementsByTagName("a"))[0];
	    link.containingLayer = l;
	    link.onmouseover=tell_expand;
	    link.onclick=toggle_me;
	    l.availableWidth = w;
	 }

      } else {
	 if (l.selector === undefined)
	    l.selector = getSelect(layers[0]);
	 if (l.selector) {
	    own_topic = layers[0];
	    if (this.saved_state)
	       l.selector.selectedIndex = this.saved_state.length && this.saved_state.shift();
	    l.isExpanded = l.selector.selectedIndex;
	    l.selector.containingLayer = l;
	    l.selector.onchange=change_me;
	    var def_link=(own_topic.getElementsByTagName("a"))[0];
	    if (def_link) {
	       l.selector.def_page=def_link.getAttribute("href");
	       l.selector.onclick=function() {
		  if (this.selectedIndex==0 && this.def_page)  top.contents.document.location=this.def_page;
	       }
	    }
	    l.availableWidth = w;
	 } else {
	    this.saved_state && this.saved_state.shift();
	    l.isExpanded = true;
	 }
      }
   } else {	// a leaf
      l.style.width=w + "px";
      l.expandedHeight=l.offsetHeight;
      return l.expandedHeight;
   }

   if (own_topic) {
      x = this.arrowWidth;
      if (!expand_now) {
	 l.firstSubtopic=1;
	 own_topic.style.left=x + "px";
	 own_topic.style.top="0px";
	 own_topic.style.width=w + "px";
	 own_topic.style.visibility="inherit";
      }
      y = own_topic.offsetHeight;
      if (l.selector && isMOZ) y*=0.6;
   } else {
      l.firstSubtopic=0;
   }

   var h=0; var subtopic;
   if (l.selector) {
      for (var i=l.firstSubtopic; i<layers.length; ++i) {
	 subtopic=layers[i];
	 subtopic.style.left=x + "px";
	 subtopic.style.top=y + "px";
      }
      l.expandedHeight=y;
      if (l.isExpanded) {
	 subtopic=layers[l.isExpanded];
	 subtopic.style.visibility="inherit";
	 h = this.init_layer(subtopic, w);
      }

   } else if (l.isExpanded) {
      for (var i=l.firstSubtopic; i<layers.length; ++i) {
	 subtopic=layers[i];
	 h += this.topicPadding;
	 subtopic.style.left=x + "px";
	 subtopic.style.top=(y+h) + "px";
	 subtopic.style.visibility="inherit";
	 if (i>l.firstSubtopic && !subtopic.siblingAbove)
	    layers[i-1].siblingAbove=subtopic;
	 h += this.init_layer(subtopic, w-x);
      }
      l.expandedHeight=h;
   }
   return y+h;
}

function expand(l, delta_h, vis_height) {
   var nav = this.pane;
   var y_top=0; 
   while (true) {
      if (vis_height !== undefined) y_top+=l.offsetTop;
      if (l == nav) break;
      while (l.siblingAbove) {
	 l=l.siblingAbove;
	 l.style.top=(l.offsetTop+delta_h) + "px";
      }
      l=l.parentNode;
      l.expandedHeight += delta_h;
   }
   if (vis_height !== undefined) {
      var y_bottom = Math.min(vis_height, this.navBottom) + y_top;
      if (y_top<0)
	 nav.style.top=(nav.offsetTop-y_top) + "px";
      else if ((y_bottom-=this.navBottom)>0)
	 nav.style.top=(nav.offsetTop-y_bottom) + "px";
   }
   check_scroll_active(this);
}

function toggle(l, link) {
   var delta_h; var vis_height;
   if (l.expandedHeight === undefined) {
      vis_height = this.init_layer(l, l.availableWidth, true);
      delta_h = l.expandedHeight;
   } else {
      var vis;
      var layers = getLayers(l);
      var own_topic=layers[0];
      if (l.isExpanded) {
	 delta_h = -l.expandedHeight;
	 vis = "hidden";
	 l.arrow.src = this.arrowExpand;
	 l.isExpanded = false;
      } else {
	 delta_h = l.expandedHeight;
	 vis_height = own_topic.offsetHeight + delta_h;
	 vis = "inherit";
	 l.arrow.src = this.arrowCollapse;
	 l.isExpanded = true;
      }
      for (var i=1; i<layers.length; ++i) {
	 layers[i].style.visibility=vis;
      }
   }
   this.expand(l,delta_h,vis_height);
}

function change(l, new_index) {
   var delta_h=0; var vis_height;
   var sublayer;
   if (l.isExpanded) {
      sublayer = l.layers[l.isExpanded];
      delta_h -= sublayer.expandedHeight;
      sublayer.style.visibility="hidden";
   }
   l.isExpanded=new_index;
   if (l.isExpanded) {
      sublayer = l.layers[l.isExpanded];
      if (sublayer.expandedHeight === undefined)
	 this.init_layer(sublayer, l.availableWidth);
      delta_h += sublayer.expandedHeight;
      sublayer.style.visibility="inherit";
   }
   if (delta_h > 0)
      vis_height = l.expandedHeight + sublayer.expandedHeight;
   this.expand(l,delta_h,vis_height);
}

function save_state(l) {
   this.saved_state.push(l.isExpanded);
   if (l.isExpanded) {
      var layers=getLayers(l);
      if (l.selector) {
	 this.save_state(layers[l.isExpanded]);
      } else {
	 for (var i=l.firstSubtopic; i<layers.length; ++i)
	    if (layers[i].firstSubtopic !== undefined)
	       this.save_state(layers[i]);
      }
   }
}

function repaint() {
   if (this.curHeight != winH(this.win) || this.curWidth != winW(this.win)) {
      this.saved_state=new Array;
      this.save_state(this.pane);
      this.win.document.location.reload();
   }
}

function init_pane(win) {
   this.win=win;
   var doc=win.document;
   this.curHeight=winH(win);
   this.curWidth=winW(win);
   var nav = doc.getElementById("navigation");
   this.pane = (nav.getElementsByTagName("div"))[0];
   var side_margin=nav.offsetLeft;
   this.topicPadding=nav.offsetTop;
   if (!this.arrowExpand) {
      var arrow = (this.pane.getElementsByTagName("img"))[0];
      this.arrowExpand = arrow.src;
      this.arrowCollapse = this.arrowExpand.replace("expand","collapse");
      this.arrowWidth = arrow.width;
   }

   this.footer = doc.getElementById("footer");
   this.scroll_arrows = doc.getElementById("scroll_arrows");
   var arrowH = this.scroll_arrows.offsetHeight;
   this.navBottom = winH(win) - this.footer.offsetHeight - arrowH;
   nav.style.zIndex=1;
   this.scroll_arrows.style.top=this.navBottom + "px";
   this.footer.style.top=(this.navBottom+arrowH) + "px";
   var WW=winW(win);
   if (top.isOpera) this.scroll_arrows.style.width=WW + "px";
   WW-=2*side_margin;
   nav.style.width=WW + "px";
   nav.style.height=this.navBottom + "px";
   nav.style.clip="rect(0px, " + WW + "px, " + this.navBottom + "px, 0px)";

   nav.style.visibility="visible";
   this.footer.style.visibility="visible";

   this.init_layer(this.pane, WW-2*side_margin);
   delete this.saved_state;
   check_scroll_active(this);
   win.onresize=function() { top.Nav.repaint() }
   win.onscroll=function() { top.Nav.inhibit_scroll(); this.onscroll=null; return true; }

   if (top.hlNavTopic) {
      this.highlight(top.hlNavTopic);
      top.hlNavTopic=null;
   }
}

function Nav_handler() {
   this.win=undefined;
   this.pane=undefined;
   this.scroll_arrows=undefined;
   this.footer=undefined;
   this.navBottom=0;
   this.topicPadding=0;
   this.arrowCollapse=undefined;
   this.arrowExpand=undefined;
   this.arrowWidth=undefined;
   this.curHeight=0;
   this.curWidth=0;

   this.init_pane=init_pane;
   this.init_layer=init_layer;
   this.toggle=toggle;
   this.change=change;
   this.expand=expand;
   this.repaint=repaint;
   this.highlight=highlight;
   this.highlight_off=function () {
      if (this.hlTopic) {
	 topic_highlight_off(this.hlTopic);
	 this.hlTopic=null;
      }
   };
   this.choose_content=choose_content;
   this.save_state=save_state;
   this.scroll_start=scroll_start;
   this.scroll_glide=scroll_glide;
   this.scroll_click=scroll_click;
   this.scroll_stop=scroll_stop;
   this.inhibit_scroll=inhibit_scroll;
   this.timeoutId=undefined;
}

var Nav=new Nav_handler();
