var InfiniteCarousel = new Class({

	container: null,
	inner: null,
	animate: null,
	nav: null,

	data: null,
	timer: null,
	ticks: -1,

	options: {
		width: 624,
		height: 282,
		delay: 5100,
		duration: 1200,
		meubius: false,
		transition: Fx.Transitions.Sine.easeInOut,
		structure: {
			header: "h3",
			data: ".carousel-data",
			link: "p a",
			img: "img"
		},
		data: null
	},

	Implements: [Options],

	initialize: function (container, options) {
		this.setOptions(options);
		this.container = document.id(container);
		this.parseData();
		this.setup();
	},

	parseData: function () {

		var data = [];
		if (this.options.data == null) {
			var re = new RegExp(".+(sticker-.+)", "");

			this.container.getElements(this.options.structure.data).each(function (el, i) {
				var slide = {},
				link = el.getElement(this.options.structure.link),
				img = el.getElement(this.options.structure.img);
				slide.title = el.getElement(this.options.structure.header).get("text");
				slide.desc = link.get("text");
				slide.url = link.get("href");
				slide.img = img.get("src");
				slide.alt = img.get("title");
				slide.rel = link.get("rel");
				slide.index = i;
				slide.sticker = '';

				var myArray = el.get('class').match(re);
				if (myArray && myArray.length > 1) {
					slide.sticker = ' ' + myArray[1];
				}

				data.push(slide); // Because I don't trust data[] = slide; in js.
			},
			this);
		}

		this.data = data;
		this.container.empty();

	},

	setup: function () {

		/*
			I didn't want to make this a String method so I'll make my own private method.
			elementize: return an element based on a string.
		*/
		function elementize(string) {
			return new Element("div", {
				html: string
			}).getFirst();
		}

		// Set the container's width, add class
		this.container.setStyle("width", '100%' /*this.options.width * 3*/).addClass("carousel");

		// Make an inner container, set width and height.
		this.inner = new Element("div", {
			"class": "carousel-inner",
			"styles": {
				"width": "100%"/*this.options.width * 3*/,
				"height": this.options.height + 40
			}
		});
		// Container grabs inner.
		this.container.grab(this.inner);
		// Make the animate div.
		this.animate = new Element("div", {
			"class": "carousel-animate",
			"styles": {
				"margin-left": (Browser.Engine.gecko ? "0" : "-8px"),
				"width": this.options.width
			}
		}).set("tween", {
			duration: this.options.duration,
			transition: this.options.transition
		});
		// Inner Container grabs this one.
		this.inner.grab(this.animate);

		// Get the link elements in the container.
		var slides = this.data;

		/*
			So we know how much space to allot.
		*/
		this.animate.setStyle("width", this.options.width * slides.length);

		// Make the separate blocks here.
		slides.each(function (data, i) {
			var biglink_data = {
				url: data.url,
				img: data.img,
				height: this.options.height,
				width: this.options.width,
				title: data.title,
				desc: data.desc,
				sticker: data.sticker
			},
			biglink = ('<a class="carousel-item{sticker}" href="{url}"><img src="{img}" height="{height}" width="{width}" border="0" /><span class="carousel-item-info"><strong><span class="FuturaFuturisC-Bold">{title}</span></strong><br /><span>{desc}</span></span></a>').substitute(biglink_data);
			biglink = elementize(biglink);

			biglink.setStyle("width", this.options.width).set("rel", data.rel);

			this.animate.grab(biglink);
		},
		this); // This links.each loop is bound to _THIS_.

		this.tick();
	},

	/*
		The recuring function that triggers the slides to move.
			Removes selected class
			Adds selected class to whatever needs it
			Runs the tween
			Increments tick or resets it
			Clears and restarts timer.
	*/
	tick: function () {
		this.slide(this.ticks); // Start it up.

		// Increment.
		this.ticks++;

		// Remember, (links.length-1) looks stupid but length doesn't _really_ start at 0.
		// If tick meets the length-1 of the links, restart.
		if (this.ticks > ($$('.carousel-animate').getChildren()[0].length - 1)) {
			this.ticks = 0;
		}
		$clear(this.timer);
		this.timer = this.tick.delay(this.options.delay, this); // Set.
	},

	events: {
		over: function (event) {
			// Mouseenter: when they move over the block.
			var data = event.target.getParent().retrieve("data", {
				index: 0
			});
			// Set tick to the current block.
			//this.ticks = data.index;
			this.tick();
			$clear(this.timer); // This clear pauses movement until mouseleave.
		},
		out: function (event) {
			// Resume movement.
			this.timer = this.tick.delay(this.options.delay, this);
		}
	},

	slide: function (tick) {
		// This animates the slides
		if (!this.options.meubius) {
			this.animate.tween("left", (document.id('infinite-carousel').getWidth() - this.options.width) / 2 - (this.ticks * this.options.width));
		} else {
			var width = document.id('first-menu').getPosition().x;
			if (Browser.Engine.name != 'gecko') {
				width += 8;
			}

			this.animate.getChildren()[0].inject(this.animate);
			if (tick < 0) {
				this.animate.setStyle("left", width - (2 * this.options.width));
			} else {
				this.animate.setStyle("left", width - (this.options.width));
				this.animate.tween("left", width - (2 * this.options.width));
			}
		}
	}

});

