var usingApplet = false;

var maxFeeds = 1;
var feedsSelected = 1;
var lastSelect = 1;
var lastSlot = 1;
var lastFeed = 1;
var lastWasUnselect = false;
var expired = false;
var appletRunning = false;
var setUpJS = true;
var appletSafe = false;
var title = "";

var cQual = 2;
var cZoom = 3;

//if (forcequality != -1)
//  cQual = forcequality;

var feedSelected = new Array();
var feedSlots = new Array();

var imageTimerID = 0;

// Select the default feed
for (var index = 0; index < feeds.length; index++) {
  if (feeds[index].id == defaultFeed) {
    feedSelected[index] = 1;
    feedSlots[index] = 1;
  } else {
    feedSelected[index] = 0;
    feedSlots[index] = -1;
  }
}

var qualitySetting = 0;

var cookieQuality;
var useQuality = cQual;

cookieQuality = getCookie("quality");

if (cookieQuality != null)
  useQuality = cookieQuality;

if (forcequality != -1)
  useQuality = forcequality;

var viewmode = 0;
var cookieViewmode;

cookieViewmode = getCookie("viewmode");

if (cookieViewmode != null) {
  if (cookieViewmode == 1)
    viewmode = 1;
  else
    viewmode = 0;
}

if (forceviewmode != -1) {
  if (forceviewmode == 1) {
    userPref = autoviewmode || confirm("You have forced the i-Catcher web view to use JavaScript mode. This is usually only\nnecessary if you are experiencing problems with the Java applet.\n\nClick OK to make this change permanent (affects this machine only).");
    if (userPref)
      setCookie("viewmode", 1);
  } else {
    userPref = autoviewmode || confirm("You have forced the i-Catcher web view to use Java mode.\n\nClick OK to make this change permanent (affects this machine only).");
    if (userPref)
      setCookie("viewmode", 2);
  }

  viewmode = forceviewmode;
}

if (viewmode > 1)
  viewmode = 0;

if (viewmode < 1)
  usingApplet = true;

// vars below here are used only for the javascript emulation of the feeds
var tempSlot = ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''];
var realSlot = ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''];

var lastUpdate = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
var feedStatus = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];

// Setup the offscreen image
var slotImages = new Array();
for (var index = 1; index <= 16; index++) {
  slotImages[index] = new Image();
  slotImages[index].name = 'cache' + index;
  slotImages[index].onload = imageLoaded;
  slotImages[index].onerror = imageLoaded;
}

var slotIDs = ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''];

slotIDs[0] = defaultFeed;

var currentLayout = 1;
var zoomMultiplier = 1.0;

var cWidth1 = 1;
var cHeight1 = 1;

// Preloaders:
// standard parts
preload('scale1.gif');
preload('scale2.gif');

// Live feeds
if (allowMultiview) {
  preload('layout.gif');
} else {
  preload('layoutdis.gif');
}



/*****************
* Initialisation *
*****************/
// Called on page load to set everything up
function postLoad() {
  title = document.title;
  if (!allowMultiview)
    disableViewControls();

  if (!allowZooming)
    disableZoomControls();

  if (duration > 0)
    window.setTimeout("expireInc()", 1000);

  document.getElementById('liveLink').href = '/?feed=' + defaultFeed;
  document.getElementById('playLink').href = '/playback/?feed=' + defaultFeed;
  document.getElementById('motionLink').href = '/motionmap.htm?feed=' + defaultFeed;

  writeLayout();

  if (viewmode != 1) {
    setUpJS = false;
  }

  if ((!usingApplet) && (setUpJS)) {
    realSlot[0] = defaultFeed;
    tempSlot[0] = defaultFeed;

    imageTimerID = window.setTimeout("imageTimer()", 50);
  }

  enablePTZControls(currentFeedIndex());

  setQual(useQuality);
  // Update the sensor list
  updateIOInfo();

  if (viewmode >= 0)
    document.viewselect.viewer[1 - viewmode].checked = true;
  else
    document.viewselect.viewer[1].checked = true;

  modeSetLockout = false;

  //Show the Gadget block unless a cookie says otherwise
  initGadgetBlock();

  //Set up the drag handler for the PTZ preset and sensor panel
  document.onmousedown = dragMouseDown;

  presetsCreepTimerID = window.setTimeout("creepPresets()", 5000);
  sensorsCreepTimerID = window.setTimeout("creepSensors()", 5000);
}

// Called when the applet has finished starting up so we know it can be used
function appletInited() {
  appletSafe = true;
  requestNewResolution(320, 240);

  // Set the initial applet PTZ capabilities
  if (currentLayout == 1) {
    var feedIndex = currentFeedIndex();
    if (feedIndex > -1) {
      var feed = feeds[feedIndex];
      document.MJPGApplet.setSlot(1, feed.id, feed.ptz);
    }
  }
}

// Called after the sliders have been set up so we can set the slider position
function sliderPostLoad() {
  setSlider(2, useQuality);
}

function checkApplet() {
  return appletSafe;
}



/***********************
* JavaScript emulation *
***********************/
var throttleCount = 0;
var throttling = true;

function feedMark(slotIndex1) {
  feedStatus[slotIndex1 - 1] = 0;
}

function imageLoaded() {
  var slotIndex = parseInt(this.name.substring(5));

  now = getMillis();

  var slotImage = document.getElementById('image' + slotIndex);
  if (slotImage != null) {
    slotImage.src = this.src;

    // Update the tooltips for the images
    if (currentLayout > 1) {
      // Get the feed that matches the ID that is in this slot
      for (var index = 0; index < feeds.length; index++) {
        if (feeds[index].id == slotIDs[slotIndex - 1]) {
          slotImage.alt = 'Click to view just the "' + feeds[index].name + '" feed.';
          slotImage.title = 'Click to view just the "' + feeds[index].name + '" feed.';
        }
      }
    } else {
      slotImage.alt = '';
      slotImage.title = '';
    }

    if (currentLayout == 1) {
      if ((this.width != cWidth1) || (this.height != cHeight1)) {
        requestNewResolution(this.width * zoomMultiplier, this.height * zoomMultiplier);
        cWidth1 = this.width;
        cHeight1 = this.height;
      }
    }
  }

  lastUpdate[slotIndex - 1] = now;
  feedStatus[slotIndex - 1] = 0;
}

function killImageTimer() {
  if (imageTimerID != 0)
    window.clearTimeout(imageTimerID);

  imageTimerID = 0;
}

function imageTimer() {
  imageTimerID = 0;

  if ((usingApplet) || (expired))
    return;

  now = getMillis();

  for (var index = 0; index < maxFeeds; index++) {
    diff = now - lastUpdate[index];

    if ((realSlot[index] != '') && (feedStatus[index] == 0) && (diff > 50)) {
      feedStatus[index] = 1;

      qs = '';
      if (qualitySetting > 0)
        qs = '&quality=' + qualitySetting;

      slotImages[index + 1].src = '/image.jpg?feed=' + realSlot[index] + qs + '&uniq=' + now;
    }
  }

  if (throttling) {
    throttleCount += 500;

    if (throttleCount >= 30000)
      throttling = false;
  }

  if (throttling)
    imageTimerID = window.setTimeout("imageTimer()", 500);
  else
    imageTimerID = window.setTimeout("imageTimer()", 30);

}

