var RokFlow = new Class({
	options: {
		show: 5,
		mouseAcceleration: Fx.Transitions.Cubic.easeIn,
		constantAt: 0,
		rate: 50,
		arrows: false,
		loader: 'loader',
		RokZoom: true,
		flow: {
			shrink: 0.5,
			spacing: 25,
			duration: 1000
		}
	},
	initialize: function (holder, options) {
		this.setOptions(options);
		if (this.options.loader) $(this.options.loader).remove();
		this.holder = $(holder).setStyle('background-image', 'none');
		this.build();
		this.flow = new Fx.Flow(this.container.getFirst(), $merge(this.options.flow, {
			RokZoom: this.options.RokZoom
		})).moveTo(1, this.options.show);
		this.setEvents()
	},
	build: function () {
		this.middle = this.holder.getCoordinates().left + this.holder.offsetWidth / 2;
		this.max = this.compute(this.options.constantAt);
		this.options.rate *= (Client.Engine.webkit) ? 0.5 : 1;
		var children = this.holder.getChildren();
		var trash;
		children.each(function (el) {
			trash = new Element('h3').setHTML(el.getElement('img').title || '&nbsp;').injectTop(el)
		});
		this.container = new Element('div').setStyles({
			'width': this.holder.offsetWidth,
			'height': this.holder.offsetHeight,
			'overflow': 'hidden'
		}).adopt(new Element('div').adopt(children)).inject(this.holder);
		this.holder.setStyles({
			'overflow': 'hidden',
			'cursor': 'default'
		});
		this.buildArrows()
	},
	setEvents: function () {
		this.moveEvents = {
			mousemove: function (e) {
				this.flow.move(((e.client.x < this.middle) ? 1 : -1) * (this.options.rate * this.compute(e.client.x).limit(0, this.max)) | 0);
				if (this.delay) $clear(this.delay);
				this.delay = (function () {
					this.container.fireEvent('mousemove', [e])
				}).delay(30, this)
			}.bind(this),
			mouseleave: function () {
				$clear(this.delay)
			}.bind(this)
		};
		this.container.addEvents(this.moveEvents);
		if (this.options.arrows) {
			this.larrow.addEvents({
				'click': this.flow.moveLeft.bind(this.flow),
				'mouseenter': function () {
					if (!this.hasClass('hover')) this.addClass('hover')
				},
				'mouseleave': function () {
					if (this.hasClass('hover')) this.removeClass('hover')
				}
			});
			this.rarrow.addEvents({
				'click': this.flow.moveRight.bind(this.flow),
				'mouseenter': function () {
					if (!this.hasClass('hover')) this.addClass('hover')
				},
				'mouseleave': function () {
					if (this.hasClass('hover')) this.removeClass('hover')
				}
			})
		}
		if (this.options.flow.RokZoom) {
			RokZoom.addEvents({
				'onClick': function () {
					this.container.removeEvent('mousemove', this.moveEvents.mousemove)
				}.bind(this),
				'onClose': function () {
					this.container.addEvent('mousemove', this.moveEvents.mousemove)
				}.bind(this)
			})
		}
	},
	compute: function (pos) {
		return this.options.mouseAcceleration(Math.abs(pos - this.middle) / this.middle)
	},
	buildArrows: function () {
		if (this.options.arrows) {
			this.larrow = new Element('div', {
				'class': 'arrow left'
			}).adopt(new Element('a', {
				'href': '#'
			}).setHTML('&larr')).injectTop(this.holder);
			this.rarrow = this.larrow.clone().set({
				'class': 'arrow right'
			}).inject(this.holder);
			this.holder.adopt(new Element('div', {
				styles: {
					clear: 'both'
				}
			}));
			this.rarrow.getElement('a').setHTML('&rarr;');
			this.container.setStyles({
				'width': this.holder.offsetWidth - 2 * this.larrow.offsetWidth
			})
		}
	}
});
RokFlow.implement(new Options, new Events);
Fx.Flow = Fx.Elements.extend({
	options: {
		RokZoom: false,
		shrink: 0.50,
		offset: 60,
		axis: 0.5,
		spacing: 25,
		transition: Fx.Transitions.linear,
		wait: false
	},
	initialize: function (el, options) {
		this.options = $merge(this.options, options);
		this.container = el.getParent();
		this.count = el.childNodes.length;
		this.setup(el, options);
		this.lefts = [];
		this.elements.each(function (el, i) {
			this.lefts[i] = (this.elements[1].getLast().offsetLeft + this.elements[1].getLast().offsetWidth) * (i - 1);
			el.set({
				id: 'flow-' + i,
				styles: {
					'position': 'absolute',
					'left': this.lefts[i]
				}
			})
		},
		this);
		this.middle = this.container.offsetWidth / 2;
		this.right = this.container.offsetLeft + this.container.offsetWidth;
		this.move(0);
		this.current = [1, 0]
	},
	setup: function (el, options) {
		this.min = [];
		this.diff = [];
		this.imgs = el.getElements('img');
		this.imgWidth = this.imgs[0].offsetWidth;
		this.imgs.each(function (img, i) {
			var max = {
				'width': img.offsetWidth,
				'height': img.offsetHeight
			};
			this.min[i] = {
				width: max.width * this.options.shrink,
				height: max.height * this.options.shrink
			};
			this.diff[i] = {
				width: max.width - this.min[i].width,
				height: max.height - this.min[i].height
			};
			img.setStyles(this.min[i])
		},
		this);
		this.divs = el.getChildren();
		this.count = this.divs.length;
		this.divs.each(function (child, i) {
			child.setStyles({
				'position': 'absolute',
				'left': child.offsetWidth * i,
				'top': this.container.offsetHeight * this.options.axis - child.offsetHeight / 2 + 0.5 * this.options.offset
			})
		},
		this);
		this.elements = [el, el.clone(), el.clone()];
		this.container.adopt(this.elements[1], this.elements[2]);
		this.parent(this.elements, options);
		this.spacing();
		this.imgs.each(function (img, i) {
			this.min[i].left = img.offsetLeft;
			this.min[i].top = el.childNodes[i].offsetTop
		},
		this);
		if (this.options.RokZoom) {
			this.container.getElements('a').each(function (a) {
				a.rel = 'rokzoom'
			});
			RokZoom.getLinks()
		}
	},
	moveTo: function (index, to) {
		var that = this,
		parsed = {},
		divs = this.elements[index].childNodes,
		by = this.middle - (this.elements[index].offsetLeft + divs[to].offsetLeft + 0.5 * (this.diff[to].width + this.min[to].width));
		(3).times(function (i) {
			parsed[i] = {
				left: [that.elements[i].offsetLeft, that.elements[i].offsetLeft + by]
			}
		});
		this.start(parsed);
		this.current = [index, to];
		return this
	},
	moveLeft: function () {
		this.current[1]--;
		if (this.current[1] < 0) {
			this.current[1] += this.count
		}
		return this.moveTo.apply(this, this.current)
	},
	moveRight: function () {
		this.current[1]++;
		if (this.current[1] >= this.count) {
			this.current[1] -= this.count
		}
		return this.moveTo.apply(this, this.current)
	},
	move: function (by) {
		var parsed = {},
		that = this;
		(3).times(function (i) {
			parsed[i] = {
				left: that.elements[i].offsetLeft + (isNaN(by) ? 0 : by)
			}
		});
		this.set(parsed)
	},
	reset: function () {
		var parsed = {},
		that = this;
		(3).times(function (i) {
			parsed[i] = {
				left: that.lefts[i]
			}
		});
		this.set(parsed)
	},
	increase: function () {
		this.parent();
		this.carousel();
		this.grow();
		this.spacing()
	},
	carousel: function () {
		var div, left = 1.5 * this.elements[0].offsetLeft + 0.5 * (this.elements[0].getLast().offsetLeft + this.elements[0].getLast().offsetWidth),
		right = 1.5 * this.elements[2].offsetLeft + 0.5 * (this.elements[2].getLast().offsetLeft + this.elements[2].getLast().offsetWidth);
		if (left > this.container.offsetLeft) {
			div = this.elements.pop();
			div.setStyle('left', this.elements[0].offsetLeft - div.getLast().offsetLeft + div.getLast().offsetWidth);
			this.elements = [div].concat(this.elements)
		} else if (right < this.right) {
			div = this.elements.shift();
			div.setStyle('left', this.elements[1].offsetLeft + length);
			this.elements.push(div)
		}
	},
	grow: function () {
		var growth, changeX, changeY, divs, curPos, off = (this.elements[1].offsetLeft < 0) ? 1 : 0,
		that = this;
		(2).times(function (i) {
			i += off;
			divs = that.elements[i].childNodes;
			that.elements[i].getElements('img').each(function (img, j) {
				curPos = that.elements[i].offsetLeft + divs[j].offsetLeft + img.offsetWidth / 2;
				if (curPos > 0 && curPos < that.right) {
					growth = that.growth(curPos);
					changeX = that.diff[j].width * growth;
					changeY = that.diff[j].height * growth;
					img.setStyles({
						'width': that.min[j].width + changeX,
						'height': that.min[j].height + changeY
					});
					divs[j].setStyles({
						'left': that.min[j].left - changeX / 2,
						'top': that.min[j].top - changeY / 2
					});
					divs[j].getElement('h3').setStyles({
						'width': that.min[j].width + changeX
					})
				}
			})
		})
	},
	spacing: function () {
		var divs, that = this;
		var B, A, D;
		(3).times(function (i) {
			divs = that.elements[i].childNodes;
			that.elements[i].getElements('img').each(function (img, j) {
				A = divs[j];
				if (j > 0) {
					B = divs[j - 1];
					B.setStyles({
						'left': A.offsetLeft - (that.options.spacing + B.offsetWidth)
					})
				}
				if (j < that.count - 1) {
					D = divs[j + 1];
					D.setStyles({
						'left': that.options.spacing + A.offsetLeft + A.offsetWidth
					})
				}
			})
		});
		B = this.elements[0];
		A = this.elements[1];
		D = this.elements[2];
		B.setStyles({
			'left': A.offsetLeft - (2 * that.options.spacing + B.getLast().offsetLeft + B.getLast().offsetWidth)
		});
		D.setStyles({
			'left': A.offsetLeft + 2 * that.options.spacing + A.getLast().offsetLeft + A.getLast().offsetWidth
		})
	},
	growth: function (pos) {
		return ((pos < this.middle) ? this.options.transition(pos / this.middle) : 1 - this.options.transition((pos - this.middle) / this.middle)).limit(0, Infinity)
	}
});
