﻿window.blockslider = {};
var BlockSlider = function(id, options) {
    this.setDom(id);    
    this.setOptions(options);
    this.init();
}
BlockSlider.Block = function(block) {
    this.setDom(block);
    
}
BlockSlider.Block.prototype = {
    dom: null,
    jq: null,
    visible: false,
    partialVisible: false,
    _width: 0,
    setDom: function(b) {
        this.jq = jQuery(b).wrap(jQuery("<div />")).parent();
        this.jq.css("position", "absolute");
        this.dom = this.jq.get(0);
        this.width(this.jq.outerWidth(true));
    },
    setVisible: function(b) { this.visible = b; if (b) this.partialVisible = false; },
    setPartialVisible: function(b) { this.partialVisible = b; },
    isVisible: function() { return this.visible; },
    isPartialVisible: function() { return this.partialVisible; },
    isHidden: function() { return !this.visible && !this.partialVisible; },
    width: function(w) { if (w != null) this._width = w; else return this.jq.outerWidth(true); },
    left: function(l) { if (l != null) this.jq.css('left', l + 'px'); else return parseInt(this.jq.css('left').replace('px',''));}
}
BlockSlider.prototype = {
	dom: null,
	jq: null,
	setDom: function (d) { if (typeof d == 'string') d = document.getElementById(d); this.dom = d; this.jq = $(d); },
	init: function () {
		var sb = this;
		this.jq.mouseover(function () { sb.mouseOver(); });
		this.jq.mouseout(function () { sb.mouseOut(); });
		this.blocks = [];
		var blocks = this.dom.childNodes;
		// Create BlockSlider.Block elements for each block
		for (var i = 0; i < blocks.length; ++i) {
			if (blocks[i].nodeType == 1) // element node
				this.blocks[this.blocks.length] = new BlockSlider.Block(blocks[i]);
		}

		// set absolute position for each block and calculate total width
		var width = 0;
		for (var i = 0; i < this.blocks.length; ++i) {
			this.blocks[i].left(width);
			var partialVisible = false;
			if (width < this.jq.width())
				partialVisible = true;
			width += this.blocks[i].width();

			if (width < this.jq.width())
				this.blocks[i].setVisible(true);
			else if (partialVisible)
				this.blocks[i].setPartialVisible(true);
		}

		this.startRotation();
	},
	setOptions: function (options) {
		this.options = {
			rotationCurrentSpeed: 0,
			rotationTargetSpeed: 1,
			rotationAcceleration: 10,
			rotationInterval: 10
		}
		if (options.prev)
			this.setPrevButton(options.prev);
		if (options.next)
			this.setNextButton(options.next);
		if (options.speed)
			this.options.rotationTargetSpeed = parseInt(options.speed);
		if (options.acceleration)
			this.options.rotationAcceleration = parseInt(options.acceleration);
		if (options.interval)
			this.options.rotationInterval = parseInt(options.interval);
	},
	mouseOver: function (e) { this.pauseRotation(); },
	mouseOut: function (e) { this.startRotation(); },

	/*
	Rotation stuff
	*/
	rotationTimer: null,
	isRotating: false,
	isStopping: false,
	startRotation: function () {
		if (this.isRotating)
			return;
		var totalBlocksWidth = 0;
		jQuery.each(this.blocks, function (idx, val) { totalBlocksWidth += val.width(); });

		if (totalBlocksWidth <= this.jq.width())
			return;
		if (this.rotationTimer == null) {
			var me = this;
			this.rotationTimer = setInterval(function () { me.tick(); }, this.options.rotationInterval);
		}
		this.isRotating = true;
	},
	pauseRotation: function () {
		if (!this.isRotating)
			return;
		clearInterval(this.rotationTimer);
		this.rotationTimer = null;
		this.isRotating = false;
	},
	tick: function () {
		if (this.options.rotationCurrentSpeed != this.options.rotationTargetSpeed) {
			this.options.rotationCurrentSpeed += this.options.rotationAcceleration;
		}
		if (this.options.rotationCurrentSpeed > this.options.rotationTargetSpeed) {
			this.options.rotationCurrentSpeed = this.options.rotationTargetSpeed;
		}
		this.rotateBlocks(this.options.rotationCurrentSpeed);
	},
	rotateBlocks: function (offset) {
		var me = this;
		var leftPosMap = {};
		jQuery.each(this.blocks, function (idx, val) {

			var nextIdx = idx + 1;
			var prevIdx = idx - 1;

			if (nextIdx > me.blocks.length - 1)
				nextIdx = 0;

			if (prevIdx < 0)
				prevIdx = me.blocks.length - 1;

			var newLeft = val.left() + offset;
			// block is out to the right?
			if (newLeft > me.jq.width() && offset > 0) {

				val.setVisible(false);
				val.setPartialVisible(false);
				var next = me.blocks[nextIdx];
				newLeft = next.left() - val.width() + offset;

				// block is out to the left?
			} else if (newLeft + val.jq.width() < 0 && offset < 0) {

				val.setVisible(false);
				val.setPartialVisible(false);
				var prev = me.blocks[prevIdx];
				newLeft = prev.left() + prev.jq.width() + offset;

				// block is partial out on any side
			} else if (newLeft + val.width() > me.jq.width() || newLeft < 0) {

				val.setVisible(false);
				val.setPartialVisible(true);

				// block is completly visible
			} else {
				val.setVisible(true);
			}
			leftPosMap[idx] = newLeft;
		});

		for (var i in leftPosMap) {
			this.blocks[i].left(leftPosMap[i]);
		}
	},
	goNext: function () {
		this.pauseRotation();
		var firstVisibleFound = -1;
		var target = null;
		for (var i = 0; i < this.blocks.length; ++i) {
			if (firstVisibleFound < 0 && this.blocks[i].isVisible()) {
				firstVisibleFound = i;
				continue;
			}
			if (firstVisibleFound > -1 && !this.blocks[i].isVisible()) {
				target = this.blocks[i];
				break;
			}
		}
		if (target == null)
			target = this.blocks[0];

		// Calculate how much we must rotate
		var offset = target.width() - (this.jq.width() - target.left());
		this.rotateBlocks(-offset);
	},
	setNextButton: function (id) {
		var me = this;
		var nextb = jQuery(document.getElementById(id));

		nextb.mouseover(function () { me.pauseRotation(); });
		nextb.mouseout(function () { me.startRotation(); });
		nextb.click(function (e) { e.preventDefault(); me.goNext(); return false; });
	},
	goPrev: function () {
		this.pauseRotation();
		var firstVisibleFound = -1;
		var target = null;
		for (var i = this.blocks.length - 1; i >= 0; --i) {
			if (firstVisibleFound < 0 && this.blocks[i].isVisible()) {
				firstVisibleFound = i;
			} else if (firstVisibleFound > -1 && !this.blocks[i].isVisible()) {
				target = this.blocks[i];
				break;
			}
		}
		if (target == null)
			target = this.blocks[this.blocks.length - 1];

		// Calculate how much we must rotate
		var offset = target.left();
		this.rotateBlocks(-offset);
	},
	setPrevButton: function (id) {
		var me = this;
		var prevb = jQuery(document.getElementById(id));
		prevb.mouseover(function () { me.pauseRotation(); });
		prevb.mouseout(function () { me.startRotation(); });
		prevb.click(function (e) { e.preventDefault(); me.goPrev(); return false; });
	}
}