function slotSource(slot) {
  if (realSlot[slot - 1] != '')
    return '/image.jpg?feed=' + realSlot[slot - 1] + '&quality=' + qualitySetting + '&uniq=' + lastUpdate[slot - 1];
  else
    return '/status/pleasewait.gif';
}



/************
* View mode *
************/
var modeSetLockout = true;

// Change to the selected mode
function selectMode(mode) {
  if (modeSetLockout)
    return;

  if (mode != viewmode) {
    location.href = '/index.htm?feed=' + playFeed + '&mode=' + mode;
  }
}



/************
* Feed list *
************/
function printFeedList() {
  for (var index = 0; index < feeds.length; index++) {
    tc = 'unselected';
    if (feeds[index].id == defaultFeed)
      tc = 'selected';

    document.write('<tr><td id="listitem' + (index + 1) + '" onClick="enterFeed(' + (index + 1) + ',1);" class="' + tc + '">');
    // The name doesn't need to be encoded here as the it is pre encoded in the JavaScript"
    document.write('<p class="item">' + feeds[index].name + '</p></td></tr>');
  }
}

$(document).ready(function() {
  $("#feedcountlabel").text(feeds.length);

  // Add the mouseover handlers for the feed list items
  $(".itemlist td").each(function(index) {
    $(this).mouseenter(function() { $(this).addClass("hover"); });
    $(this).mouseleave(function() { $(this).removeClass("hover"); });
  });

  // Set the height to a maximum of 188 pixels (11 items)
  // The initial size is set in the HTML
  var container = document.getElementById("itemlistcontainer");
  var divHeight = container.scrollHeight;
  if (divHeight > 188) { divHeight = 188; }
  container.style.height = divHeight;
});



/*********************
* Feed/slot handling *
*********************/
function jumpSlot(slotIndex) {
  // This needs to be done first as viewSelect clears the slotIDs
  var feedID = slotIDs[slotIndex - 1];

  viewSelect(0);

  var feedIndex = feedIndexFromID(feedID)
  enterFeed(feedIndex + 1, 1);
}

function enterFeed(feedIndex, commit) {
  expireTime = 0;

  if (cView == 0) { // Single view
    // Unselect any currently selected feeds
    for (var index = 0; index < feeds.length; index++) {
      if (feedSelected[index]) {
        $('#listitem' + (index + 1)).removeClass("selected");

        feedSelected[index] = 0;
        feedSlots[index] = -1;
      }
    }

    // Kill all the slots
    for (var index = 2; index <= 16; index++)
      killSlot(index);

    feedsSelected = 0;
    lastSlot = 1;
  }

  if ((commit == 1) && (lastWasUnselect) && (feedSelected[feedIndex - 1])) {
    feedSelected[lastSelect - 1] = 1;
    $('#listitem' + lastSelect).addClass("selected");
    feedsSelected++;
    feedSlots[lastSelect - 1] = lastSlot;
  }

  if ((feedsSelected <= maxFeeds) && (feedSelected[feedIndex - 1] == 1)) {
    feedSelected[feedIndex - 1] = 0;
    feedsSelected--;
    lastSlot = feedSlots[feedIndex - 1];
    feedSlots[feedIndex - 1] = -1;
  } else if ((feedsSelected < maxFeeds) && (feedSelected[feedIndex - 1] == 0)) {
    feedSelected[feedIndex - 1] = 1;
    feedsSelected++;
  } else if (feedsSelected > maxFeeds) {
    feedSelected[feedIndex - 1] = 0;
    feedsSelected--;
  } else if ((feedsSelected == maxFeeds) && (feedSelected[feedIndex - 1] == 0)) {
    return;
  }

  if (feedSelected[feedIndex - 1]) {
    $('#listitem' + feedIndex).addClass("selected");
    setSlot(lastSlot, feeds[feedIndex - 1].id);

    if (currentLayout == 1)
      enablePTZControls(feedIndex - 1);

    // Update the sensor list
    updateIOInfo();

    feedSlots[feedIndex - 1] = lastSlot;

    lastWasUnselect = false;

    playFeed = feeds[feedIndex - 1].id;

    document.title = title + " - " + feeds[feedIndex - 1].name;
    document.getElementById('liveLink').href = '/?feed=' + playFeed;
    document.getElementById('playLink').href = '/playback/?feed=' + playFeed;
    document.getElementById('motionLink').href = '/motionmap.htm?feed=' + playFeed;

    lastFeed = feedIndex;

  } else {

    $('#listitem' + feedIndex).removeClass("selected");

    feedSlots[feedIndex - 1] = -1;

    lastWasUnselect = true;
    lastSelect = feedIndex;

  }

  if (commit)
    commitSlots();
}

function setSlot(slot, feedID) {
  if (usingApplet) {
    ptz = feeds[feedIndexFromID(feedID)].ptz;
    if (checkApplet())
      document.MJPGApplet.setSlot(slot, feedID, ptz);
  } else {
    tempSlot[slot - 1] = feedID;
  }
  slotIDs[slot - 1] = feedID;
}

function killSlot(slot) {
  if (usingApplet) {
    if (checkApplet())
      document.MJPGApplet.killSlot(slot);
  } else {
    tempSlot[slot - 1] = '';
  }
  slotIDs[slot - 1] = '';
}

function commitSlots() {
  if (usingApplet) {
    if (checkApplet())
      document.MJPGApplet.commitSlots();
  } else {
    for (var index = 0; index < 16; index++) {
      realSlot[index] = tempSlot[index];
    }
  }
}

function getNextSlot() {
  if (lastSlot > 16)
    return;

  if (lastSlot == -1)
    lastSlot = 0;

  for (var index = lastSlot; index < 16; index++) {
    if (slotIDs[index] == '') {
      lastSlot = index + 1;
      return;
    }
  }
}

// Return the current feeds index in the list and its ID
function currentFeedIndex() {
  if (currentLayout == 1) {
    for (var index = 0; index < feeds.length; index++) {
      if (feedSelected[index])
        return index;
    }
  }
  return -1;
}

function currentFeedID() {
  try {
    return feeds[currentFeedIndex()].id;
  } catch(ex) {
    return "";
  }
}

function feedIndexFromID(feedID) {
  for (var index = 0; index < feeds.length; index++) {
    if (feeds[index].id == feedID)
      return index;
  }
  return 0
}



/*****************
* Layout control *
*****************/
var cView = 0;
var viewIcons = ['view1', 'view4', 'view9', 'view16', 'viewfocused', 'viewcentral'];

// Disable the view controls if it is disabled in the Console
function disableViewControls() {
  $('#displayGrid').addClass('disabled');
  $('#displayGrid .icon').not("#view1").addClass('disabled');
}

$(document).ready(function() {
  // Add the mouseover handlers for the display icons
  $("#displayGrid .icon").each(function(index) {
    $(this).mouseenter(function() {
      if (allowMultiview) {
        $(this).addClass("hover");
      }
    });
    $(this).mouseleave(function() { $(this).removeClass("hover"); });
  });
});

