function hideBanner() {
  document.getElementById("bannerContainer").style.display = 'none';
  document.getElementById("hide_banner").style.display = 'none';
  document.getElementById("show_banner").style.display = '';

  var code = extractFromOrder('BANNER');
  var codePos = widgetOrder.indexOf(code);  
  var codeLen = code.length;
  if (code.indexOf('~') == -1) {
    code = '~' + code;
  }

  widgetOrder = widgetOrder.substring(0, codePos) +
    code + widgetOrder.substring(codePos + codeLen);
  saveWidgetOrder();
}

function showBanner() {
  document.getElementById("bannerContainer").style.display = '';
  document.getElementById("hide_banner").style.display = '';
  document.getElementById("show_banner").style.display = 'none';

  var code = extractFromOrder('BANNER');
  var codePos = widgetOrder.indexOf(code);  
  var codeLen = code.length;
  var symbolPos = code.indexOf('~');
  if (symbolPos != -1) {
    code = code.substring(0, symbolPos) + code.substring(symbolPos + 1);
  }
  widgetOrder = widgetOrder.substring(0, codePos) +
    code + widgetOrder.substring(codePos + codeLen);
  saveWidgetOrder();
}


function showCustomization() {
  var images = document.images;
  for (var i = 0; i < images.length; i++) {
    var icon = images[i];
    var className = icon.className;
    if (className.indexOf("icon ") == 0) {
      var parentName = icon.parentNode.className;
      if (parentName.indexOf("customization") != -1) {
        icon.parentNode.style.display="inline";
      }
    }
  }

  document.getElementById("show_customization").style.display = 'none';
  document.getElementById("hide_customization").style.display = '';
}

function hideCustomization() {
  var images = document.images;
  for (var i = 0; i < images.length; i++) {
    var icon = images[i];
    var className = icon.className;
    if (className.indexOf("icon ") == 0) {
      var parentName = icon.parentNode.className;
      if (parentName.indexOf("customization") != -1) {
        icon.parentNode.style.display="none";
      }
    }
  }

  document.getElementById("show_customization").style.display = '';
  document.getElementById("hide_customization").style.display = 'none';
}


function hideWidget(name) {
  document.getElementById(name).style.display = 'none';
  hideColumnIfInvisible(document.getElementById(name).parentNode);


  var showLabel = document.getElementById("show_" + name);
  if (showLabel) {
    showLabel.className = 'show';
    showLabel.alt = "[Add widget '" + widgetTitles[name] + "']";
    showLabel.title = "Add widget '" + widgetTitles[name] + "'";
  }

  var code = extractFromOrder(name);
  var codePos = widgetOrder.indexOf(code);  
  var codeLen = code.length;
  if (code.indexOf('~') == -1) {
    code = '~' + code;
  }
  widgetOrder = widgetOrder.substring(0, codePos) +
    code + widgetOrder.substring(codePos + codeLen);
  saveWidgetOrder();

  if (name == "customize") {
    hideCustomization();
  }
}

function showWidget(name) {
  document.getElementById(name).style.display = 'block';
  document.getElementById(name).parentNode.style.display = '';
  var showLabel = document.getElementById("show_" + name);
  if (showLabel) {
    showLabel.className = 'showhidden';
    showLabel.alt = "[Widget displayed]";
    showLabel.title = "Already displaying '" + widgetTitles[name] + "'";
  }
  rebalanceColumns();

  var code = extractFromOrder(name);
  var codePos = widgetOrder.indexOf(code);  
  var codeLen = code.length;
  var symbolPos = code.indexOf('~');
  if (symbolPos != -1) {
    code = code.substring(0, symbolPos) + code.substring(symbolPos + 1);
  }
  widgetOrder = widgetOrder.substring(0, codePos) +
    code + widgetOrder.substring(codePos + codeLen);

  saveWidgetOrder();
}

function minimizeWidget(name) {
  document.getElementById("body_" + name).style.display = 'none';
  document.getElementById("min_" + name).style.display = 'none';
  document.getElementById("max_" + name).style.display = 'inline';
  document.getElementById("header_" + name).style.cursor = 'pointer';
  document.getElementById("header_" + name).onclick = getExpandFunction(name);
  delayExpandFunction(name, 0);

  var code = extractFromOrder(name);
  var codePos = widgetOrder.indexOf(code);  
  var codeLen = code.length;
  if (code.indexOf('-') == -1) {
    code = '-' + code;
  }
  widgetOrder = widgetOrder.substring(0, codePos) +
    code + widgetOrder.substring(codePos + codeLen);

  saveWidgetOrder();
}

