// Create scrolling variable
if (!Scrolling) var Scrolling = {};

//Scroller constructor
Scrolling.Scroller = function (id, t) 
{
  //get the container
  var o = document.getElementById(id);
  var o_w = o;
  o.innerHTML = o.innerHTML + '<div id="'+id+'bar" style="position:absolute;top:0;right:0;"><div class="scrollbar-track"><div class="scrollbar-handle" style="position:absolute;"></div></div></div>';
  o = o.getElementsByTagName("div")[0];
  

	//private variables
	var self  = this;
	var _vwidth   = o_w.offsetWidth;
	var _vheight  = o_w.offsetHeight;
	var _twidth   = o.offsetWidth
	var _theight  = o.offsetHeight;
	var _hasTween = t ? true : false;
	var _timer, _x, _y;

	//public variables
	this.onScrollStart = function (){};
	this.onScrollStop  = function (){};
	this.onScroll      = function (){};
	this.scrollSpeed   = 30;
	
	//private functions
	function setPosition (x, y) {
		if (x < _vwidth - _twidth) 
			x = _vwidth - _twidth;
		if (x > 0) x = 0;
		if (y < _vheight - _theight) 
			y = _vheight - _theight;
		if (y > 0) y = 0;
		
		_x = x;
		_y = y;
		
		o.style.left = _x +"px";
		o.style.top  = _y +"px";
	};
	
	//public functions
	this.scrollBy = function (x, y) { 
		setPosition(_x - x, _y - y);
		this.onScroll();
	};
	
	this.scrollTo = function (x, y) { 
		setPosition(-x, -y);
		this.onScroll();
	};
	
	this.startScroll = function (x, y) {
		this.stopScroll();
		this.onScrollStart();
		_timer = window.setInterval(
			function () { self.scrollBy(x, y); }, this.scrollSpeed
		);
	};
		
	this.stopScroll  = function () { 
		if (_timer) window.clearInterval(_timer);
		this.onScrollStop();
	};
	
	this.reset = function () {
		_twidth  = o.offsetWidth
		_theight = o.offsetHeight;
		_x = 0;
		_y = 0;
		
		o.style.left = "0px";
		o.style.top  = "0px";
		
		if (_hasTween) t.apply(this);
	};
	
	this.swapContent = function (c, w, h) {
		o = c;
		o = o.getElementsByTagName("div")[0];
		
		if (w) _vwidth  = w;
		if (h) _vheight = h;
		this.reset();
	};
	
	this.getDimensions = function () {
		return {
			vwidth  : _vwidth,
			vheight : _vheight,
			twidth  : _twidth,
			theight : _theight,
			x : -_x, y : -_y
		};
	};
	
	this.getContent = function () {
		return o;
	};
	
	this.reset();
};