// Handle switching between single and grouped views
function viewSelect(view) {
  if (!allowMultiview)
    return;

  $("#" + viewIcons[cView]).removeClass("selected");
  $("#" + viewIcons[view]).addClass("selected");

  cView = view;

  oMaxFeeds = maxFeeds;

  if (cView == 0) maxFeeds = 1;
  if (cView == 1) maxFeeds = 4;
  if (cView == 2) maxFeeds = 9;
  if (cView == 3) maxFeeds = 16;
  if (cView == 4) maxFeeds = 6;
  if (cView == 5) maxFeeds = 13;

  setLayout(cView + 1);

  if (cView == 0) {
    enterFeed(lastFeed, 1);

    lastWasUnselect = false;
    lastSelect = -1;
    lastSlot = -1;

    return;
  }

  lastSlot = 0;

  if (maxFeeds > oMaxFeeds) {
    // Select new feeds to fill the gaps
    for (var index = 0; index < feeds.length; index++) {
      if ((feedSelected[index] == 0) && (feedsSelected < maxFeeds)) {
        getNextSlot();
        enterFeed(index + 1, 0);
      }
    }
  } else {
    // Unselect enough feeds
    for (var index = 0; index < feeds.length; index++) {
      if ((feedSelected[index] == 1) && (feedSlots[index] > maxFeeds)) {
        enterFeed(index + 1, 0);
      }
    }

    for (var index = maxFeeds; index < oMaxFeeds; index++) {
      killSlot(index + 1);
    }
  }

  lastWasUnselect = false;
  lastSelect = -1;
  lastSlot = -1;

  commitSlots();

  if (currentLayout == 1) {
    enablePTZControls(currentFeedIndex());
  } else {
    enablePTZControls(0);
  }
  // Update the sensor list
  updateIOInfo();
}

// Notify the relevant objects
function setLayout(newView) {
  if (usingApplet) {
    if (checkApplet())
      document.MJPGApplet.setLayout(newView);
    currentLayout = newView;
  } else {
    killImageTimer();
    currentLayout = newView;
    writeLayout();

    // Reset all the image states and handlers
    for (var index = 0; index < 16; index++) {
      feedStatus[index] = 0;
      lastUpdate[index] = 0;
      slotImages[index + 1].onload = imageLoaded;
      slotImages[index + 1].onerror = imageLoaded;
    }

    imageTimerID = window.setTimeout("imageTimer()", 50);
  }
}

// Output suitable HTML for the current mode/view
function writeLayout() {
  var lhtml = '';

  for (var index = 0; index < 16; index++) {
    feedStatus[index] = 1;
  }

  if (!usingApplet) {
    var cl = currentLayout;
    var z = zoomMultiplier;

    if (currentLayout == 1) {
      lhtml = lhtml + '<table cellpadding="0" cellspacing="0" border="0"><tr><td>';
      lhtml = lhtml + '<img src="' + slotSource(1) + '" id="image1" name="image1" onLoad="feedMark(1);">';
      lhtml = lhtml + '</td><td>';
      lhtml = lhtml + '<img src="" id="tiltimage" name="tiltimage" onclick="tiltscrollclick(event);" style="display: none;" height="0" width="0" alt="">';
      lhtml = lhtml + '</td></tr><tr><td valign="top">';
      lhtml = lhtml + '<img src="" id="panimage" name="panimage" onclick="panscrollclick(event);" style="display: none;" height="0" width="0" alt="">';
      lhtml = lhtml + '</td><td></td></tr></table>';
    }

    if ((currentLayout >= 2) && (currentLayout <= 4)) { // grid view
      var widths = [0, 0, 192, 170, 160];
      var heights = [0, 0, 144, 128, 120];
      var slotIndex = 1;

      lhtml = lhtml + '<table cellpadding="0" cellspacing="0" border="0">';

      for (var row = 0; row < currentLayout; row++) {
        lhtml = lhtml + '<tr>';

        for (var col = 0; col < currentLayout; col++) {
          lhtml = lhtml + '<td>';
          lhtml = lhtml + '<img src="' + slotSource(slotIndex) + '" width="' + (widths[cl] * z) + '" height="' + (heights[cl] * z) + '" id="image' + slotIndex + '" name="image' + slotIndex + '" onLoad="feedMark(' + slotIndex + ');" onClick="jumpSlot(' + slotIndex + ');">';
          lhtml = lhtml + '</td>';
          slotIndex++;
        }

        lhtml = lhtml + '</tr>';
      }

      lhtml = lhtml + '</table>';
    }

    if (currentLayout == 5) { // focused view
      lhtml = lhtml + '<table cellpadding="0" cellspacing="0" border="0"><tr>';
      lhtml = lhtml + '<td rowspan="2" colspan="2"><img src="' + slotSource(1) + '" id="image1" name="image1" width="' + (340 * z) + '" height="' + (256 * z) + '" onLoad="feedMark(1);" onClick="jumpSlot(1);"></td>';
      lhtml = lhtml + '<td><img src="' + slotSource(2) + '" id="image2" name="image2" width="' + (170 * z) + '" height="' + (128 * z) + '" onLoad="feedMark(2);" onClick="jumpSlot(2);"></td></tr>';
      lhtml = lhtml + '<tr><td><img src="' + slotSource(3) + '" id="image3" name="image3" width="' + (170 * z) + '" height="' + (128 * z) + '" onLoad="feedMark(3);" onClick="jumpSlot(3);"></td></tr>';
      lhtml = lhtml + '<tr><td><img src="' + slotSource(4) + '" id="image4" name="image4" width="' + (170 * z) + '" height="' + (128 * z) + '" onLoad="feedMark(4); onClick="jumpSlot(4);""></td>';
      lhtml = lhtml + '<td><img src="' + slotSource(5) + '" id="image5" name="image5" width="' + (170 * z) + '" height="' + (128 * z) + '" onLoad="feedMark(5); onClick="jumpSlot(5);""></td>';
      lhtml = lhtml + '<td><img src="' + slotSource(6) + '" id="image6" name="image6" width="' + (170 * z) + '" height="' + (128 * z) + '" onLoad="feedMark(6); onClick="jumpSlot(6);""></td></tr>';
      lhtml = lhtml + '</table>';
    }

    if (currentLayout == 6) { // central view
      lhtml = lhtml + '<table cellpadding="0" cellspacing="0" border="0"><tr>';
      // Top line
      lhtml = lhtml + '<td><img src="' + slotSource(1) + '" id="image1" name="image1" width="' + (192 * z) + '" height="' + (144 * z) + '" onLoad="feedMark(1);" onClick="jumpSlot(1);"></td>';
      lhtml = lhtml + '<td><img src="' + slotSource(2) + '" id="image2" name="image2" width="' + (192 * z) + '" height="' + (144 * z) + '" onLoad="feedMark(2);" onClick="jumpSlot(2);"></td>';
      lhtml = lhtml + '<td><img src="' + slotSource(3) + '" id="image3" name="image3" width="' + (192 * z) + '" height="' + (144 * z) + '" onLoad="feedMark(3);" onClick="jumpSlot(3);"></td>';
      lhtml = lhtml + '<td><img src="' + slotSource(4) + '" id="image4" name="image4" width="' + (192 * z) + '" height="' + (144 * z) + '" onLoad="feedMark(4);" onClick="jumpSlot(4);"></td></tr>';

      // Middle set
      lhtml = lhtml + '<td><img src="' + slotSource(5) + '" id="image5" name="image5" width="' + (192 * z) + '" height="' + (144 * z) + '" onLoad="feedMark(5);" onClick="jumpSlot(5);"></td>';
      lhtml = lhtml + '<td colspan="2" rowspan="2"><img src="' + slotSource(6) + '" id="image6" name="image6" width="' + (384 * z) + '" height="' + (288 * z) + '" onLoad="feedMark(6);" onClick="jumpSlot(6);"></td>';
      lhtml = lhtml + '<td><img src="' + slotSource(7) + '" id="image7" name="image7" width="' + (192 * z) + '" height="' + (144 * z) + '" onLoad="feedMark(7);" onClick="jumpSlot(7);"></td></tr>';

      // Middle set follower
      lhtml = lhtml + '<td><img src="' + slotSource(8) + '" id="image8" name="image8" width="' + (192 * z) + '" height="' + (144 * z) + '" onLoad="feedMark(8);" onClick="jumpSlot(8);"></td>';
      lhtml = lhtml + '<td><img src="' + slotSource(9) + '" id="image9" name="image9" width="' + (192 * z) + '" height="' + (144 * z) + '" onLoad="feedMark(9);" onClick="jumpSlot(9);"></td></tr>';

      // Bottom row
      lhtml = lhtml + '<td><img src="' + slotSource(10) + '" id="iamge10" name="image10" width="' + (192 * z) + '" height="' + (144 * z) + '" onLoad="feedMark(10);" onClick="jumpSlot(10);"></td>';
      lhtml = lhtml + '<td><img src="' + slotSource(11) + '" id="image11" name="image11" width="' + (192 * z) + '" height="' + (144 * z) + '" onLoad="feedMark(11);" onClick="jumpSlot(11);"></td>';
      lhtml = lhtml + '<td><img src="' + slotSource(12) + '" id="image12" name="image12" width="' + (192 * z) + '" height="' + (144 * z) + '" onLoad="feedMark(12);" onClick="jumpSlot(12);"></td>';
      lhtml = lhtml + '<td><img src="' + slotSource(13) + '" id="image13" name="image13" width="' + (192 * z) + '" height="' + (144 * z) + '" onLoad="feedMark(13);" onClick="jumpSlot(13);"></td></tr>';

      lhtml = lhtml + '</table>';
    }

    writeLayoutHTML(lhtml);
  }
}

