var APPNAME = window.navigator.appName;
var APPVERSION = window.navigator.appVersion;
var USERAGENT = window.navigator.userAgent;

function Client () {

  // properties
  this.browser = "other";
  this.browserName = "Other";
  this.browserVersion = 0;
  this.version = 0;
  
  this.os = "other";
  this.osName = "Other";
  this.osVersion = 0;
  
  this.standardMode = false;
  
  this.mouseListeners = new Array();
  
  //methods
  this.init = Client_init;
  this.addMouseListener = Client_addMouseListener;
  this.removeMouseListener = Client_removeMouseListener;
  this.initBrowser = Client_initBrowser;
  this.getFullOsName = Client_getFullOsName;
  this.captureMouseEvents = Client_captureMouseEvents;
  this.releaseMouseEvents = Client_releaseMouseEvents;
  this.eventPassThrough = Client_eventPassThrough;
  this.mouseMove = Client_mouseMove;
  this.mouseUp = Client_mouseUp;
  this.cancelMouseFeedback = Client_cancelMouseFeedback;
  this.leftMouseClick = Client_leftMouseClick;
  this.rightMouseClick = Client_rightMouseClick;
  this.initOperatingSystem = Client_initOperatingSystem;
  this.getClientWidth = Client_getClientWidth;
  this.getClientHeight = Client_getClientHeight;
  this.getDocumentWidth = Client_getDocumentWidth;
  this.getDocumentHeight = Client_getDocumentHeight;
  this.getBodyWidth = Client_getBodyWidth;
  this.getBodyHeight = Client_getBodyHeight;
  this.getOffsetTop = Client_getOffsetTop;
  this.getOffsetLeft = Client_getOffsetLeft;
  this.getXResolution = Client_getXResolution;
  this.getYResolution = Client_getYResolution;
  this.getLayerReference = Client_getLayerReference;
  this.getLinkReference = Client_getLinkReference;
  this.getImageReference = Client_getImageReference;
  this.getLayerStyleProperty = Client_getLayerStyleProperty;
  this.getCrossBrowserStyleProperty = Client_getCrossBrowserStyleProperty;
  this.getCrossBrowserStyleValue = Client_getCrossBrowserStyleValue;
  this.setLayerStyleProperty = Client_setLayerStyleProperty;
  this.scrollBy = Client_scrollBy;
  this.scrollTo = Client_scrollTo;
  this.printSystemSpecs = Client_printSystemSpecs;
  this.printScreenSpecs = Client_printScreenSpecs;
  
  this.init();
}

function Client_init () {
  
  if (document.documentElement)
    this.standardMode = true;
  this.initBrowser();
  this.initOperatingSystem();
  this.captureMouseEvents("MOVE");
  document.onmouseup = this.mouseUp;
  document.onmousemove = this.mouseMove;
}

function Client_addMouseListener (listener) {

  var listenerCount = this.mouseListeners.length;
  this.mouseListeners[listenerCount] = listener;
}

function Client_removeMouseListener (listener) {

  var listenerCount = this.mouseListeners.length;
  for (var i = 0;i < listenerCount;i++)
    if (this.mouseListeners[i] == listener)
      this.mouseListeners.splice(i,1);
}

