//////////////////////////////////////////////////////////////
// this code interacts with an <div> element in the HTML
// with the element id 'page_state' which is then used
// as a collection of global variables to keep track of
// moving elements in the page.
//
// page_state variables are only manipulated in 
// the following functions:
// 
// pageState, pageName
//
// initHTML, updateHTML 
//    (methods of Physics object)
//////////////////////////////////////////////////////////////


///////////////////////////////////////////////////////////
// BASIC INTERFACE TO ELEMENTS AND ATTRIBUTES IN THE HTML
///////////////////////////////////////////////////////////

function pageState()
{
  var pageState = document.getElementById("page_state");
  return pageState;
}

function pageName()
{
  var pageName=pageState().getAttribute("pageName");  
  return pageName;
}

function setPageVar(name, value)
{
  pageState().setAttribute(name, value);
}

function getPageVar(name)
{
  var value = pageState().getAttribute(name);
  return value;
}

function contentPic()
{
  var image = document.getElementById("content_pic");;
  return image;
}

function navigationBar()
{
  var navigationBar = document.getElementById("navigation");
  return navigationBar;
}

///////////////////////////////////
// src names:
///////////////////////////////////

function mouseoverButtonSrc(buttonName)
{
  var src = "images/buttons/" + buttonName + "_active.jpg";
  return src;
}

function mouseoutButtonSrc(buttonName)
{
  var src = "images/buttons/" + buttonName + "_inactive.jpg";
  return src;
}

function currentButtonSrc(buttonName)
{
  var src = "images/buttons/" + buttonName + "_currentButton.jpg";
  return src;
}

function contentPicSrc(name)
{
  src = "images/" + name + "_pic.jpeg";
  return src;
}

///////////////////////////////////////////////////////////
// BUTTONS
///////////////////////////////////////////////////////////


function activeLinkName()
// gives a name for the current page used for comparing to the button 'name'
// variable used to decide which button the current page corresponds to.
{
  var link_name = pageName();
  return link_name;
}

function Button(name, buttonId, overURL, outURL)
//  the constructor function assigns to the object in the HTML with
//  id=buttonId the following image src's:
//    if active, never change from initial pic
//    if mouseover, overURL
//    if mouseout, outURL
//
//  we decide if the link corresponds to the active page by checking
//  if the button's name variable matches the output of activeLinkName()
//
//  externally prototyped methods:
//    initButton (constructor function)
{
  this.name = name;
  this.id = buttonId;
  this.overURL = overURL;
  this.outURL = outURL;

  if (!(activeLinkName() == this.name))
    this.init();
}

Button.prototype.init = function()
// loads the javascript associated to button
{
  //  if we don't declare these string variables with the 'var' syntax,
  //  each new button tries to modify the same variables --- is it possible
  //  that without the 'var' statement, the variables are really global???
  //  YES. this is how it works (experimentation).
  var overURL = this.overURL;
  var outURL = this.outURL;
  var buttonElement = document.getElementById(this.id);
  buttonElement.onmouseover = function(){this.src = overURL;}
  buttonElement.onmouseout = function(){this.src = outURL;}
}

///////////////////////////////////////////////////////////////////
// EXPANDING LIST
///////////////////////////////////////////////////////////////////
//  these use the following structures within the html:
//    within the html, we have two div's (corresponding to
//    a list called 'name'):
//      id = nameHeader
//        (this encloses a single element which is an h1)
//      id = name   
//        (this encloses a single element whic is the list itself)      
///////////////////////////////////////////////////////////////////

function ExpandingList(divId)
// externally defined prototypes
//    open, close, replaceHeader
//
// externally defined data
//    openHeader, closedHeader 
{
  this.div = document.getElementById(divId);
  this.name = divId;
  this.header = this.div.getElementsByTagName("h1")[0];
  var ulChildren = this.div.getElementsByTagName("ul");
  var olChildren = this.div.getElementsByTagName("ol");
  if (ulChildren.length > 0)
    this.list = ulChildren[0];
  else
    this.list = olChildren[0];

  //  constructor:
  this.replaceHeader();
  this.close();
}