function writeLayoutHTML(sText) {
  if (document.getElementById) {
    document.getElementById('feedPanel').innerHTML = sText;
  } else {
    var oLayer;

    oLayer = document.layers['feedPanel'].document;

    oLayer.open();
    oLayer.write(sText);
    oLayer.close();
  }
}

// Handle resize notifications from the applet or other code
function requestNewResolution(newWidth, newHeight) {
  if (usingApplet) {
    if (checkApplet()) {
      document.MJPGApplet.width = newWidth;
      document.MJPGApplet.height = newHeight;
    }
  } else {
    var mainImage = document.getElementById('image1');
    if (currentLayout == 1) {
      if (mainImage != null) {
        mainImage.width = newWidth;
        mainImage.height = newHeight;
      }
    }
  }

  if (currentLayout == 1) {
    enablePTZControls(currentFeedIndex());
  }

  // Resize the preset and sensor panels
  sizePresetPanel();
  sizeSensorPanel();

  // Resize the Gadget text (limited to 300px wide)
  document.getElementById('gadgetblock').style["width"] = (newWidth < 300 ? 300 : newWidth);
}



/****************
* Image options *
****************/
// Disable the size controls if they are disabled in the Console
function disableZoomControls() {
  document.getElementById('izo').className = 'adjTextDis';
  document.getElementById('izi').className = 'adjTextDis';
  document.getElementById('slider01').className = 'sliderd';
  document.getElementById('zslider').src = '/images/scale2d.gif';
  document.getElementById('zoomtext').className = 'icontrolsd';
}

// Slider state information
var slider = new Array();
slider[1] = new Object();
slider[1].min = 1;
slider[1].max = 5;
slider[1].val = 3;
slider[1].onchange = sliderChangeCallback;

slider[2] = new Object();
slider[2].min = 1;
slider[2].max = 5;
slider[2].val = 3;
slider[2].onchange = sliderChangeCallback;

// Callback to "do our stuff"
function sliderChangeCallback(val, slider) {
  if (slider == 1)
    setZoomL(Math.floor(val + 0.5));
  if (slider == 2)
    setQual(Math.floor(val + 0.5));
}

// Up/down handler
function adjustZoom(offset) {
  newZoom = eval(cZoom + '+' + offset);
  if (newZoom < 1) newZoom = 1;
  if (newZoom > 5) newZoom = 5;
  setSlider(1, newZoom);
  setZoomL(newZoom);
}

// Take the new value from code, no need to update the slider
function setZoomL(newZoom) {
  if (!allowZooming)
    return;

  cZoom = newZoom;
  notifyZoom(newZoom);
}

// Change the zoom level
function notifyZoom(zoomLevel) {
  if (usingApplet) {
    if (checkApplet())
      document.MJPGApplet.setZoom(zoomLevel);
  } else {
    if (zoomLevel == 1)
      zoomMultiplier = 0.25;
    if (zoomLevel == 2)
      zoomMultiplier = 0.5;
    if (zoomLevel == 3)
      zoomMultiplier = 1.0;
    if (zoomLevel == 4)
      zoomMultiplier = 2.0;
    if (zoomLevel == 5)
      zoomMultiplier = 4.0;

    if (currentLayout == 1)
      requestNewResolution(slotImages[1].width * zoomMultiplier, slotImages[1].height * zoomMultiplier);

    if ((currentLayout >= 2) && (currentLayout <= 4)) {
      var widths = [0, 192, 170, 160];
      var heights = [0, 144, 128, 120];

      // Resize each image segment as needed
      for (var index = 1; index <= maxFeeds; index++) {
        var slotImage = document.getElementById('image' + index);
        if (slotImage != null) {
          slotImage.width = widths[currentLayout] * zoomMultiplier;
          slotImage.height = heights[currentLayout] * zoomMultiplier;
        }
      }
    }

    if (currentLayout == 5) {

      // Resize the main image segment as needed
      slotImage = document.getElementById('image1');
      if (slotImage != null) {
        slotImage.width = 340 * zoomMultiplier;
        slotImage.height = 256 * zoomMultiplier;
      }

      // Resize the rest as needed
      for (var index = 2; index <= maxFeeds; index++) {
        slotImage = document.getElementById('image' + index);
        if (slotImage != null) {
          slotImage.width = 170 * zoomMultiplier;
          slotImage.height = 128 * zoomMultiplier;
        }
      }
    }

    if (currentLayout == 6) {

      // Resize the main image segment as needed
      slotImage = document.getElementById('image6');
      if (slotImage != null) {
        slotImage.width = 320 * zoomMultiplier;
        slotImage.height = 240 * zoomMultiplier;
      }

      // Resize the rest as needed
      for (var index = 1; index <= maxFeeds; index++) {
        slotImage = document.getElementById('image' + index);
        if ((slotImage != null) && (index != 6)) {
          slotImage.width = 160 * zoomMultiplier;
          slotImage.height = 120 * zoomMultiplier;
        }
      }
    }

  }
}