function maximizeWidget(name) {
  document.getElementById("body_" + name).style.display = 'block';
  document.getElementById("min_" + name).style.display = 'inline';
  document.getElementById("max_" + name).style.display = 'none';
  document.getElementById("header_" + name).style.cursor = 'auto';
  document.getElementById("header_" + name).onclick = '';

  var code = extractFromOrder(name);
  var codePos = widgetOrder.indexOf(code);  
  var codeLen = code.length;
  var minusPos = code.indexOf('-');
  if (minusPos != -1) {
    code = code.substring(0, minusPos) + code.substring(minusPos + 1);
  }
  widgetOrder = widgetOrder.substring(0, codePos) +
    code + widgetOrder.substring(codePos + codeLen);

  saveWidgetOrder();
}

function push(array, elt) {
  array[array.length] = elt;
}

function findNeighbor(object, tagname, delta) {
  var container = object.parentNode;

  var candidates = container.getElementsByTagName(tagname);
  var siblings = [];
  for (var i = 0; i < candidates.length; i++) {
    if (candidates[i].parentNode == container &&
        candidates[i].style.display != 'none') {
      //siblings.push(candidates[i]);
      push(siblings, candidates[i]);
    }
  }

  var objectPos;
  for (var i = 0; i < siblings.length; i++) {
    if (siblings[i] == object) {
      objectPos = i;
      break;
    }
  }

  var neighborPos = objectPos + delta;
  if (neighborPos >= 0 && neighborPos < siblings.length) {    
    return siblings[neighborPos];
  }  
}

function saveWidgetOrder() {
  document.cookie =
    'widgets=' + widgetOrder + '; expires=Tue, 19 Jan 2038 03:14:07 UTC; path=/'
}

function readWidgetOrderFromCookie() {
  var cookie = document.cookie;
  if (cookie.indexOf('widgets=~~~~~~') >= 0) {
    // Workaround for badly initialized cookies in initial distribution
    cookie = '';
  }
  var start = cookie.indexOf('; widgets=') + 10;
  if (start == 9) {
    var start = cookie.indexOf('widgets=') + 8;
  }
  if (start == 7) {
      return "HW^nrb|muo|a-dl-C";
      //return "HW^nul|mra~|-ob-C~";
  }

  var end = cookie.indexOf(';', start);
  if (end == -1) end = cookie.length;
  if (end - start < 2) {
    // Another attempted workaround, just in case.
      return "HW^nrb|muo|a-dl-C";
      //    return "HW^nul|mr~|-ob-C~";
  }

  // Insert the new "Member Discussions" widget into the bottom-right of
  // the page.
  var ans = cookie.substring(start, end);
  if (ans.indexOf('d') == -1) {
      ans = ans.replace('a', 'a-d');
  }

  return ans;
}

function resetWidgetOrder() {
    widgetOrder = //"HW^nul|mra~|-ob-C~";
  widgetOrder = "HW^nrb|muo|al-d-C";
  saveWidgetOrder();
  reorderWidgets(widgetOrder);
  hideCustomization();
}

function moveWidgetDown(name) {
  var code = extractFromOrder(name);
  var oldCodePos = widgetOrder.indexOf(code);  

  var widget = document.getElementById(name);
  var neighbor = findNeighbor(widget, "div", +2);

  if (neighbor) {
    var nextCode = extractFromOrder(neighbor.id);
    var nextPos = widgetOrder.indexOf(nextCode);
    widgetOrder = widgetOrder.substring(0, oldCodePos) +
        widgetOrder.substring(oldCodePos + code.length, nextPos) + 
        code +
        widgetOrder.substring(nextPos);     

    widget.parentNode.insertBefore(widget, neighbor);
  } else {
    var nextPos = widgetOrder.indexOf('|', oldCodePos);
    if (nextPos == -1) nextPos = widgetOrder.length;
    widgetOrder = widgetOrder.substring(0, oldCodePos) +
        widgetOrder.substring(oldCodePos + code.length, nextPos) + 
        code +
        widgetOrder.substring(nextPos);     

    widget.parentNode.appendChild(widget);
  }

  saveWidgetOrder();
}