ExpandingList.prototype.replaceHeader = function()
{
  var header = this.header;

  function newHeader(someText)
  {
    var textNode = document.createTextNode(someText);
    var headerNode = document.createElement("h1");
    headerNode.appendChild(textNode);

    headerNode.onmouseover = function(){this.style.color="white";}
    headerNode.onmouseout = function(){this.style.color="black";}

    return headerNode;
  }

  var openText = "\u25BC " + this.name;
  this.openHeader = newHeader(openText);

  var closedText = "\u25BA " + this.name;
  this.closedHeader = newHeader(closedText);

  var expandingList = this;
  //  I'm doing the above statement, because the context
  //  seems to change later when I want to call its methods
  //  in the onclick functions below...

  this.div.insertBefore(this.openHeader, header);
  this.div.insertBefore(this.closedHeader, header);
  this.div.removeChild(header);
  this.openHeader.onclick = function(){expandingList.close();};
  this.closedHeader.onclick = function(){expandingList.open();};
}

ExpandingList.prototype.close = function()
{
  this.list.style.display = "none";
  this.openHeader.style.display = "none";
  this.closedHeader.style.display = "inline";
}

ExpandingList.prototype.open = function()
{
  this.list.style.display = "inline";
  this.closedHeader.style.display = "none";
  this.openHeader.style.display = "inline";
}


///////////////////////////////////////////////////////////
// MOVING PAGE ELEMENTS
///////////////////////////////////////////////////////////

function Physics(name, vInitial, dMin, dMax, vMax, bounce, vBounce, aBounce,
timeStep, delay, updateStyleFcn, returnFcn)
// Object (when evolve method is called) will start with fixed velocity at
// position dMax, and position d will proceed at velocity v to dMin (v is sign
// reversed so that positive v is in the direction from dMax to dMin). When
// dMin is reached, if bounce is nonzero, object will acquire velocity vBounce (in
// the direction from vMin to vMax) and accelleration aBounce (in the direction
// from vMax to vMin), and bounce will be decreased by 1. When dMin is reached
// with bounce 0, object stops (evolve terminates).
// 
// timeStep = time between iterations of animation (smaller is
// cleaner/slower/more processing) delay = time before beginning animations  
//
// externally prototyped methods:
//    initHTML
//    updateHTML, updateVars (internal use only)
//    evolve
{
  this.name = name;
  this.d = dMax;
  this.v = -vInitial;
  this.a = 0;
  this.dMin = dMin;
  this.dMax = dMax;
  this.vMax = vMax;
  this.bounce = bounce;
  this.vBounce = vBounce;
  this.aBounce = aBounce;
  this.timeStep = timeStep;
  this.delay = delay;
  this.returnFcn = returnFcn;
  this.updateStyleFcn = updateStyleFcn;

  // this function creates variables within the HTML based on
  // the name. 
  this.updateHTML();
  var context = this;
    function evolve()
    {
      context.evolve(); 
    }
  setTimeout(function(){evolve();}, delay);
}

// Externally prototyped Physics methods:

Physics.prototype.updateHTML = function()
{
  setPageVar(this.name + "_d", this.d);
  setPageVar(this.name + "_v", this.v);
  setPageVar(this.name + "_a", this.a);
  setPageVar(this.name + "_bounce", this.bounce);

  this.updateStyleFcn(this.d);
}

Physics.prototype.updateVars = function()
{
  var name = this.name;
  this.d = parseFloat(getPageVar(name + "_d")); 
  this.v = parseFloat(getPageVar(name + "_v")); 
  this.a = parseFloat(getPageVar(name + "_a")); 
  this.bounce = parseInt(getPageVar(name + "_bounce"));
}

Physics.prototype.evolve = function()
{
  this.updateVars();
  var context = this;
  function doOver()
  {
    context.evolve(); 
  }

  var newD = this.d + this.v;
  if (newD < this.dMin)
    newD = this.dMin;
  this.d = newD;

  var newV = this.v + this.a;
  if ((-newV) > this.vMax)
    newV = -this.vMax;
  this.v = newV;

  if (this.d == this.dMin)
    {
      if (this.bounce > 0)
      {
        this.bounce -= 1;
        this.v = this.vBounce;
        this.a = this.aBounce;
        this.vBounce = this.vBounce*(.6);
        this.updateHTML();
        setTimeout(function(){doOver();}, this.timeStep);
      }
      else
        {
          this.updateHTML();
          this.returnFcn();
        }
    }
  else
    {
    this.updateHTML();
    setTimeout(function(){doOver();}, this.timeStep);
    }

}