// Up/down handler
function adjustQual(offset) {
  // Richard thinks he used eval here due to variable typing problems
  newQuality = eval(cQual + '+' + offset);
  if (newQuality < 1) newQuality = 1;
  if (newQuality > 5) newQuality = 5;
  setSlider(2, newQuality);
  setQual(newQuality);
}

// Take the new value from code, updating the slider
function setQual(newQuality) {
  setQualSlider(newQuality, 1);
}

// Take the new value from code, optionally update the slider
function setQualSlider(newQuality, commit) {
  cQual = newQuality;
  setCookie("quality", newQuality);
  if (commit == 1)
    notifyQual(newQuality);
}

// Change the quality level
function notifyQual(qualLevel) {
  if (usingApplet) {
    if (checkApplet())
      document.MJPGApplet.setQuality(qualLevel);
  } else {
    if (qualLevel == 1)
      qualitySetting = 15;
    if (qualLevel == 2)
      qualitySetting = 25;
    if (qualLevel == 3)
      qualitySetting = 50;
    if (qualLevel == 4)
      qualitySetting = 75;
    if (qualLevel == 5)
      qualitySetting = 0;
  }
}



/******************
* Expiry handling *
******************/
var expireTime = 0;

function expireTimer() {
  expired = true;

  if (usingApplet) {
    document.MJPGApplet.notifyInvalidSession();
  } else {
    viewSelect(0);

    if (!allowMultiview)
      writeLayout();

    // Update the view image
    mainImage = document.getElementById('image1');
    mainImage.src = '/status/expired.gif';
    mainImage.width = 352;
    mainImage.height = 288;
  }

  // Hide the gradient control
  pi = document.getElementById('panimage');
  if (pi != null) { pi.style.display = "none"; }
  ti = document.getElementById('tiltimage');
  if (ti != null) { ti.style.display = "none"; }

  // And the PTZ controls
  document.getElementById('ptzpanel').style.display = 'none';
  document.getElementById('ptzpresetpanel').style.display = 'none';

  // And the sensor list
  document.getElementById('sensorpanel').style.display = 'none';
}

// Increment the expiry time to allow for >60s timeouts
function expireInc() {
  expireTime++;

  if (expireTime > duration)
    expireTimer();
  else
    window.setTimeout("expireInc()", 1000);
}



/**************
* PTZ Control *
**************/
var ptzImage = new Image();
var ptzFine = 0;

// Initialise anything that is needed for the PTZ controls
$(document).ready(function() {
  $(".smallbutton").mouseenter(function() { if(!$(this).hasClass("smallbuttondisabled")) { $(this).addClass("smallbuttonhover"); } });
  $(".smallbutton").mouseleave(function() { $(this).removeClass("smallbuttonhover"); });
});

// Show and hide all the PTZ controls and panels as needed
function enablePTZControls(feedIndex) {
  if (expired)
    return;

  var fw = 0;
  var fh = 0;
  panEn = 0;
  tiltEn = 0;
  zoomEn = 0;

  // If it is a single (valid) feed, enable as needed
  if (currentLayout == 1 && feedIndex != -1) {
    panEn = feeds[feedIndex].ptz & 1;
    tiltEn = feeds[feedIndex].ptz & 2;
    zoomEn = feeds[feedIndex].ptz & 4;
  }

  // Get a reference to the PTZ gradient bars
  pi = document.getElementById('panimage');
  ti = document.getElementById('tiltimage');

  // If any of them are enabled..
  if ((zoomEn) || (panEn) || (tiltEn)) {

    // Enable the pan, tilt, and zoom buttons if that feature is available
    // There is no need to set them outside this block as the PTZ controls will be hidden
    if (panEn || tiltEn) {
      $(".ptztable .direction").removeClass("disabled");
    } else {
      $(".ptztable .direction").addClass("disabled");
    }

    if (zoomEn) {
      $(".ptztable .zoom").removeClass("disabled");
    } else {
      $(".ptztable .zoom").addClass("disabled");
    }

    if (!usingApplet) {
      // Get the image tag size
      fi = document.getElementById('image1');
      fw = fi.width;
      fh = fi.height;
    } else {
      if (checkApplet()) {
        // Get the image tag size
        fw = document.MJPGApplet.width;
        fh = document.MJPGApplet.height;
      }
      // If the applet hasn't loaded yet, it will be the default of 0 from above
    }

    $("#fineButton").removeClass('smallbuttondisabled');
    $("#homeButton").removeClass('smallbuttondisabled');

    // Load the pan gradient image
    if ((pi != null) && (fw != 0) && (panEn)) {
      pi.width = fw;
      pi.height = 12;
      pi.src = '/ptz/gradient.gif?orientation=0&size=' + fw;
      pi.style.display = "inline";
    }

    // Load the tilt gradient image
    if ((ti != null) && (fh != 0) && (tiltEn)) {
      ti.width = 17;
      ti.height = fh;
      ti.src = '/ptz/gradient.gif?orientation=1&size=' + fh;
      ti.style.display = "inline";
    }

    document.getElementById('ptzpanel').style.display = 'inline';
    updatePresetList(feeds[feedIndex].id);

  } else {
    //Disable the PTZ buttons
    document.getElementById('ptzpanel').style.display = 'none';
    $("#fineButton").addClass('smallbuttondisabled');
    $("#homeButton").addClass('smallbuttondisabled');
    document.getElementById('ptzpresetpanel').style.display = 'none';
    clearPresetList();
  }

  // If the PTZ gradients exist but they aren't available, hide them
  if ((!panEn) && (pi != null)) { pi.style.display = "none"; }
  if ((!tiltEn) && (ti != null)) { ti.style.display = "none"; }
}

function sendPTZCommand(command, parameters) {
  url = '/ptz/control.htm?feed=' + currentFeedID() + '&' + command + '&uniq=' + getMillis();

  ptzImage.src = url;
}

// Toggles the fine movement mode
function setFine() {
  ptzFine = 1 - ptzFine;

  if (ptzFine)
    $("#fineButton").addClass('smallbuttonselected');
  else
    $("#fineButton").removeClass('smallbuttonselected');
}

// Handle the zoom rondel
function doPTZ(url) {
  if (currentLayout != 1)
    return;

  angle = 5;
  if (ptzFine)
    angle = 1;

  url = url + '&angle=' + angle;

  sendPTZCommand(url);
}

function goHome() {
  if (currentLayout != 1)
    return;

  sendPTZCommand('move=home');
}

function gotoPreset(presetIndex) {
  //1 based list of presets
  //0 is the home positions
  sendPTZCommand('move=preset&preset=' + presetIndex);
}