function moveWidgetUp(name) {
  var code = extractFromOrder(name);
  var oldCodePos = widgetOrder.indexOf(code);  

  var widget = document.getElementById(name);
  var neighbor = findNeighbor(widget, "div", -1);

  if (neighbor) {
    var nextCode = extractFromOrder(neighbor.id);
    var nextPos = widgetOrder.indexOf(nextCode);
    widgetOrder = widgetOrder.substring(0, nextPos) +
        code +
        widgetOrder.substring(nextPos, oldCodePos) +
        widgetOrder.substring(oldCodePos + code.length);

    widget.parentNode.insertBefore(widget, neighbor);
  }

  saveWidgetOrder();
}

function moveWidgetRight(name) {
  var widget = document.getElementById(name);
  var column = widget.parentNode;
  var newColumn = findNeighbor(column, "td", +1);
  var needRebalance = false

  var code = extractFromOrder(name);
  var oldCodePos = widgetOrder.indexOf(code);  

  if (newColumn) {
    var nextCode = extractFromOrder(firstDiv(newColumn).id);
    var nextPos = widgetOrder.indexOf(nextCode);
    widgetOrder = widgetOrder.substring(0, oldCodePos) +
        widgetOrder.substring(oldCodePos + code.length, nextPos) + 
        code +
        widgetOrder.substring(nextPos);        

    newColumn.insertBefore(widget, newColumn.firstChild);
  } else {
    widgetOrder = widgetOrder.substring(0, oldCodePos) + 
        widgetOrder.substring(oldCodePos + code.length) +
        '|' + code;

    newColumn = document.createElement('td');
    column.parentNode.appendChild(newColumn);
    newColumn.appendChild(widget);
    needRebalance = true;
  }

  if (removeColumnIfEmpty(column)) {
    needRebalance = true;
  } else if (hideColumnIfInvisible(column)) {
    needRebalance = true;
  }
  if (needRebalance) {
    rebalanceColumns();
  }

  saveWidgetOrder();
}

function extractFromOrder(id) {
  var code = cookieNamesReverse[id];
  var end = widgetOrder.indexOf(code);
  var start = end;
  while ((start > 0) && 
      (widgetOrder.charAt(start-1) == '-' ||
       widgetOrder.charAt(start-1) == '~')) {
    start--;
  }
  var ans = widgetOrder.substring(start, end + 1);
  return ans;
}

function firstDiv(column) {
  return column.getElementsByTagName("div")[0];
}

function moveWidgetLeft(name) {
  var widget = document.getElementById(name);
  var column = widget.parentNode;
  var newColumn = findNeighbor(column, "td", -1);
  var needRebalance = false;

  var code = extractFromOrder(name);
  var oldCodePos = widgetOrder.indexOf(code);  

  if (newColumn) {
    var nextCode = extractFromOrder(firstDiv(newColumn).id);
    var nextPos = widgetOrder.indexOf(nextCode);
    widgetOrder = widgetOrder.substring(0, nextPos) +
        code +
        widgetOrder.substring(nextPos, oldCodePos) +
        widgetOrder.substring(oldCodePos + code.length);

    newColumn.insertBefore(widget, newColumn.firstChild);    
  } else {
    var start = widgetOrder.indexOf('^') + 1;
    widgetOrder = widgetOrder.substring(0, start) + 
        code + '|' + 
        widgetOrder.substring(start, oldCodePos) +
        widgetOrder.substring(oldCodePos + code.length);    

    newColumn = document.createElement('td');
    column.parentNode.insertBefore(newColumn, column.parentNode.firstChild);
    newColumn.appendChild(widget);
    needRebalance = true;
  }
  if (removeColumnIfEmpty(column)) {
    needRebalance = true;
  }
  if (needRebalance) {
    rebalanceColumns();
  } else if (hideColumnIfInvisible(column)) {
    needRebalance = true;
  }

  saveWidgetOrder();
}

function removeColumnIfEmpty(column) {
  var num = column.getElementsByTagName("div").length;
  if (column.getElementsByTagName("div").length == 0) {
    column.parentNode.removeChild(column);

    var pos = widgetOrder.indexOf("||");
    if (pos == -1) {
      pos = widgetOrder.indexOf("^|");
    }
    if (pos != -1) {
      widgetOrder = 
          widgetOrder.substring(0, pos + 1) + widgetOrder.substring(pos + 2);
    } else {
      widgetOrder = widgetOrder.substring(0, widgetOrder.length - 1);
    }

    return true;
  }
  return false;
}

