var execArray = function(fnc) {
	if (!fnc) return;
	if (Object.isFunction(fnc)) return fnc();
	for (var fnc = $A(fnc),arr = [],i = 0; i < fnc.length; arr.push('fnc['+(i++)+']'));
	if (arr.length) if (fnc[0] != null && typeof fnc[0] == 'object' && Object.isFunction(fnc[0][fnc[1]]))
		with (arr) return new Function('fnc','return '+shift()+'['+shift()+']('+join(',')+')')(fnc);
	else with (arr) return new Function('fnc','return '+shift()+'('+join(',')+')')(fnc);
};
var getTransform = function(node,trans,Class) {
	if (!trans) return undefined;
	if (trans instanceof Class) return trans;
	else return new Class(node,trans,10,true);
};
var randName = function() {
	return 'r'+Math.random().toString().substr(2,8);
};
var isUndefined = function(obj) {
	return typeof obj == 'undefined';
};
var isElement = function(obj) {
	return Object.isElement(obj);
};
var falser = new Function('return false');

var Gallery = Class.create({
	initialize:function(viewport,storefront) {
		var myself = this,sys = {items:[],imgs:null};
		this.addItem = function(node,props,fader,hover) {
			if (sys.items.detect(function(item) {
				return item.node == node || $(item.node) == $(node);
			})) return myself;
			var item = {props:$H(props),node:node,fader:fader,hover:hover,width:null};
			return void(sys.items.push(item)) || myself;
		};
		this.showItem = function(index) {
			var node,item = sys.items[index],attachHover = function() {
				if (item.hover = getTransform(node,item.hover,Hover))
					item.hover.enableObserve();
				item.loaded = true;
			};
			if (!item || !Object.isElement(node = $(item.node))) return myself;
			if (Object.isNumber(item.width)) return myself;
			item.width = parseInt(node.getWidth());
			if (item.fader = getTransform(node,item.fader,Fader))
				item.fader.playForward(attachHover);
			else attachHover();
			return myself;
		};
		this.attachSlider = function(handle,track) {
			if (sys.control instanceof Control.Slider) sys.control.dispose();
			var fader,required,node = $(viewport),width = node?-node.getWidth()/2:0,
				track = $(track),handle = $(handle),obj = $(storefront);
			sys.items.each(function(item,node) {
				if (node = $(item.node)) width += item.width;
			});
			if (required = (width > 0 && track && handle && obj))
				handle.setStyle({cursor:'pointer'});
			with (sys.control = new Control.Slider(handle,track)) {
				options.onSlide = required?function(value) {
					if (fader) fader.rewind();
					obj.setStyle({left:-width*value+'px'});
				}:falser;
				options.onChange = required?function(value) {
					var tag = obj.tagName.toLowerCase(),
						a = -Math.round(width*value),b = parseInt(obj.getStyle('left')) || 0,x;
					with (Math) if ((x = floor((x = abs(abs(a)-abs(b)))/(1+2*log(1+200*x/width)))) < 2)
						return sys.control.setEnabled();
					if (!void(sys.control.setDisabled()) && fader) fader.rewind();
					with (fader = fader || obj.attachFader(null,10,false)) {
						getTransform().setSchema(tag+'::left('+b+'px>'+a+'px:'+x+' trend{1>5:log})');
						playForward([sys.control,'setEnabled']);
					};
				}:falser;
			};
			return sys.control;
		};
		this.getItem = function(index) {
			var item = sys.items[index];
			return item?item.props:undefined;
		};
		this.count = function() {
			return sys.items.length;
		};
		this.onLoad = function(fnc) {
			(function() {
				if (sys.items.find(function(item) {
					return !item.loaded;
				})) return setTimeout(arguments.callee,200);
				execArray(fnc);
			})();
		};
		Event.observe(window,'load',function() {
			sys.imgs = sys.imgs || sys.items.collect(function(item,node) {
				if (node = $(item.node)) return node.select('img').first();
			});
			var repeat = false;
			sys.imgs.each(function(node,i) {
				if (!node) return;
				if (node.complete !== true) repeat = true;
				else if (node.onload instanceof Function) {
					sys.imgs[i] = null;
					node.onload();
				}
			});
			if (repeat) setTimeout(arguments.callee,500);
		});
	}
});