// Handle clicks in the applet
function directPTZMovement(mX, mY) {
  if (currentLayout != 1)
    return;

  sendPTZCommand('move=inimage&x=' + mX + "&y=" + mY + "&width=" + document.MJPGApplet.width + "&height=" + document.MJPGApplet.height);
}

// Pan/tilt gradient click handlers
function panscrollclick(click) {
  if (navigator.appName == 'Netscape') {
    rx = click.clientX - document.getElementById('panimage').x;
  } else {
    rx = click.offsetX;
  }

  mins = parseInt(rx * (360 / (document.getElementById('panimage').width - 1)));
  mins = (mins - 180);

  sendPTZCommand('move=to&pan=' + mins);
}

function tiltscrollclick(click) {
  if (navigator.appName == 'Netscape') {
    rx = click.clientY - document.getElementById('tiltimage').y;
  } else {
    rx = click.offsetY;
  }

  mins = parseInt(rx * (360 / document.getElementById('tiltimage').height));
  mins = -(mins - 180);

  sendPTZCommand('move=to&tilt=' + mins);
}



/***********************
* Preset list handling *
***********************/
var http = getHTTPObject();

// Remove all existing presets
function clearPresetList() {
  var table = document.getElementById('ptzpresettable');
  for (var index = 0; index < table.rows[0].cells.length;) {
    table.rows[0].deleteCell(index);
  }
}

// Get the list of presets from the server
function updatePresetList(feedid) {
  clearPresetList();

  if (feedid != "") {
    http.open("GET", "/ptz/presets.xml?feed=" + feedid, true);
    http.onreadystatechange = HandlePresetReply;
    http.send(null);
  }
}

// Handle the preset list reply and update the panel
function HandlePresetReply() {
  if (http.readyState == 4) {

    if (http.responseText != "") {
      var feedID = currentFeedID();

      var presetlist = http.responseXML.documentElement;
      var panel = document.getElementById('ptzpresetpanel');
      var table = document.getElementById('ptzpresettable');
      var tablerow = table.rows[0];

      // Add the home preset
      var cell = tablerow.insertCell(0);
      cell.innerHTML = "<a href=\"#\" onclick=\"return gotoPresetCheck(0);\"><img src=\"/ptz/presetimage.jpg?feed=" + feedID + "&preset=0\" width=\"80\" height=\"60\"><br />Home</a>";

      var presets = presetlist.getElementsByTagName("preset");
      if (presets.length == 0) {
        panel.style.display = 'none';
      } else {
        panel.style.display = 'block';

        for (var index = 0; index < presets.length; index++) {
          var preset = presets[index];
          var cell = tablerow.insertCell(tablerow.cells.length);
          // The name needs to be encoded here as the XML library decodes the HTML entities
          cell.innerHTML = "<a href=\"#\" onclick=\"return gotoPresetCheck(" + (index + 1) + ");\"><img src=\"/ptz/presetimage.jpg?feed=" + feedID + "&preset=" + (index + 1) + "\" width=\"80\"><br />" + HTMLEntities(preset.attributes.getNamedItem('name').value) + "</a>";
        }

        sizePresetPanel();
      }

    } else {
      //request failed
    }
  }
}

// This will resize the preset panel to fit all the preset images, keeping it below the image size (or 336, whichever is larger)
function sizePresetPanel() {
  var imageWidth = 336;

  if (!usingApplet) {
    // Get the image tag size
    imageWidth = document.getElementById('image1').width
  } else {
    if (checkApplet()) {
      // Get the image tag size
      imageWidth = document.MJPGApplet.width;
    }
    // If the applet hasn't loaded yet, it will be the default of 338 from above
  }
  // Limit the image size to a minimum of 336
  //if (imageWidth < 336) { imageWidth = 336; }
  // Subtract the frame borders
  imageWidth -= 24;

  // Add the PTZ gradients if they're visible
  var ti = document.getElementById('tiltimage');
  if (ti != null) { imageWidth += ti.width; }

  var newWidth = document.getElementById('ptzpresetpanel2').scrollWidth;
  //if (newWidth > imageWidth) { newWidth = Math.floor(imageWidth / 84) * 84; }
  if (newWidth > imageWidth) { newWidth = imageWidth; }
  document.getElementById('ptzpresetpanel2').style.width = newWidth;
}

// Handle preset image clicks, but ignore clicks if it has been dragged
function gotoPresetCheck(presetIndex) {
  if (!dragIgnoreClick) {
    gotoPreset(presetIndex);
  }
  return false;
}

var presetsCreepTimerID = 0;

// Slowly slide the preset list from side to side
function creepPresets() {
  var creepAmount = 2
  var atEnd = false;

  var panel = document.getElementById("ptzpresetpanel2");

  if (panel.creepAmount == undefined) { panel.creepAmount = creepAmount; }
  panel.scrollLeft += panel.creepAmount;

  if (panel.scrollLeft == 0) {
    panel.creepAmount = creepAmount;
    atEnd = true;
  } else if (panel.scrollLeft + panel.offsetWidth == panel.scrollWidth) {
    panel.creepAmount = -creepAmount;
    atEnd = true;
  } else {
  }

  presetsCreepTimerID = window.setTimeout("creepPresets()", (atEnd ? 5000 : 100));
}

// Stop it moving on mouseover
var presetsMouseOutTimer = 0;

function presetsMouseOver() {
  // Stop the creep timer
  window.clearTimeout(presetsCreepTimerID);
  window.clearTimeout(presetsMouseOutTimer);
}

function presetsMouseOut() {
  // Reset the creep time after 100ms (unless they mouseover again)
  presetsMouseOutTimer = window.setTimeout(creepPresets, 100);
}



/*****************
* IO device list *
*****************/
var iohttp = getHTTPObject();

var sensorIDs = new Array();
var setImage = new Image();
var IOTimerID = 0;

function updateIOInfo() {
  //alert('attempting update');
  iohttp.open("GET", "/io/sensors.xml?skipauth&feed=" + currentFeedID(), true);
  iohttp.onreadystatechange = handleIOReply;
  iohttp.send(null);
}

function handleIOReply() {
  if (iohttp.readyState == 4) {
    //alert('got reply');
    if (iohttp.responseText != "") {
      loadIOInfo(iohttp.responseXML.documentElement);
    } else {
      //request failed
      //clearIOInfo();
    }

    //Set the timer for 5s time
    if (IOTimerID != 0) { window.clearTimeout(IOTimerID); }
    IOTimerID = window.setTimeout("updateIOInfo()", 5000);
  }
}

