function createSideBar(id, layerId, side, visible, delay) {
  return new _SideBar(id, layerId, side, visible, delay);
}

function _SideBar(id, layerId, side, visible, delay) {
  ////////// Variables and Members ////////
  // public:
//  this.browser        = CreateBrowser();
//  this.page           = CreatePage();
  this.layer          = CreateLayer(layerId);
  this.id             = id;

  // public:
  this.setVisible     = _SideBar_setVisible;
  this.isVisible      = _SideBar_isVisible;
  this.toggleVisibility = _SideBar_toggleVisibility;
  // private:
  this._visible       = !visible; // set as opposite so that it switch when setVisible is called.
  
  // public:
  this.refresh        = _SideBar_refresh;
  this.reposition     = _SideBar_reposition;
  
  // public:
  this.onSlideStart   = null;
  this.onSlideEnd     = null;
  this.isSliding      = _SideBar_isSliding;
  // private:
  this._sliding       = 0;
  
  // public:
  this.delay          = delay;
  
  // private:
  this._side           = side;

  // private:
  this._ref           = "_" + id + "_SideBar";
  eval(this._ref + " = this");
  
  // private:
  this._top           = this.layer.getTop();
  this._left          = this.layer.getLeft();
  
  ///////// Initialisation Stage ////////
  // Add it to the document.sidebars array.
  if (typeof(document.sidebars) != "object") {
    document.sidebars = new Array();
  }
  document.sidebars[document.sidebars.length]   = this;
  document.sidebars[id] = this;
  
  // Catch resize events so that it tracks.
  if (window.browser.ns) {
    window.captureEvents(Event.RESIZE);
  }
  window.onresize = _SideBar_window_onResize;
  
  window.browser.captureScrollEvents();
  window.browser.onscroll = _SideBar_browser_onScroll;
  
//  eval("document.sidebars." + id + " = this");

  // Put the layer in the correct place to start.
  this.layer.setVisible(visible);
  this._visible = visible;
  
  switch(side) {
  case 1: // left
  case 3: // right
    this.layer.setLeft(0);
    break;
  case 2: // top
  case 4: // bottom
  default:
    this.layer.setTop(0);
    break;
  }
}

function _SideBar_setVisible(visible) {
  if (this._visible != visible && !this._sliding) {
    // Send the onSlideStart event
    if (typeof(this.onSlideStart) == "function") {
      if (!this.onSlideStart(this))
        return;
    } else if (this.onSlideStart != null && typeof(this.onSlideStart) == "object") {
      if (!this.onSlideStart.trigger(this))
        return;
    }
    this._visible = visible;
  
    // set up the onSlideEnd object.
    if (this.layer.onSlideEnd != null && typeof(this.layer.onSlideEnd) == "object") {
      delete this.layer.onSlideEnd;
    }
    this.layer.onSlideEnd = new _SideBar_SlideEndHandler(this);
  
    var top, left;
    if (visible) { // showing
      switch(this._side) {
      case 1: // left
        top  = this._top + window.browser.getViewTop();
        left = window.browser.getViewLeft();
        this.layer.setLeft(left-this.layer.getWidth());
        break;
      case 2: // top
        top  = window.browser.getViewTop();
        left = this._left + window.browser.getViewLeft();
        this.layer.setTop(top-this.layer.getHeight());
        break;
      case 3: // right
        var viewWidth = window.browser.getViewWidth();
        top  = this._top + window.browser.getViewTop();
        left = viewWidth - this.layer.getWidth();
        this.layer.setLeft(viewWidth);
        break;
      default: // bottom
        var viewHeight = window.browser.getViewHeight();
        top  = viewHeight - this.layer.getHeight();
        left = this._left + window.browser.getViewLeft();
        this.layer.setTop(viewHeight);
      }
    } else { // hiding
      switch(this._side) {
      case 1: //left
        this.layer.setLeft(0);
        top  = this._top + window.browser.getViewTop();
        left = -this.layer.getWidth();
        break;
      case 2: // top
        this.layer.setTop(0);
        top  = -this.layer.getHeight();
        left = this._left + window.browser.getViewLeft();
        break;
      case 3: // right
        var viewWidth = window.browser.getViewWidth();
        this.layer.setLeft(viewWidth - this.layer.getWidth());
        top  = this._top + window.browser.getViewTop();
        left = viewWidth;
        break;
      default: // bottom
        var viewHeight = window.browser.getViewHeight();
        this.layer.setTop(viewHeight - this.layer.getHeight());
        top  = viewHeight;
        left = this._left + window.browser.getViewLeft();
      }
    }
    this.layer.setVisible(true);
    
    var step = 25;
    var delay = this.delay;
    
    this._sliding = (visible) ? 1 : 2;
    
    this.layer.slideTo(left, top, step, delay);
  }
}

function _SideBar_isVisible() {
  return this._visible;
}

function _SideBar_toggleVisibility() {
  this.setVisible(!this.isVisible());
}

function _SideBar_isSliding() {
  return this._sliding;
}

function _SideBar_refresh() {
  var top, left;

  this.layer.refresh();
  
  this.reposition();
}

function _SideBar_reposition() {
  
  switch(this._side) {
  case 1: // left
    this.layer.setLeft(window.browser.getViewLeft());
    this.layer.setTop(this._top + window.browser.getViewTop());
    break;
  case 2: // top
    this.layer.setLeft(this._left + window.browser.getViewLeft());
    this.layer.setTop(window.browser.getViewTop());
    break;
  case 3: // right
    var viewWidth = window.browser.getViewWidth();
    this.layer.setLeft(viewWidth-this.layer.getWidth());
    this.layer.setTop(this._top + window.browser.getViewTop());
    break;
  default: // bottom
    var viewHeight = window.browser.getViewWidth();
    this.layer.setLeft(this._left + window.browser.getViewLeft());
    this.layer.setTop(viewHeight-this.layer.getHeight());
  }
}

/////////////////// Private object //////////////////////
function _SideBar_SlideEndHandler(sideBar) {
  this.sideBar = sideBar;
  this.trigger = _SideBar_SlideEndHandler_trigger;
}

function _SideBar_SlideEndHandler_trigger(target) {
  var sb = this.sideBar;
  if (sb._sliding == 2) { // it's hiding
    target.setVisible(false);
    switch(sb._side) {
    case 1: // left
    case 3: // right
      target.setLeft(-target.getWidth());
      break;
    case 2: // top
    default: // bottom
      target.setTop(-target.getHeight());
      break;
    }
  }
//  sb._visible = (sb._sliding == 1) ? true : false;
  sb._sliding = 0;
  
  // Send onSlideEnd event
  if (typeof(sb.onSlideEnd) == "function") {
    sb.onSlideEnd(sb);
  } else if (sb.onSlideEnd != null
          && typeof(sb.onSlideEnd) == "object") {
    sb.onSlideEnd.trigger(sb);
  }
}

function _SideBar_window_onResize(evt) {
  for(i = 0; i < document.sidebars.length; i++) {
    document.sidebars[i].refresh();
  }
}

function _SideBar_browser_onScroll() {
  for(i = 0; i < document.sidebars.length; i++) {
    document.sidebars[i].reposition();
  }
}