function hideColumnIfInvisible(column) {
  var candidates = column.getElementsByTagName("div");
  for (var i = 0; i < candidates.length; i++) {
    var candidate = candidates[i];
    if (candidate.className == 'widget' && candidate.style.display != 'none') {
      return;
    }
  }
  column.style.display = 'none';
  rebalanceColumns();
}

function rebalanceColumns() {
  var cells = document.getElementById("mainRow").cells;
  var numTotal = cells.length;

  var numVisible = 0;
  var trailingHidden = 0;
  for (var i = 0; i < numTotal; i++) {
    if (cells[i].style.display != 'none') {
      numVisible++;
      trailingHidden = 0;
    } else {
      trailingHidden++;
    }
  }

  var header = document.getElementById("spanningRow");
  header.colSpan = numVisible; //numTotal - trailingHidden;

  var width = 100.0 / numVisible;  
  //alert(numVisible + " " + width);

  var numShown = 0;
  for (var i = 0; i < numTotal; i++) {
    var hereWidth = width;
    if (numVisible == 3 && cells[i].style.display != 'none') {
      numShown++;
      hereWidth += (numShown == 2) ? (8.0/3) : (-4.0/3);
    }
    cells[i].width = hereWidth + "%";
  }
}

var width = [0, 78, 147, 226, 295, 366, 423, 493, 557, 615, 680, 735];
var i;
var pos;


var images = [
  [
"images/AdventBelfryCrop.jpg",
"images/AtlantaRingingRoomWindow.jpg",
"images/BrewsterBelfry.jpg",
"images/MiamiTower.jpg",
"images/Phila---St-MartinRoof.jpg",
"images/QCTower.jpg",
"images/AdventLadder.jpg",
"images/FlyingPig.jpg",
"images/ONBells.jpg",
"images/QCTrebleCrop.jpg",
  ],
  [
"images/KzooRinging.jpg",
"images/MM_JS_I&MR.jpg",
"images/NR_DM_--_MM_--_MB.jpg",
"images/RF-MS-LK-MM.jpg",
"images/SG_BH_LW_TC.jpg",
"images/GrotonOuting.jpg",
"images/JW.jpg",
"images/KW.jpg",
"images/OH.jpg",
"images/Sitting-Out.jpg",
  ]
]


cookieNamesReverse = new Object();
cookieNamesReverse['BANNER'] = 'H';
cookieNamesReverse['whatIsRinging'] = 'W';
cookieNamesReverse['map'] = 'm';
cookieNamesReverse['upcoming'] = 'u';
cookieNamesReverse['recent'] = 'r';
cookieNamesReverse['clapper'] = 'l';
cookieNamesReverse['news'] = 'n';
cookieNamesReverse['resources'] = 'o';
cookieNamesReverse['customize'] = 'C';
cookieNamesReverse['books'] = 'b';
cookieNamesReverse['articles'] = 'a';
cookieNamesReverse['discuss'] = 'd';

cookieNames = new Object();
cookieNames['a'] = 'articles';
cookieNames['b'] = 'books';
cookieNames['m'] = 'map';
cookieNames['n'] = 'news';
cookieNames['o'] = 'resources';
cookieNames['C'] = 'customize';
cookieNames['r'] = 'recent';
cookieNames['l'] = 'clapper';
cookieNames['u'] = 'upcoming';
cookieNames['W'] = 'whatIsRinging';
cookieNames['d'] = 'discuss';

widgetTitles = new Object();
widgetTitles['articles'] = 'Articles';
widgetTitles['books'] = 'Highlights from Our Store';
widgetTitles['map'] = 'Find Ringing Near You';
widgetTitles['news'] = 'Announcements' 
widgetTitles['resources'] = 'Resources & Links';
widgetTitles['customize'] = 'Customize This Page';
widgetTitles['recent'] = 'Recent Reports';
widgetTitles['clapper'] = 'The Clapper';
widgetTitles['upcoming'] = 'Calendar of Events';
widgetTitles['whatIsRinging'] = "Change Ringing? What's that?";
widgetTitles['discuss'] = 'Member Discussions';

widgetOrder = "";