function Client_initBrowser () {

  if (USERAGENT.toLowerCase().indexOf("opera") >= 0) {
    this.browser = "op";
    this.browserName = "Opera";
    this.browserVersion = USERAGENT.substring(USERAGENT.toLowerCase().indexOf("opera")+6,USERAGENT.lastIndexOf("[")-2);
  }  
  else if(USERAGENT.toLowerCase().indexOf("msie") >= 0) {
    this.browser = "ie";
    this.browserName = "Internet Explorer";
    this.browserVersion = APPVERSION.substring(APPVERSION.toLowerCase().indexOf("msie")+4,APPVERSION.toLowerCase().indexOf("win")-2);
  }
  else if (USERAGENT.toLowerCase().indexOf("netscape") >= 0) {
    this.browser = "ns";
    this.browserName = "Netscape";
    this.browserVersion = USERAGENT.substr(USERAGENT.lastIndexOf("/")+1);
  }
  else if(USERAGENT.toLowerCase().indexOf("safari") >= 0) {
    this.browser = "sf";
    this.browserName = "Safari";
    this.browserVersion = USERAGENT.substr(USERAGENT.lastIndexOf("/")+1);
  }
  else if (USERAGENT.toLowerCase().indexOf("mozilla") >= 0) {
    this.browser = "mz";
    this.browserName = "Mozilla";
    this.browserVersion = USERAGENT.substring(USERAGENT.indexOf("rv:")+3,USERAGENT.lastIndexOf(")"));
  }
  this.version = parseFloat(this.browserVersion);
}

function Client_initOperatingSystem () {

  if (USERAGENT.toLowerCase().indexOf("win") >= 0) {
  
    this.os = "win";
    this.osName = "Windows";
    if (USERAGENT.indexOf("95") >= 0)
      this.osVersion = "95";
    else if (USERAGENT.toLowerCase().indexOf("9x 4.90") >= 0)
      this.osVersion = "ME";
    else if (USERAGENT.indexOf("98") >= 0)
      this.osVersion = "98";
    else if (USERAGENT.toLowerCase().indexOf("nt 5.1") >= 0)
      this.osVersion = "XP";
    else if (USERAGENT.toLowerCase().indexOf("nt 5.0") >= 0)
      this.osVersion = "2000";
    else if (USERAGENT.toLowerCase().indexOf("nt") >= 0)
      this.osVersion = "NT";
  }
  else if (USERAGENT.toLowerCase().indexOf("Mac") >= 0) {
  
    this.os = "mac";
    this.osName = "MacOS";
    if (USERAGENT.toLowerCase().indexOf("os x"))
      this.osVersion = "X";
  }
  else if (USERAGENT.toLowerCase().indexOf("linux") >= 0) {
  
    this.os = "linux";
    this.osName = "Linux";
  }
  else if (USERAGENT.toLowerCase().indexOf("freebsd") >= 0) {
  
    this.os = "bsd";
    this.osName = "FreeBSD";
  }
  else if (USERAGENT.toLowerCase().indexOf("bsd") >= 0) {
  
    this.os = "bsd";
    this.osName = "BSD";
  }
}

function Client_captureMouseEvents (events) {
    
  if ((this.browser == "ns") || (this.browser == "mz")) {
    if (typeof(events) == "string")
      events = [events];
    var eventsCount = events.length;
    for (var i = 0;i < eventsCount;i++) {
      switch (events[i]) {
        
        case "UP":
          document.captureEvents(Event.MOUSEUP);
          break;
        case "DOWN":
          document.captureEvents(Event.MOUSEUP);
          break;
        case "MOVE":
          document.captureEvents(Event.MOUSEMOVE);
      }
    }      
  }
}

function Client_releaseMouseEvents (events) {
    
  if ((this.browser == "ns") || (this.browser == "mz")) {
    if (typeof(events) == "string")
      events = [events];
    var eventsCount = events.length;
    for (var i = 0;i < eventsCount;i++) {
      switch (events[i]) {
        
        case "UP":
          document.releaseEvents(Event.MOUSEUP);
          break;
        case "DOWN":
          document.releaseEvents(Event.MOUSEUP);
          break;
        case "MOVE":
          document.releaseEvents(Event.MOUSEMOVE);
      }
    }      
  }
}

function Client_eventPassThrough (e) {

  if ((this.browser == "ns") || (this.browser == "mz"))
    document.routeEvent(e);
}

function Client_mouseUp (e) {

  var listenerCount = client.mouseListeners.length;
  for (var i = 0;i < listenerCount;i++)
    client.mouseListeners[i].onMouseUp();
    
  if ((client.browser == "ns") || (client.browser == "mz"))
    document.routeEvent(e);
}