function loadIOInfo(ioinfo) {
  //alert('processing reply');
  var feedID = currentFeedID();

  var panel = document.getElementById('sensorpanel');
  var table = document.getElementById('sensortable');
  var tablerow = table.rows[0];

  var sensors = ioinfo.getElementsByTagName("sensor");
  if (sensors.length == 0) {
    panel.style.display = 'none';
  } else {
    panel.style.display = 'block';

    var index; // This is used after the for loop so needs to be function scoped
    for (index = 0; index < sensors.length; index++) {
      var sensor = sensors[index];
      var sensorID = getElementValue(sensor, "id");
      var sensorValue = getElementValue(sensor, "nativevalue");

      var needUpdate = false;
      if (index < tablerow.cells.length) {
        //The row already exists, set a flag if any details change
        var cell = tablerow.cells[index];
        needUpdate = (cell.sensorID != sensorID || cell.sensorValue != sensorValue);
      } else {
        //Add the row to the table
        var cell = tablerow.insertCell(tablerow.cells.length);
        needUpdate = true;
      }
      cell.sensorID = sensorID;

      if (needUpdate) {
//        alert("updating " + sensorID);
        // The name needs to be encoded here as the XML library decodes the HTML entities
        cell.innerHTML = "<a href=\"#\" onclick=\"return toggleSensorStateCheck('" + HTMLEntities(sensorID) + "');\"><span class=\"imageContainer\"><img src=\"/io/sensorimage.jpg?sensor=" + HTMLEntities(sensorID) + "&value=" + HTMLEntities(sensorValue) + "\" width=\"80\" onload=\"checkHeight(this, 80, 60);\"></span><br />" + HTMLEntities(getElementValue(sensor, "name")) + "</a>";
        cell.sensorValue = sensorValue;
      }
    }

    //Remove all the extra cells
    for (index; index < tablerow.cells.length;) {
      tablerow.deleteCell(index);
    }

    sizeSensorPanel();
  }
}

// Handle preset image clicks, but ignore clicks if it has been dragged
function toggleSensorStateCheck(sensor) {
  if (!dragIgnoreClick) {
    toggleSensorState(sensor);
  }
  return false;
}

function toggleSensorState(sensor) {
//alert ("Toggling sensor " + sensor);
  url = '/io/setsensor.htm?sensor=' + sensor + '&uniq=' + getMillis();
  setImage.src = url;
}

function clearIOInfo() {
  var table = document.getElementById('sensortable');
  for (var index = 0; index < table.rows[0].cells.length;) {
    table.rows[0].deleteCell(index);
  }
}

// This will resize the sensor panel to fit all the sensor images, keeping it below the image size (or 336, whichever is larger)
function sizeSensorPanel() {
  var imageWidth = 336;

  if (!usingApplet) {
    // Get the image tag size
    imageWidth = document.getElementById('image1').width
  } else {
    if (checkApplet()) {
      // Get the image tag size
      imageWidth = document.MJPGApplet.width;
    }
    // If the applet hasn't loaded yet, it will be the default of 338 from above
  }
  // Limit the image size to a minimum of 336
  //if (imageWidth < 336) { imageWidth = 336; }
  // Subtract the frame borders
  imageWidth = imageWidth - 24;

  // Add the PTZ gradients if they're visible
  var ti = document.getElementById('tiltimage');
  if (ti != null) { imageWidth += ti.width; }

  var newWidth = document.getElementById('sensorpanel2').scrollWidth;
  //if (newWidth > imageWidth) { newWidth = Math.floor(imageWidth / 84) * 84; }
  if (newWidth > imageWidth) { newWidth = imageWidth; }
  document.getElementById('sensorpanel2').style.width = newWidth;
}

var sensorsCreepTimerID = 0;

// Slowly slide the sensors list from side to side
function creepSensors() {
  var creepAmount = 2
  var atEnd = false;

  var panel = document.getElementById("sensorpanel2");

  if (panel.creepAmount == undefined) { panel.creepAmount = creepAmount; }
  panel.scrollLeft += panel.creepAmount;

  if (panel.scrollLeft == 0) {
    panel.creepAmount = creepAmount;
    atEnd = true;
  } else if (panel.scrollLeft + panel.offsetWidth == panel.scrollWidth) {
    panel.creepAmount = -creepAmount;
    atEnd = true;
  } else {
  }

  sensorsCreepTimerID = window.setTimeout("creepSensors()", (atEnd ? 5000 : 100));
}

// Stop it moving on mouseover
var sensorsMouseOutTimer = 0;

function sensorsMouseOver() {
  // Stop the creep timer
  window.clearTimeout(sensorsCreepTimerID);
  window.clearTimeout(sensorsMouseOutTimer);
}

function sensorsMouseOut() {
  // Reset the creep time after 100ms (unless they mouseover again)
  sensorsMouseOutTimer = window.setTimeout(creepSensors, 100);
}



/**************
* Gadget info *
**************/
function initGadgetBlock() {
  //Show the Gadget block unless a cookie says otherwise
  var hideGadgetVal = getCookie("hidegadget");
  if (hideGadgetVal == null) { hideGadgetVal = 0; }

  if ((navigator.userAgent.indexOf("Windows NT 6.0") > -1) && hideGadgetVal == 0) {
    //Windows vista 
    document.getElementById('gadgetblock').style.display = 'block';
  }
}

//Hide the gadget on request
function hideGadget() {
  document.getElementById('gadgetblock').style.display = 'none';
  setCookie('hidegadget', 1);
  return false;
}



/******************
* Ancillary stuff *
******************/
function getMillis() {
  var date = new Date();
  return date.getTime();
}

function HTMLEntities(str) {
  var div = document.createElement('div');
  var text = document.createTextNode(str);
  div.appendChild(text);
  return div.innerHTML;
}

function checkHeight(object, maxWidth, maxHeight) {
  if (object.height > maxHeight) {
    object.width = object.width * (maxHeight / object.height);
  }

  //alert((maxHeight - object.height) / 2);
  object.style.marginTop = (maxHeight - object.height) / 2;
  object.style.marginLeft = (maxWidth - object.width) / 2;
}



/**********
* Cookies *
**********/
// Imported from /cookies.js
// Original JavaScript code by Duncan Crombie: dcrombie at chirp.com.au
// Please acknowledge use of this code by including this header.
// http://members.ozemail.com.au/~dcrombie/cookie.html

function getCookie(name) { // use: getCookie("name");
  var cookie = document.cookie;
  var index = cookie.indexOf(name + "=");
  if (index == -1) return null; //Not found
  index = cookie.indexOf("=", index) + 1;
  var endstr = cookie.indexOf(";", index);
  if (endstr == -1) endstr = cookie.length;
  return unescape(cookie.substring(index, endstr));
}

function setCookie(name, value) { // use: setCookie("name", value);
  var today = new Date();
  var expiry = new Date(today.getTime() + 28 * 24 * 60 * 60 * 1000); // plus 28 days

  if (value != null && value != "")
    document.cookie = name + "=" + escape(value) + "; expires=" + expiry.toGMTString() + "; path=/";
}



/*****************
* Slider control *
*****************/
// Imported from /slider.js
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Originally from:
  http://www.arantius.com/article/lightweight+javascript+slider+control

Copyright (c) 2006 Anthony Lieuallen, http://www.arantius.com/

The following licensing information applies solely to slider.js, the
DHTML/JavaScript slider control. Please see the i-Catcher EULA for information
pertaining to the i-Catcher license.

Permission is hereby granted, free of charge, to any person obtaining a copy of 
this software and associated documentation files (the "Software"), to deal in 
the Software without restriction, including without limitation the rights to 
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 
the Software, and to permit persons to whom the Software is furnished to do so, 
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all 
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