function reorderWidgets(order) {
  widgetOrder = order;
  var N = order.length;

  var container = document.getElementById("mainRow");
  var columns = document.getElementById("mainRow").cells;
  var currCol = 0;
  
  var minimizeNext = false;
  var hideNext = false;

  for (var i = 0; i < N; i++) {
    var code = order.charAt(i);
    if (code == '|') {
      currCol++;
      if (currCol >= columns.length) {
        newColumn = document.createElement('td');
        container.appendChild(newColumn);
      }
    } else if (code == '-') {
      minimizeNext = true;
    } else if (code == '~') {
      hideNext = true;
    } else if (code == '^') {
      // Just a marker for the start of the non-header stuff.
    } else if (code == 'H') {
      if (hideNext) {
        hideBanner();
        hideNext = false;
      } else {
        showBanner();
      }
    } else {
      var id = cookieNames[code];
      //alert(code + " " + id + " " + hideNext);
      if (minimizeNext) {
        minimizeWidget(id);
        delayExpandFunction(id, 1);  // Tell it not to skip the first "click"
        minimizeNext = false;
      } else {
          //alert(code + ": " + id);
        maximizeWidget(id);
      }
      if (hideNext) {
        hideWidget(id);
        hideNext = false;
      } else {
        showWidget(id);
        document.getElementById(id).parentNode.style.display = '';
      }

      if (code != 'W') {
        var widget = document.getElementById(id);
        columns[currCol].appendChild(widget);
      }
    }
  }

  for (code in cookieNames) {
    if (order.indexOf(code) == -1) {
      // Move the widget to the end, then hide it.
      var id = cookieNames[code];
      if (code != 'W') {
        var widget = document.getElementById(id);
        columns[currCol].appendChild(widget);
        columns[currCol].style.display='';
      }
      hideWidget(id);
    }
  }

  for (var i = 0; i < columns.length; i++) {
    //if (!removeColumnIfEmpty(columns[i])) {
      hideColumnIfInvisible(columns[i]);
    //}
  }

  rebalanceColumns();
}

function rotateBanner(name, index) {
  //alert("B " + name);
  var oldImage = document.getElementById(name + bannerPos[index]);

  bannerPos[index]++;
  if (bannerPos[index] >= images[index].length) bannerPos[index] = 0;
  var newImage = document.getElementById(name + bannerPos[index]);

  newImage.style.display = '';
  oldImage.style.display = 'none';


  //img.src = images[index][bannerPos[index]];



  //alert("rotateBanner('" + name + "', " + index + ")");
  setTimeout("rotateBanner('" + name + "', " + index + ")", 16000);
  //setTimeout("rotateBanner('bannerRight', 1)", 8000);
}

function hookUpIcons() {
  var images = document.images;
  for (var i = 0; i < images.length; i++) {
    var icon = images[i];
    var className = icon.className;
    if (className.indexOf("icon ") == 0) {
      var action = className.substr(5);
      var header = icon;
      while (header.className.indexOf("widget") == -1) {
        header = header.parentNode;
      }
      var target = header.id;
      icon.onclick = curry(iconFunctions[action], target);
      icon.style.visibility = 'visible';
    }
  }
}

expandFunctions = new Object();
expandDelayFunctions = new Object();

function getExpandFunction(name) {
  var ans = expandFunctions[name];
  if (ans == undefined) {
    initMaximizeFunctions(name);
    ans = expandFunctions[name];
  }
  return ans;
}
function delayExpandFunction(name, x) {
  var ans = expandDelayFunctions[name];
  if (ans == undefined) {
    initMaximizeFunctions(name);
    ans = expandDelayFunctions[name];
  }
  ans.call(this, x);
}
function initMaximizeFunctions(name) {
  var counter = 1;
  expandDelayFunctions[name] = function(x) {
    if (x == undefined) {
      counter = 0;
    } else {
      counter = x;
    }
    //alert("Delay " + name + " " + x + " -> " + counter);
  }
  expandFunctions[name] = function() {
    //alert("Expand " + name + "? " + counter);
    if (counter == 1) {
      maximizeWidget(name);
    } else {
       counter = 1;
    }
  };
}

function curry(func, msg) {
  return function() {
    func.call(this, msg);
  }
}

// TODO: This is a total and complete hack. (But thanks, 6.001!)
function curryIgnoreOnce(func, msg) {
  var counter = 0;
  return function() {
    if (counter == 1) {
      func.call(this, msg);
    } 
    counter++;
  }
}


iconFunctions = new Object();
iconFunctions["min"] = minimizeWidget;
iconFunctions["max"] = maximizeWidget;
iconFunctions["left"] = moveWidgetLeft;
iconFunctions["right"] = moveWidgetRight;
iconFunctions["up"] = moveWidgetUp;
iconFunctions["down"] = moveWidgetDown;
iconFunctions["close"] = hideWidget;


function changeBannerLogo(name) {
  var logo = document.getElementById("bannerLogo");
  logo.src = name;
}