var players = new Hash;
window.playerReady = function(obj) {
	var key,target = Prototype.Browser.IE?window:document;
	if ((obj = players.get(obj.id)) && isElement(obj.player = $(target[obj.name]))) {
		obj.player.addModelListener('meta',void(window[key = randName()] = function() {
			if (obj.hasMeta) return undefined;
			obj.toggleDisplay(obj.player.writeAttribute({height:obj.height,width:obj.width}));
			if (obj.noSlider) return obj.fader.rewind(void(obj.isIdle = true));
			if (obj.hasSlider) obj.track.setStyle({width:obj.width+'px'});
			obj.hasMeta = void(obj.fader.playForward(function() {
				if (obj.hasSlider) with (obj.slider = new Control.Slider(obj.handle,obj.track)) {
					if (obj.trans) obj.hover = obj.hover || attachHover(obj.trans);
					if (obj.hover instanceof Hover) obj.hover.enableObserve();
					options.onSlide = options.onChange = falser;
					disableJumps();
				};
				obj.isIdle = true;
			})) || obj.track.show();
		}) || key);
		obj.player.addModelListener('time',void(window[key = randName()] = function(data) {
			if (!obj.hasSlider) return undefined;
			var duration = parseInt(data.duration);
			obj.slider.setValue(parseInt(data.position)/duration,0,true);
			with (obj.slider.options) if (onSlide == falser) onSlide = function(value) {
				if (obj.prcLoaded < value) return false;
				if (obj.player) obj.player.sendEvent('seek',Math.round(duration*value));
			};
		}) || key);
		obj.player.addModelListener('loaded',void(window[key = randName()] = function(data) {
			obj.prcLoaded = parseInt(data.loaded)/parseInt(data.total);
			if (isElement(obj.buffer)) obj.buffer.setStyle({width:obj.prcLoaded*100+'%'});
		}) || key);
	};
};
var Player = Class.create({
	initialize:function(node,handle,track,buffer,config,fader,hover) {
		var myself = this,sys = {name:randName(),isIdle:true};
		sys.toggleDisplay = function(display) {
			if (isElement(node = sys.node = $(node)))
				node.setStyle({top:(display?sys.top:'-90000px') || 0});
			if (!display && isElement(sys.player))
				sys.player.sendEvent('play',false);
		};
		var loadPlayer = function() {
			(function() {
				if (!isElement(node = $(node) || node))
					return setTimeout(arguments.callee,500);
				sys.buffer = $(buffer);
				if (sys.hasSlider = (handle = sys.handle = $(handle)) && (track = sys.track = $(track))) {
					fader = sys.fader = getTransform(track,fader,Fader);
					hover = getTransform(track,hover,Hover);
					sys.trans = (hover instanceof Hover)?hover.getTransform():undefined;
				} sys.toggleDisplay(void(sys.top = node.makePositioned().getStyle('top')));
				with (new SWFObject('/commons/player/player.swf',sys.name,1,1,'9')) {
					addParam('flashvars','config=/commons/player/'+config+'.config');
					addParam('allowfullscreen','true');
					addParam('allowscriptaccess','always');
					addVariable('javascriptid',sys.name);
					addVariable('enablejs','true');
					write(node = node.id = randName());
					players.set(sys.name,sys);
				};
			})();
		};
		this.onPlayerReady = function(fnc) {
			(function() {
				if (sys.player) return execArray(fnc);
				else setTimeout(arguments.callee,500);
			})();
		};
		this.play = function(file,width,height,noSlider) {
			Object.extend(sys,{file:file,width:parseInt(width),height:parseInt(height),noSlider:noSlider});
			myself.onPlayerReady(function() {
				if (!sys.isIdle) return;
				if (sys.slider instanceof Control.Slider)
					sys.slider = void(sys.slider.dispose());
				sys.isIdle = void(sys.toggleDisplay(false));
				var loadFile = function() {
					if (sys.hasSlider && track.hide()) handle.setStyle({cursor:'pointer',left:0});
					sys.buffer.setStyle({width:sys.prcLoaded = 0});
					sys.hasMeta = void(sys.player.sendEvent('load',sys.file));
				};
				var unsetFader = function() {
					if (sys.fader instanceof Fader) {
						var last = sys.fader.getTransform().getLastPlay();
						if (isUndefined(last)) loadFile();
						else sys.fader.playBackward(loadFile);
					} else loadFile();
				};
				if (sys.hover instanceof Hover) {
					var last = sys.hover.getTransform().getLastPlay();
					sys.hover.disableObserve();
					sys.hover.immediateStop();
					if (isUndefined(last)) unsetFader();
					else sys.hover.playBackward(unsetFader);
				} else unsetFader();
			});
		};
		loadPlayer();
	}
});
