Object.extend(Function.prototype, {
	onLoad: function() {
		Event.observe(window, "load", this);
	}
});
function showImage(n) {
	i = 0;
	while (true) {
		var im = $("imagechanger_"+i);
		if (!im) break;
		if (i == n) 	Element.show(im);
		else			Element.hide(im);
		i++;
	}
	return false;
}
function copyBillingToDelivery() {
	["name", "telephone", "address_1", "address_2", "address_3", "address_4", "city", "county", "postcode", "country"].each(function(x) {
			try {
				$('el_delivery_'+x).value=$('el_'+x).value;
			} catch (e) {}
	});
}

function selectMetadata(md, id, value) {
	var el = $("metadata-"+md+"-"+id);
	if (el.nodeName == "SELECT") {
		for (n = 0; n < el.options.length; n++) {
			if (el.options[n].value == value)
				el.selectedIndex = n;
		}
	}
}

var rotators = []

function rotateItems(els, num, options) {
	if (typeof(els) != "object")
		els = [els];
	els.each(function(el) {
		r = new ItemRotator(el, num, options || {})
		rotators.push(r);
	});
}

if (typeof(Class) != "undefined") {
	var ItemRotator = Class.create({
		pos: 0,
		initialize: function (el, num) {
			this.options = Object.extend({
				num: num,
				duration: 10,
				fade_duration: 1,
				async: false,
				absolutize: false
			}, arguments[2] || { });
			this.el = $(el);
			this.items = this.el.select(".rotate_item");
			if (this.items.length <= this.options.num) {
				this.items.each(function(el) {
					Element.show(el);
				});
				return;
			}

			this.items.each(function(el) {
				Element.remove(el);
			});
			for (var n = 0; n < this.options.num; n++) {
				this.el.appendChild(this.items[n]);
				Element.show(this.items[n]);
			}
			if (!this.options.async)
				this.pos = n;
			window.setTimeout(this.performRotate.bind(this), this.options.duration * 1000);
			if (this.options.async)
				this.options.duration /= this.options.num;
		},
		performRotate: function() {
			this.options.async ? this.asyncRotate() : this.syncRotate();
		},
		// {{{
		syncRotate: function() {
			var to_hide = [];
			var to_show = [];
			this.items.each(function(el, n) { // Hide all items
				if (Element.visible(el))
					to_hide.push(n);
			});
			var hide_effects = [];
			var show_effects = [];
			to_hide.each(function(n) {
				var next_el = this.loop(n+this.options.num, this.items.length);
				hide_effects.push(new Effect.Fade(this.items[n], {
					sync: true,
					afterFinish: function() {
						this.items[n].insert({ before: this.items[next_el]});
						Element.remove(this.items[n]);
					}.bind(this)
				}));
				to_show.push(next_el);
			}.bind(this));
			new Effect.Parallel(hide_effects, {
				duration: 1,
				afterFinish: function() {
					to_show.each(function(n) {
						show_effects.push(new Effect.Appear(this.items[n], { sync: true }));
					}.bind(this));
					new Effect.Parallel(show_effects, {
						duration: 1,
						afterFinish: function() {
							window.setTimeout(this.performRotate.bind(this), this.options.duration * 1000);
						}.bind(this)
					});
				}.bind(this)
			});
		},
		// }}}
		asyncRotate: function(inc) {
			if (this.timer) {
				window.clearTimeout(this.timer);
				this.timer = false
			}
			var num = inc ? inc : this.options.num;
			// This should be easy
			if (this.options.absolutize)
				$A(this.el.getElementsByClassName("rotate_item")).reverse().each(function(el) { el.absolutize() });

			cb2 = function() {
				this.timer = window.setTimeout(this.performRotate.bind(this), this.options.duration * 1000);
				this.pos = inc ? next_el : this.loop(this.pos+1, this.items.length); // XXX: May need to set this beforeStart
			}
			cb1 = function() {
				// Append next
				var next_el = this.loop(this.pos + num, this.items.length);
				this.items[this.pos].insert({ before: this.items[next_el]});
				Element.remove(this.items[this.pos]);

				this.items[next_el].setOpacity(0);
				Element.show(this.items[next_el]);

				if (this.options.absolutize)
					$A(this.el.getElementsByClassName("rotate_item")).reverse().each(function(el) { Element.staticize(el); });

				if (this.options.duration)
					new Effect.Appear(this.items[next_el], {
						duration: this.options.fade_duration,
						afterFinish: cb2.bind(this)
					});
				else
					cb2.bind(this)();
			}

			if (this.options.duration)
				new Effect.Fade(this.items[this.pos], {
					duration: this.options.fade_duration,
					afterFinish: cb1.bind(this)
				});
			else
				cb1.bind(this)();
		},
		prev: function() {
			this.asyncRotate(-1);
		},
		next: function() {
			this.asyncRotate();
		},
		loop: function(n, max) {
			if (n >= max)
				n -= max;
			if (n < 0)
				n += max;
			return n;
		}
	});
}