function Client_mouseMove (e) {

  if ((client.browser == "ns") || (client.browser == "mz")) {
    client.xMouse = e.pageX;
    client.yMouse = e.pageY;
  }
  else {
    client.xMouse = event.x;
    client.yMouse = event.y;
  }
  var listenerCount = client.mouseListeners.length;
  for (var i = 0;i < listenerCount;i++)
    client.mouseListeners[i].onMouseMove(client.xMouse,client.yMouse);
    
  if ((client.browser == "ns") || (client.browser == "mz"))
    document.routeEvent(e);
}

function Client_cancelMouseFeedback () {

  if (this.browser == "ie") {
    event.returnValue = false;
    event.cancelBubble = true;
  }
}

function Client_leftMouseClick (e) {

  var button = ((this.browser == "ns") || (this.browser == "mz")) ? e.which : event.button;
  
  return (button == 1);
}

function Client_rightMouseClick (e) {

  var button = ((this.browser == "ns") || (this.browser == "mz")) ? e.which : event.button;
  
  return (button == 2);
}

function Client_getFullOsName () {

  return this.osName + " " + this.osVersion;
}

function Client_getClientWidth () {

  if (this.standardMode && document.documentElement.clientWidth)
    return document.documentElement.clientWidth;
  else if ((this.browser == "ie") && (this.version < 6))
    return document.body.clientWidth;
  else if ((this.browser == "sf") || ((this.browser == "op") && (this.version >= 6)))
    return document.body.clientWidth;
  else if (self.outerWidth)
    return self.outerWidth;
  else
    return -1;  
}

function Client_getClientHeight () {

  if (this.standardMode && document.documentElement.clientHeight)
    return document.documentElement.clientHeight;
  else if ((this.browser == "ie") && (this.version < 6))
    return document.body.clientHeight;
  else if ((this.browser == "sf") || ((this.browser == "op") && (this.version >= 6)))
    return document.body.clientHeight;
  else if (self.outerHeight)
    return self.outerHeight;
  else
    return -1;  
}

function Client_getDocumentWidth (frame) {

  frame = (frame != "undefined") ? frame : document;
  if (this.standardMode && frame.documentElement.scrollWidth)
    return frame.documentElement.scrollWidth;
  else if (frame.body.offsetWidth)
    return frame.body.offsetWidth;
  else
    return -1;
}

function Client_getDocumentHeight (frame) {

  frame = (frame != "undefined") ? frame : document;
  if (this.standardMode && frame.documentElement.scrollHeight)
    return frame.documentElement.scrollHeight;
  else if (frame.body.offsetHeight)
    return frame.body.offsetHeight;
  else
    return -1;
}

function Client_getBodyWidth (frame) {

  frame = (frame != "undefined") ? frame : document;
  if (this.standardMode && frame.documentElement.scrollWidth)
    return frame.documentElement.scrollWidth;
  else
    return -1;
}

function Client_getBodyHeight (frame) {

  frame = (frame != "undefined") ? frame : document;
  if (this.standardMode && frame.documentElement.scrollHeight)
    return frame.documentElement.scrollHeight;
  else
    return -1;
}

function Client_getOffsetTop () {

  if (this.standardMode && document.documentElement.scrollTop)
    return document.documentElement.scrollTop;
  else if ((this.browser == "ie") && (this.version < 6))
    return document.body.scrollTop;
  else if ((this.browser == "sf") || ((this.browser == "op") && (this.version >= 6)))
    return document.body.scrollTop;
  else if (self.pageYOffset)
    return self.pageYOffset;
  else
    return -1;  
}

function Client_getOffsetLeft () {

  if (this.standardMode && document.documentElement.scrollLeft)
    return document.documentElement.scrollLeft;
  else if ((this.browser == "ie") && (this.version < 6))
    return document.body.scrollLeft;
  else if ((this.browser == "sf") || ((this.browser == "op") && (this.version >= 6)))
    return document.body.scrollLeft;
  else if (self.pageXOffset)
    return self.pageXOffset;
  else
    return -1;  
}

