/**
 * @author Alexey Androsov <messie at cs-knopka dot ru>
 * @version 0.1
 */

/**
 * Text scroller
 * 
 * @param {Object} _node
 * @param {Array} _texts
 */
var Scroller = function(_node, _texts){
//static	
	this.timeout = 200;
//
	this.node = _node;
	this.texts = _texts;
	this.init();
}

Scroller.prototype = new function(){
// constructor	
	this.init = function(){
		this.node.style.height = this._getHeight(this.node) + 'px';
		this.node.style.overflow = 'hidden';
		
		this.setText();
		this.setEvents();
	}
	
	this.setText = function() {
		var text = '<div id="scroller_block" class="scroller_texts" style="position:absolute;top:'+this.node.style.height+';">';
		for (var i=0, j=this.texts.length; i<j; i++) {
			text += this.texts[i];
			text += '<div class="scroller_delimeter"></div>';	
		}
		text += '</div>';
		this.node.innerHTML = text;
		this.scrollBlock = document.getElementById('scroller_block');
		this.scrollBlock.style.height = this._getHeight(this.scrollBlock) + 'px';
	}
	
	this.setEvents = function() {
		this.executer = new PeriodicalExecuter(this._scrollText.bind(this), 0.1);
	}
	
// private
	this._scrollText = function() {
		if ( parseFloat(this.scrollBlock.style.top) <= -1*parseFloat(this.scrollBlock.style.height) ) {
			this.scrollBlock.style.top = this.node.style.height;
		} else {
			this.scrollBlock.style.top = parseFloat(this.scrollBlock.style.top) - 1 + 'px';
		}
	}

	this._getHeight = function(element) {
		var els = element.style;
		var originalVisibility = els.visibility;
		var originalPosition = els.position;
		var originalDisplay = els.display;
		els.visibility = 'hidden';
		els.position = 'absolute';
		els.display = 'block';
		var originalHeight = element.clientHeight;
		els.display = originalDisplay;
		els.position = originalPosition;
		els.visibility = originalVisibility;
		return originalHeight;
	}
}

/*************************************************/
var Class = {
  create: function() {
    return function() {
      this.initialize.apply(this, arguments);
    }
  }
}

Function.prototype.bind = function() {
  var __method = this, args = $A(arguments), object = args.shift();
  return function() {
    return __method.apply(object, args.concat($A(arguments)));
  }
}

var PeriodicalExecuter = Class.create();
PeriodicalExecuter.prototype = {
  initialize: function(callback, frequency) {
    this.callback = callback;
    this.frequency = frequency;
    this.currentlyExecuting = false;

    this.registerCallback();
  },

  registerCallback: function() {
    this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
  },

  stop: function() {
    if (!this.timer) return;
    clearInterval(this.timer);
    this.timer = null;
  },

  onTimerEvent: function() {
    if (!this.currentlyExecuting) {
      try {
        this.currentlyExecuting = true;
        this.callback(this);
      } finally {
        this.currentlyExecuting = false;
      }
    }
  }
}

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;
  }
}