///////////////////////////////////////////////////////////////////
// STARTUP ROUTINES
///////////////////////////////////////////////////////////////////

function initButtons()
// searches for the following id's: 
// homeButton, researchButton, programmingButton, teachingButton
{
  function newButtonNamed(name)
  {
    var id = name + "Button";
    var overURL = mouseoverButtonSrc(name);
    var outURL = mouseoutButtonSrc(name);
    new Button(name, id, overURL, outURL);
  }
  newButtonNamed("home");
  newButtonNamed("research");
  newButtonNamed("programming");
  newButtonNamed("teaching");
}

function animateNavigation()
{
  function doNothing(){}
  function update(value){navigationBar().style.marginTop = Math.round(value) + "%";}

  new Physics("navBar",
    3.5,            //  vInitial
    3,            //  dMin
    115,            //  dMax
    50,             //  vMax
    0,          //  bounce?
    0,              //  vBounce
    0,              //  aBounce
    2,              //  timeStep
    0,              //  delay
    update,         //  update style function
    doNothing);     //  return function
}

function animateContentPic(speed, vBounce, aBounce, delay, bounce)
{
  function doNothing(){}
  function update(value){contentPic().style.right = value + "%";}

  new Physics("contentPic",
    speed,            //  vInitial
    -5,             //  dMin
    115,            //  dMax
    50,             //  vMax
    bounce,           //  bounce?
    vBounce,             //  vBounce
    aBounce,           //  aBounce
    1,              //  timeStep
    delay,              //  delay
    update,         //  update style function
    doNothing);     //  return function
}

//////////////////////////////////////////////////////////////////////
//  This is the function which is called by the body onload event
//  (i.e. after all the elements and their respective id's in the code
//  have been parsed!)
//////////////////////////////////////////////////////////////////////

function onloadRoutine()
{
  showAfterLoad();
  animatePage();
}


//////////////////////////////////////////////////////////////
//  OTHER INITIALIZATION ROUTINES
//////////////////////////////////////////////////////////////

function animatePage()
{
  var name=pageName();
  initButtons();
  switch(name)
  {
    case "home":
      animateContentPic(3.5, 5, -.15, 300, 4);
      animateNavigation();
      generateEmail();
      break;
    case "research":
      animateContentPic(7, 1, -.1, 300, 1);
      break;
    case "programming":
      animateContentPic(7, 1, -.1, 300, 1);
      break;
    case "teaching":
      animateContentPic(7, 3, -.1, 300, 3);
      break;
  }
}

function generateEmail()
{
  emailLink = document.getElementById("email");
  unicodeEmail =
  "\u0064\u006b\u0072\u0061\u0073\u0068\u0065\u006e\u0040\u006d\u0061\u0074\u0068\u002e\u0075\u0067\u0061\u002e\u0065\u0064\u0075";
  
  //  see for example : http://www.mikezilla.com/exp0012.html
  //  for a unicode conversion to hex format
  emailLink.setAttribute("href","mailto:"+ unicodeEmail);
}

function elementsToHide()
{
  var toHide = [navigationBar(), contentPic()];
  return toHide;
}

function hideWhileLoading()
{
  var toHide = elementsToHide();
  for (i in toHide)
    toHide[i].style.display="none";

  if (pageName() == "research")
  {
    new ExpandingList("Publications");
    new ExpandingList("Preprints");
    new ExpandingList("Lecture Slides");
    new ExpandingList("Other Manuscripts");
  }
}

function showAfterLoad()
{
  var toShow = elementsToHide();
  for (i in toShow)
    toShow[i].style.display="";
}

////////////////////////////////////////////////////////////
// THIS WILL RUN IN THE HEAD WHEN THE SCRIPT IS FIRST READ!
////////////////////////////////////////////////////////////

//  this space has been intentionally left blank.