function Client_getXResolution () {

  if (self.screen.height)
    return self.screen.width;
  else
    return self.screen.width;
}

function Client_getYResolution () {

  if (self.screen.height)
    return self.screen.height;
  else
    return self.screen.height;
}

function Client_getLayerReference (layerId) {

  var layer = null;

  if (typeof(layerId) == "string") {
    if (this.browser == "ie")
      return document.all[layerId];
    else if (this.standardMode)
      return document.getElementById(layerId);
    else if (document.layers)
      return document.layers[layerId];
  }
  else if (typeof(layerId) == "object")
    return layerId;
}

function Client_getImageReference (layerId,imageId) {

  var layer = this.getLayerReference(layerId);
  
  if (((this.browser == "ns") || (this.browser == "mz")) && (layer != null))
    return layer.document.images[imageId];
  else
    return document.images[imageId];
}
  
function Client_getLinkReference (layerId) {
  
  var layer = this.getLayerReference(layerId);
  
  if (((this.browser == "ns") || (this.browser == "mz")) && (layer != null))
    return layer.document.links[layer.document.links.length-1];
  else
    return document.links[document.links.length-1];
}

function Client_getLayerStyleProperty (layerId,prop) {

  if ((this.standardMode) || (this.browser == "ie"))
    return this.getLayerReference(layerId).style[prop];
  else if (document.layers)
    return this.getLayerReference(layerId)[prop];
}

function Client_getCrossBrowserStyleProperty (prop) {

  if (this.browser == "ie") {
    switch (prop) {
    
      case "left": return "pixelLeft";
      case "top": return "pixelTop";
    }
  }
  return prop;
}

function Client_getCrossBrowserStyleValue (prop,value) {
  
  if (this.browser == "ie") {
   
    if ((prop == "visibility") && value)
      value = "visible";
    else if ((prop == "visibility") && !value)
      value = "hidden"; 
  }
  else if ((this.browser == "ns") || (this.browser == "mz")) {
  
    if ((prop == "visibility") && value)
      value = "show";
    else if ((prop == "visibility") && !value)
      value = "hide";
    else if (typeof(value) == "number")
      value = value +"px";
  }
  
  return value;
}

function Client_setLayerStyleProperty (layerId,prop,value) {
  
  prop = this.getCrossBrowserStyleProperty(prop);
  value = this.getCrossBrowserStyleValue(prop,value);
  if ((this.standardMode) || (this.browser == "ie"))
    this.getLayerReference(layerId).style[prop] = value;
  else if (document.layers)
    this.getLayerReference(layerId)[prop] = value;
    
  return value;
}

function Client_scrollBy (frame,dx,dy) {

  frame = (frame != "undefined") ? frame : window;
  frame.scrollBy(Math.round(dx),Math.round(dy));
}

function Client_scrollTo (frame,x,y) {

  frame = (frame != "undefined") ? frame : window;
  frame.scrollTo(Math.round(x),Math.round(y));
} 


function Client_printSystemSpecs () {

  var html = "";
  
  html += "Operating System: "+ this.osName +" "+ this.osVersion +" ("+ this.os +")<br />";
  html += "Browser: "+ this.browserName +" "+ this.browserVersion +" ("+ this.version.toString() +")<br />";
  html += "Resolution: "+ this.getXResolution() +" x "+ this.getYResolution() +"<br />";
  
  document.write(html);  
}

function Client_printScreenSpecs () {
  
  var html = "";
  
  html += "Browser width: "+ this.getClientWidth() +"<br />";
  html += "Browser height: "+ this.getClientHeight() +"<br />";
  html += "Document width: "+ this.getDocumentWidth() +"<br />";
  html += "Document height: "+ this.getDocumentHeight() +"<br />";
  html += "Body width: "+ this.getBodyWidth() +"<br />";
  html += "Body height: "+ this.getBodyHeight() +"<br />";
  
  document.write(html);
}