/* took a few functions from the prototype library as we dont need it all */

Function.prototype.bind = function() {
  var __method = this, args = $A(arguments), object = args.shift();
  return function() {
    return __method.apply(object, args.concat($A(arguments)));
  }
}

var $A = Array.from = function(iterable) {
  if (!iterable) return [];
  if (iterable.toArray) {
    return iterable.toArray();
  } else {
    var results = [];
    for (var i = 0, length = iterable.length; i < length; i++)
      results.push(iterable[i]);
    return results;
  }
}

var toArray = function() {
	return this.map();
}

  Array.prototype.concat = function() {
    var array = [];
    for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);
    for (var i = 0, length = arguments.length; i < length; i++) {
      if (arguments[i].constructor == Array) {
        for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
          array.push(arguments[i][j]);
      } else {
        array.push(arguments[i]);
      }
    }
    return array;
  }



var scrollerarray=new Array() //array to cache scroller instances
var scrollerclear=new Array() //array to cache corresponding clearinterval pointers

function Scroller(id, parent, child){
    this.amount = 1;
    this.interval = 30;
    this.scrollposition = 0;
    this.scrollindex = 0;
    this.padding = 1;
    this.margin = 1;
    this.id = id;
    this.childId = child;
    this.parentId = parent;
    this.scrollindex = 0;
    this.lastChild = 1;
    this.elmArray = [];
    this.tmpArray = [];
    this.totalHeight = 0;
    var scrollerinstance=this;
    scrollerarray[scrollerarray.length]=this;
    this.objectId = scrollerarray.length-1;
    var elm;
    var lastElm;
    
    for (var i = 1; i < 50; i++) {
        elm = document.getElementById(this.childId + i);

        if (elm != null) {
            //weird rendering thing were you need padding and margin set to actually get the offsetheight
            elm.style.padding = this.padding + "px";
            elm.style.margin = this.margin + "px";
            this.scrollindex += elm.offsetHeight;
            this.totalHeight += elm.offsetHeight;
            this.lastChild = i;
            lastElm = elm;
        } else {
            break;
        }
    }
    if (lastElm != null) {
        this.scrollindex -= lastElm.offsetHeight;
        this.elmArray = [];
        this.tmpArray = [];
        for (var i = 1; i < this.lastChild; i++) {
            this.elmArray[i - 1] = i;
            this.tmpArray[i - 1] = 0;
        }
    }
    setTimeout(function(){scrollerinstance.start()}, 500);
}

Scroller.prototype.start=function(mouse){
    var scrollerinstance=this;
    if (mouse == true && !scrollerinstance.mousehover) {
        return;
    }
    if(scrollerinstance.elmArray.length  < 2){
        return;
    }
    if (!scrollerinstance.running) {
        if (scrollerinstance.expanded) {
            document.getElementById(scrollerinstance.parentId).style.height = scrollerinstance.parentHeight + "px";
            scrollerinstance.expanded = false;
        }
        scrollerinstance.intervalId = scrollerclear[scrollerinstance.objectId]=setInterval(function(){scrollerinstance.scroll();}, scrollerinstance.interval);
        scrollerinstance.running = true;
        scrollerinstance.mouseEvents(true);
    }
}

Scroller.prototype.stop=function(mouse){
    var scrollerinstance=this;
    if (scrollerinstance.running) {
        clearInterval(scrollerinstance.intervalId);
        scrollerinstance.running = false;
        scrollerinstance.mouseEvents(false);
    }
}

Scroller.prototype.mouseEvents=function(on) {
    var scrollerinstance=this;
    var scroller = document.getElementById(scrollerinstance.id);
    if (on) {
        scroller.onmouseover = scrollerinstance.mousestop.bind(scrollerinstance);
        scroller.onmouseout = scrollerinstance.mousestart.bind(scrollerinstance);
    } else {
        scroller.onmouseover = null;
        scroller.onmouseout = null;
    }
}

Scroller.prototype.mousestop = function() {
    var scrollerinstance = this;
    if (!scrollerinstance.expanded) {
        clearInterval(scrollerclear[scrollerinstance.objectId]);
        scrollerinstance.running = false;
    }
}

Scroller.prototype.mousestart = function() {
    var scrollerinstance = this;
    if (!scrollerinstance.expanded) {
        scrollerinstance.intervalId = scrollerclear[scrollerinstance.objectId]=setInterval(function(){scrollerinstance.scroll();}, scrollerinstance.interval);
        scrollerinstance.running = true;
    }
}

Scroller.prototype.toggleOnOff = function() {
    var scrollerinstance=this;
    if (scrollerinstance.running) {
        scrollerinstance.stop();
    } else {
        scrollerinstance.start();
    }
}

Scroller.prototype.toggleExpand = function() {
    var scrollerinstance=this;
    if (scrollerinstance.expanded) {
        scrollerinstance.start();
    } else {
        scrollerinstance.expand();
    }
}

Scroller.prototype.expand = function() {
    var scrollerinstance=this;
    scrollerinstance.stop();
    scrollerinstance.expanded = true;
    var scroll = document.getElementById(scrollerinstance.id);
    for (var i = 1; i <= scrollerinstance.lastChild; i++) {
        scroll.appendChild(document.getElementById(scrollerinstance.childId + i));
    }
    scroll.style.top = 0;

    var parent = document.getElementById(scrollerinstance.parentId);
    //save the old height
    scrollerinstance.parentHeight = parent.offsetHeight;
    //set the expanded height
    parent.style.height = scrollerinstance.totalHeight + "px";
}

Scroller.prototype.scroll = function() {
    var scrollerinstance=this;
    var scroll = document.getElementById(scrollerinstance.id);
    if (scrollerinstance.scrollposition >= scrollerinstance.scrollindex) {
        var pos = 0;
        for (var i = 0; i < scrollerinstance.elmArray.length; i++) {
            var _child = document.getElementById(scrollerinstance.childId + scrollerinstance.elmArray[i]);
            pos += _child.offsetHeight;
            scroll.appendChild(_child);
        }
        scroll.style.top = "0px";
        scrollerinstance.scrollposition = 1;

        scrollerinstance.tmpArray[0] = scrollerinstance.lastChild;
        for (var i = 1; i < scrollerinstance.tmpArray.length; i++) {
            scrollerinstance.tmpArray[i] = scrollerinstance.elmArray[i - 1];
        }
        scrollerinstance.lastChild = scrollerinstance.elmArray[scrollerinstance.elmArray.length - 1];
        if (document.getElementById(scrollerinstance.childId + scrollerinstance.lastChild) == null) {
            //there is an error getout
            scrollerinstance.stop();
        } else {
            scrollerinstance.scrollindex = scrollerinstance.totalHeight - document.getElementById(scrollerinstance.childId + scrollerinstance.lastChild).offsetHeight;
            for (var i = 0; i < scrollerinstance.tmpArray.length; i++) {
                scrollerinstance.elmArray[i] = scrollerinstance.tmpArray[i];
            }
        }
    } else {
        scrollerinstance.scrollposition += scrollerinstance.amount;
        scroll.style.top = (-1 * scrollerinstance.scrollposition) + "px";
    }
}