//Scrollbar constructor
Scrolling.Scrollbar = function (id, s, t) 
{
  var o = document.getElementById(id);
  
  //private variables
  var self = this;
  var _components = {};
  var _dimensions = {};
  var _temporary  = {};
  var _hasTween   = t ? true : false;
  var _timer, _ratio;
  
  //public variables
  this.onMouseDown   = function (){};
  this.onMouseUp     = function (){};
  this.onScroll      = function (){};
  this.scrollAmount  = 5;
  this.scrollSpeed   = 30;
  this.disabled      = false;
  
  //private functions
  function initialize () {
    var c = _components;
    var d = _dimensions;
    var g = s.getDimensions();

    c.up     = findComponent("scrollbar-up", o);
    c.down   = findComponent("scrollbar-down", o);
    c.track  = findComponent("scrollbar-track", o);
    c.handle = findComponent("scrollbar-handle", c.track);
    
    d.trackTop     = findOffsetTop(c.track);
    d.trackHeight  = c.track.offsetHeight;
    d.handleHeight = c.handle.offsetHeight;
    d.y = 0
    
    if (_hasTween) t.apply(self);
    
    addEvent(s.getContent(), "mousewheel", scrollbarWheel);
    addEvent(s.getContent(), "DOMMouseScroll", scrollbarWheel);
    addEvent(o, "mousedown", scrollbarClickPrimer);
    
    self.reset();
  };
  
  function findOffsetTop (o) {
    var t = 0;
    if (o.offsetParent) {
      while (o.offsetParent) {
        t += o.offsetTop;
        o  = o.offsetParent;
      }
    }
    return t;
  };
  
  function addEvent (o, t, f) {
    if (o.attachEvent) o.attachEvent('on'+ t, f);
    else o.addEventListener(t, f, false);
  };
  
  function removeEvent (o, t, f) {
    if (o.detachEvent) o.detachEvent('on'+ t, f);
    else o.removeEventListener(t, f, false);
  };
  
  function findComponent (c, o) {
    var kids = o.childNodes;
    for (var i = 0; i < kids.length; i++) {
      if (kids[i].className && kids[i].className.indexOf(c) >= 0) {
        return kids[i];
      }
    }
  };
  
  function scroll (y) {
    if (y < 0) y = 0;
    if (y > _dimensions.trackHeight - _dimensions.handleHeight)
      y = _dimensions.trackHeight - _dimensions.handleHeight;

    _components.handle.style.top = y +"px";
    _dimensions.y = y;
    
    s.scrollTo(0, Math.round(_dimensions.y * _ratio));
    self.onScroll();
  };
  
  function scrollbarClickPrimer (e) {
    if (self.disabled) return false;
    
    e = e?e:event;
    if (!e.target) e.target = e.srcElement;
    
    _dimensions.trackTop = findOffsetTop(_components.track);
    scrollbarClick(e.target.className, e);
  };
  
  function scrollbarClick (c, e) {
    var d  = _dimensions;
    var t  = _temporary;
    var cy = e.clientY + document.body.scrollTop;
    
    if (c.indexOf("scrollbar-up") >= 0)
      startScroll(-self.scrollAmount);
    
    if (c.indexOf("scrollbar-down") >= 0) 
      startScroll(self.scrollAmount);
      
    if (c.indexOf("scrollbar-track") >= 0)
      if (_hasTween) self.tweenTo((cy - d.trackTop - d.handleHeight / 2) * _ratio);
      else scroll(cy - d.trackTop - d.handleHeight / 2);  
    
    if (c.indexOf("scrollbar-handle") >= 0) {
      t.grabPoint = cy - findOffsetTop(_components.handle);
      addEvent(document, "mousemove", scrollbarDrag, false);  
    }
    
    t.target = e.target;
    t.select = document.onselectstart;
    
    document.onselectstart = function (){ return false; };
    self.onMouseDown(e.target, c, e);
    
    addEvent(document, "mouseup", stopScroll);
  };
  
  function scrollbarDrag (e) {
    e = e?e:event;
    var d = _dimensions;
    var t = parseInt(_components.handle.style.top);
    var v = e.clientY + document.body.scrollTop - d.trackTop;
    
    if (v >= d.trackHeight - d.handleHeight + _temporary.grabPoint)
      v = d.trackHeight - d.handleHeight;
      
    else if (v <= _temporary.grabPoint)
      v = 0;
      
    else v = v - _temporary.grabPoint;
      
    scroll(v);
  };
  
  function scrollbarWheel (e) {
    if (self.disabled) return false;
    
    e = e ? e : event;
    var dir = 0;
    
    if (typeof e.wheelDelta == 'undefined') {
      if (e.detail > 0) dir = 1;
      if (e.detail < 0) dir = -1;
    } else {
      if (e.wheelDelta >= 120) dir = -1;
      if (e.wheelDelta <= -120) dir = 1;
    }

    self.scrollBy(dir * 20);
    
    if(e.stopPropagation) e.stopPropagation();
    if(e.preventDefault) e.preventDefault();
    e.cancelBubble = true;
    e.cancel = true;
    e.returnValue = false;
    return false;
  };
  
  function startScroll (y) {
    _temporary.disty = y;
    _timer = window.setInterval(function () {
      self.scrollBy(_temporary.disty);
    }, self.scrollSpeed);
  };
  
  function stopScroll (e) {
    e = e?e:event;
    
    removeEvent(document, "mousemove", scrollbarDrag);
    removeEvent(document, "mouseup", stopScroll);
    
    document.onselectstart = _temporary.select;
    if (_timer) window.clearInterval(_timer);
    
    self.onMouseUp(_temporary.target, _temporary.target.className, e);
  };
  
  //public functions
  this.reset = function () {
    var d = _dimensions;
    var c = _components;
    var g = s.getDimensions();
    
    _ratio = (g.theight - g.vheight) / (d.trackHeight - d.handleHeight);
    
    c.handle.ondragstart = function (){ return false; };
    c.handle.onmousedown = function (){ return false; };
    c.handle.style.top   = "0px";
    d.y = 0;
    
    s.reset();
    scroll(0);
    
    if (g.theight < g.vheight) {
      this.disable()
    } else this.enable();
  };
  
  this.scrollTo = function (y) {
    scroll(y / _ratio);
  };
  
  this.scrollBy = function (y) {
    scroll((s.getDimensions().y + y) / _ratio);
  };
  
  this.swapContent = function (n) {
    var d = s.getDimensions
    s.swapContent(n, d.vwidth, d.vheight);
    initialize();
  };
  
  this.disable = function () {
    this.disabled = true;
    o.className  += "scrollbar-disabled";
  };
  
  this.enable = function () {
    this.disabled = false;
    o.className = o.className.replace(/scrollbar\-disabled/, "");
  };
  
  this.getContent = function () {
    return s.getContent();
  };
  
  this.getComponents = function () {
    return _components;
  };
  
  this.getDimensions = function () {
    var d = s.getDimensions();
    d.trackHeight  = _dimensions.trackHeight;
    d.handleHeight = _dimensions.handleHeight;
    d.handleY = _dimensions.y;
    
    return d;
  };
  
  initialize();
};

//ScrollTween constructor
Scrolling.ScrollTween = function () 
{
  //private variables
  var self    = this;
  var _steps  = [0,25,50,70,85,95,97,99,100];
  var _values = [];
  var _idle   = true;
  var o, _inc, _timer;
  
  //private functions
  function tweenTo (y) {
    if (!_idle) return false;
    
    var d = o.getDimensions();
    if (y < 0) y = 0;
    if (y > d.theight - d.vheight)
      y = d.theight - d.vheight;
      
    var dist = y - d.y;
    _inc     = 0;
    _timer   = null;
    _values  = [];
    _idle    = false;
    
    for (var i = 0; i < _steps.length; i++) {
      _values[i] = Math.round(d.y + dist * (_steps[i] / 100));
    }

    _timer = window.setInterval(function () {
      o.scrollTo(_values[_inc]); 
      if (_inc == _steps.length - 1) {
        window.clearInterval(_timer);
        _idle = true;
      } else _inc++;
    }, o.stepSpeed);
  };
  
  function tweenBy (y) {
    o.tweenTo(o.getDimensions().y + y);
  };
  
  function setSteps (s) {
    _steps = s;
  };
  
  //public functions
  this.apply = function (p) {
    o = p;
    o.tweenTo   = tweenTo;
    o.tweenBy   = tweenBy;
    o.setSteps  = setSteps;
    o.stepSpeed = 30;
  };
};