//add event function from http://www.dynarch.com/projects/calendar/
function addAnEvent(el, evname, func) {
  if (el.attachEvent) { // IE
    el.attachEvent("on" + evname, func);
  } else if (el.addEventListener) { // Gecko / W3C
    el.addEventListener(evname, func, true);
  } else {
    el["on" + evname] = func;
  }
}

function drawSliderByVal(slider) {
  slider.val = Math.floor(slider.val);
  var knob = slider.getElementsByTagName('img')[0];
  var p = (slider.val - slider.min) / (slider.max - slider.min);
  var x = (slider.scrollWidth - 12) * p;
  knob.style.left = x + "px";
}

function setSlider(num, val) {
  slider[num].val = val;

  sliderControl = document.getElementById('slider0' + num);

  if (sliderControl != null) {
    sliderControl.val = val;
    drawSliderByVal(sliderControl);
  }
}

function findPosX(obj) {
  var curleft = 0;
  if (obj.offsetParent) {
    while (obj.offsetParent) {
      curleft += obj.offsetLeft
      obj = obj.offsetParent;
    }
  } else if (obj.x)
    curleft += obj.x;

  return curleft;
}

function setSliderByClientX(slider, clientX) {
//  var pvars = (clientX - findPosX(slider)) / (slider.scrollWidth + 10);
  var pvars = (clientX - slider.offsetLeft - 6) / (slider.scrollWidth - 12);
  slider.val = (slider.max - slider.min) * pvars + slider.min;
  if (slider.val > slider.max) slider.val = slider.max;
  if (slider.val < slider.min) slider.val = slider.min;

  drawSliderByVal(slider);
  slider.onchange(slider.val, slider.num);
}

function sliderClick(eventInfo) {
  var el = sliderFromEvent(eventInfo);
  if (!el) return;

  setSliderByClientX(el, eventInfo.clientX);
}

function sliderMouseMove(eventInfo) {
  var el = sliderFromEvent(eventInfo);
//  if (!el) return;
//  if (activeSlider < 0) return;

  if ((!el) || (activeSlider < 0)) {
    activeSlider = -1;

    return;
  }

  if ((el.num == 1) && (!allowZooming))
    return;

  setSliderByClientX(el, eventInfo.clientX);
  stopEvent(eventInfo);
}

function sliderFromEvent(eventInfo) {
  if (!eventInfo && window.event) eventInfo = window.event;
  if (!eventInfo) return false;

  var el;
  if (eventInfo.target) el = eventInfo.target;
  if (eventInfo.srcElement) el = eventInfo.srcElement;

  if (!el.id || !el.id.match(/slider\d+/)) el = el.parentNode;
  if (!el) return false;
  if (!el.id || !el.id.match(/slider\d+/)) return false;

  return el;
}

function attachSliderEvents() {
  var divs = document.getElementsByTagName('div');
  var divNum;
  for (var index = 0; index < divs.length; index++) {
    if (divNum = divs[index].id.match(/\bslider(\d+)\b/)) {
      divNum = parseInt(divNum[1]);
      divs[index].min = slider[divNum].min;
      divs[index].max = slider[divNum].max;
      divs[index].val = slider[divNum].val;
      divs[index].onchange = slider[divNum].onchange;
      divs[index].num = divNum;

      addAnEvent(divs[index], 'mousedown', function(eventInfo) {
        sliderClick(eventInfo);
        var el = sliderFromEvent(eventInfo);
        if (!el) return;
        activeSlider = el.num;
        stopEvent(eventInfo);
      });
      addAnEvent(divs[index], 'mouseup', function(eventInfo) {
        activeSlider = -1;
        stopEvent(eventInfo);
      });
    }
  }

  sliderPostLoad();
}

//borrowed from prototype: http://prototype.conio.net/
function stopEvent(event) {
  if (event.preventDefault) {
    event.preventDefault();
    event.stopPropagation();
  } else {
    event.returnValue = false;
    event.cancelBubble = true;
  }
}

addAnEvent(window, 'load', attachSliderEvents);
addAnEvent(document, 'mousemove', sliderMouseMove);
var activeSlider = -1;



/***************************
* Draggable panel handling *
***************************/
var dragParent = null; // The div containing the draggable panel
var dragTarget = null; // The object being dragged

var dragIgnoreClick = false

// Does all the checking and setup for the draggable container handling
function dragMouseDown(eventInfo) {
  // Set hand to "grab"
  var cursorType = '-moz-grabbing';
  if (eventInfo == null) {
    eventInfo = window.event;
    cursorType = 'w-resize';
  } // Fix some IE things...

  // Get the object actually being dragged and the draggable container
  var target = eventInfo.target != null ? eventInfo.target : eventInfo.srcElement;
  dragParent = getDraggable(target);

  // Check if it's in a draggable container
  if (dragParent != null) {
    // Store the current target object and cursor and change to the drag cursor
    target.originalCursor = target.style.cursor;
    target.style.cursor = cursorType;
    dragTarget = target;

    // Note the current positions and mousedown offset
    dragParent.originalScrollLeft = dragParent.scrollLeft;
    dragParent.dragOffset = eventInfo.clientX;

    //Set up the events to handle the rest
    document.onmousemove = dragMouseMove;
    document.onmouseup = dragMouseUp;

    // Stop propogation
    return false;
  }
}

// This function handles the dragging of the contents left to right
function dragMouseMove(eventInfo) {
  if (eventInfo == null) {
    eventInfo = window.event;
  } // Fix some IE things...

  // Is the mouse button down and do we have a draggable object
  if (eventInfo.button <= 1 && (dragParent != null)) {
    // Calculate the new offset position
    var newOffset = (dragParent.dragOffset - eventInfo.clientX);
    // Bounds checking is done by IE
    dragParent.scrollLeft = dragParent.originalScrollLeft + newOffset;

    // Stop propogation
    return false;
  }
}

//Called when user releases a mouse button after a drag event
function dragMouseUp(eventInfo) {
  // Do we have a draggable object
  if (dragParent != null) {
    // Reset the targets cursor
    dragTarget.style.cursor = dragTarget.originalCursor;

    // Disable the handler events
    document.onmousemove = null;
    document.onmouseup = null;

    var distanceDragged = Math.abs(dragParent.scrollLeft - dragParent.originalScrollLeft);
    if (distanceDragged > 2) {
      // Set a flag so the click event in the next 100ms is ignored
      dragIgnoreClick = true;
      window.setTimeout(function() { dragIgnoreClick = false; }, 100);
    }

    // Release the object references
    dragTarget = null;
    dragParent = null;

    return false;
  }
}

// Iterates up through an objects parents to see if it is a drag container
function getDraggable(item) {
  var currentItem = item;

  //Loop until we hit the document element
  while (currentItem != document) {
    //If it's a member of the dragcontainer class, we're done
    if (currentItem.className.indexOf("dragContainer") > -1) {
      return currentItem;
    }
    //Try its parent
    currentItem = currentItem.parentNode;
  }

  //Nothing was found
  return null;
}
