var FlashSlideShow = Class.create({
	initialize: function(elm, options){
		this._options = Object.extend({
			interval: 0.15
		}, options || {})
		this._element = $(elm);
		if( this._element ){
			this._loading_elements = $$('.' + this._element.identify() + '_loading');
			this._pe = null;
		}
	},
	startAnimation: function(){
		this.stopAnimation();
		//this._pe = new PeriodicalExecuter(this.doAnimation.bind(this), this._options.interval);
		this._pe = true;
		this.doAnimation();
	},
	doAnimation: function(){
		//this._element.doAnimation();
		if( this._pe ){
			this._element.doAnimation();
			this.doAnimation.bind(this).delay(this._options.interval);
		}
	},
	stopAnimation: function(){
		if( this._pe ){
			//this._pe.stop();
			this._pe = false;
		}
	},
	beforeLoad: function(){
		debugit('beforeLoad');
		/* hiding the element makes the movie clip loads fail SILENTLY */
		//this._element.hide();
		this._loading_elements.invoke('show');
		this.stopAnimation();
	},
	afterLoad: function(){
		debugit('got here!');
		this.startAnimation();
		this._loading_elements.invoke('hide');
		debugit('got here too!');
		//this._elment.show();
	},
	setJavascriptFunction: function( name, func){
		this._element.setJavascriptFunction(name, func);
	},
	loadImages: function(images){
		if( this._element ){
			debugit( 'element: ' + this._element);
			if( this._element.loadImages ){
				debugit( 'loadImages defined: ' + typeof(this._element.loadImages));
				this._element.loadImages(images);
			}else{
				debugit( typeof(this._element));
				debugit( typeof(this._element.loadImages));
			}
		}
	}
});

var SlideShow = Class.create(PSLib.Animation.AutoOpenCloseCollection, {
	initialize: function($super, container, collection_options, options, open_options, close_options){
		this.directions = [-1, 1];
		this.positions = [0, -1, -0.5];
		this._element_data = $H();
		this._images = $A();
		this._imgonload = null;
		open_options = Object.extend(open_options, {
			options: {
				beforeStart: this.beforeOpen.bind(this)
			}
		});
		close_options = Object.extend(close_options, {
			options: {
				afterFinish: this.afterClose.bind(this)
			}
		});
		this._delta = Object.isUndefined(collection_options.delta)?0.5:collection_options.delta;
		this._animation_interval = Object.isUndefined(collection_options.interval)?0.20:collection_options.interval;
		$super( container, collection_options, options, open_options, close_options);
		
		this._loading_elements = $$('.' + this._container.readAttribute('id') + '_loading');
		/* resize all the images here and determine positions and directions here
		 * store all data in the element_data hash
		 */
		this._setElementData();
		var current = this.getCurrent();
		if( current ){
			this._startAnimation(current.getElement());
		}
		/* hide loading, show content */
		this._toggleLoading(false);
	},
	
	beforeOpen: function( eff ){
		/* resize eff.element and start animation */
		if( eff.element ){
			this._startAnimation( eff.element )
		}
	},
	
	startSlideShow: Prototype.emptyFunction,
	pauseSlideShow: Prototype.emptyFunction,
	
	_setElementData: function(){
		var dims;
		if( Prototype.Browser.IE ){
			debugit('IE!');
			var s = $A();
			this._elements.invoke('getElement').each( function(e){
				if( e.getStyle('display') != 'none'){
					e.hide();
					s.push(e);
				}
			});
			dims = this._container.getDimensions();
			debugit('dims: ' + dims.width + ', ' + dims.height);
			s.invoke('show');
		}else{
			dims = this._container.getDimensions();
		}
		
		this._elements.invoke('getElement').each( function(e){
			var diffs, dirs, img, pos;
			img = e.down('img');
			if( img ){
				debugit('resizing element: ' + e.readAttribute('id'));
				diffs = this._resizeElement(dims, img);
				pos = this._setPosition(img, diffs.x, diffs.y);
				dirs = this._getDirections();
				this._element_data.set( e.readAttribute('id'), {
					diff_x: diffs.x,
					diff_y: diffs.y,
					dir_x: dirs.x,
					dir_y: dirs.y,
					pe: null,
					left: pos.x,
					top: pos.y
				});
				this._images.push(img.readAttribute('src'));
			}else{
				debugit('no image found');
			}
		}, this);
	},
	
	_getDirections: function(){
		var index;
		var dir_x = this.directions[Math.round(Math.random())];
		var dir_y = this.directions[Math.round(Math.random())];
		debugit( 'dirs: ' + dir_x + ', ' + dir_y);
		return {x: dir_x, y: dir_y};
	},
	
	_setPosition: function(elm, diff_x, diff_y){
		if (elm) {
			elm.makePositioned();
			var pos_x = Math.floor(Math.random() * 3);
			var pos_y = Math.floor(Math.random() * 3);
			
			pos_x = Math.round(this.positions[pos_x] * diff_x);
			pos_y = Math.round(this.positions[pos_y] * diff_y);
			elm.setStyle({
				top: pos_y + 'px',
				left: pos_x + 'px'
			});
			return {x: pos_x, y: pos_y};
		}
	},
	
	afterClose: function( eff ){
		/* stop animation of the element */
		this._stopAnimation(eff.element);
	},
	
	_resizeElement: function( dims, elm ){
		/* we will have containing div and image inside
		 * image should have position relative and be larger than containing div.
		 * it's position will be animated within the bounds of the slideshow container
		 */
		/*var dims = celm.getDimensions();*/
		debugit('celm dims: ' + dims.width + ', ' + dims.height);
		var hidden = elm.getStyle('display') == 'none'?1:0;
		var elm_dims = elm.getDimensions();
		debugit('img dims: ' + elm_dims.width + ', ' + elm_dims.height);
		if( !elm_dims.width || !elm_dims.height ){
			var temp = new Image();
			temp.src = elm.readAttribute('src');
			elm_dims.width = temp.width;
			elm_dims.height = temp.height;
		}
		debugit('img dims: ' + elm_dims.width + ', ' + elm_dims.height);
		var add_to = 2 * Math.round(this._delta * ( this._time / this._animation_interval));
		debugit('add to: ' + add_to);
		var new_height, new_width;
		new_height = new_width = 0;
		
		if( elm_dims.width && elm_dims.height && dims.width/dims.height < elm_dims.width/elm_dims.height){
			new_height = dims.height + add_to;
			new_width = new_height * elm_dims.width / elm_dims.height;
		}else{
			new_width = dims.width + add_to;
			if( elm_dims.width && elm_dims.height){
				new_height = new_width * elm_dims.height / elm_dims.width;	
			}
		}
		var diff_x, diff_y;
		var obj = {};
		diff_x = diff_y = 0;
		if( new_width ){
			obj.width = new_width + 'px';
			diff_x = Math.floor(new_width - dims.width);
		}
		if( new_height ){
			obj.height = new_height + 'px';
			diff_y = Math.floor(new_height - dims.height);
		}
		debugit('new: ' + new_width + ', ' + new_height);
		elm.setStyle(obj);
		return {'x': diff_x, 'y': diff_y};
	},
	
	_startAnimation: function( elm ){
		var e = elm;
		var id = e.readAttribute('id');
		//debugit('element id: ' + id);
		if( id ){
			var data = this._element_data.get(id);
			if( data ){
				/*data.pe = new PeriodicalExecuter( function(pe){
					this._doAnimation(e);
				}.bind(this), this._animation_interval);*/
				data.pe = true;
				this._doAnimation.bind(this).delay( this._animation_interval, e, data);
			}else{
				//debugit('_startAnimation: no data for element ' + id);
			}
		}else{
			//debugit('_startAnimation: elment does not have an id');
		}
	},
	
	_doAnimation: function(elm, data){
		/* move the item by delta and check for bounding */
		//debugit('_doAnimation: ' + elm + ', ' + elm.readAttribute('id'));
		var obj = this._element_data.get(elm.readAttribute('id'));
		if( obj ){
			//debugit('_doAnimation: before down');
			var img = elm.down('img');
			//debugit('_doAnimation: after down');
			if (img) {
				obj.left = obj.left + this._delta * obj.dir_x;
				obj.top = obj.top + this._delta * obj.dir_y;
				//debugit('_doAnimation: set new position');
				var left = obj.left; //Math.round(obj.left);
				var top = obj.top; //Math.round(obj.top);
				//debugit('_doAnimation: got rounded values');
				//debugit(obj.dir_x + ', ' + obj.dir_y);
				if (left > 0) {
					left = 0;
					obj.dir_x = -obj.dir_x;
				}
				else{
					if (left < -obj.diff_x) {
						left = -obj.diff_x;
						obj.dir_x = -obj.dir_x;
					}
				}
				if (top > 0) {
					top = 0;
					obj.dir_y = -obj.dir_y;
				}
				else {
					if (top < -obj.diff_y) {
						top = -obj.diff_y;
						obj.dir_y = -obj.dir_y;
					}
				}
				img.setStyle({
					'top': top + 'px',
					'left': left + 'px'
				});
				if( data && data.pe == true){
					this._doAnimation.bind(this).delay( this._animation_interval, elm, data);
				}
			}else{
				//debugit('_doAnimation: could not find img element');
			}
		}else{
			//debugit('_doAnimation: no data found for element ' + elm.readAttribute('id'));
		}
	},
	
	_stopAnimation: function( elm ){
		/* kill timeout of interval in animation hash */
		var id = elm.readAttribute('id');
		var data = this._element_data.get(id);
		if( data && data.pe ){
			//data.pe.stop();
			data.pe = false;
		}
	},
	
	_unload: function(){
		/* remove all keys from hash */
		this._element_data.keys().each( function(k){
			var temp = this._element_data.get(k);
			try{
				temp.pe.stop();
			}catch(ex){
				//debugit('no periodical executer!');
			}
			this._element_data.unset(k);
		}, this);
		this._images.clear();
		
		/* stop auto fade */
		this.stop();
		this._elements.invoke('getElement').invoke('remove');
	},
	
	_toggleLoading: function( on ){
		if( on ){
			this._loading_elements.invoke('show');
			this._container.hide();
		}else{
			this._container.show();
			this._loading_elements.invoke('hide');
		}
	},
	
	_startAfterLoad: function( start_index, current, temp){
		try{
			if( Prototype.Browser.IE){
				delete temp.onload;
				temp.onload = null;
				this._imgonload = null;
			}else{
				if( this._imgonload){
					temp.stopObserving(this._imgonload);
					this._imgonload = null;
				}
			}
		}catch(ex){
			debugit('stop observing exception: ' + ex);
		}
		this.start();
		this._startAnimation(current);
		this._toggleLoading(0);
	},
	
	_compareImages: function(images){
		if( this._images.length == images.length){
			debugit('equal length');
			for( var i=0; i<this._images.length; i++){
				if( images.indexOf(this._images[i]) == -1){
					return false;
				}
			}
			return true;
		}else{
			return false;
		}
	},
	
	loadImagesHTML: function( url, start_index){
		
	},
	
	loadImages: function(images){
		if( Object.isArray(images) && !this._compareImages(images)){
			this._toggleLoading(1);
			this._unload();
			
			var l = images.length;
			if( Object.isUndefined(start_index) || start_index < 0 || start_index >= l){
				start_index = 0;
			}
			for( var i=0; i<l; i++){
				var temp = new Element('div', {'class': 'item', 'id': 'img' + i});
				temp.insert( new Element('img', {'src': images[i], 'alt': images[i]}));
				this._container.insert(temp);
			}
			this.update();
			this._setElementData();
			
			var current = this.getCurrent();
			var start_index = -1;
			if( current ){
				start_index = this._elements.indexOf(current);
			}
			for( var i=0; i<l; i++){
				var temp = new Image();
				if( i == start_index ){
					debugit('found start index: ' + i);
					/*if( Prototype.Browser.IE ){
						temp.onload = function(){
							this._startAfterLoad(start_index, current.getElement(), temp);
						}.bind(this);
					}else{
						temp.observe('load', function(){
							this._startAfterLoad(start_index, current.getElement(), temp);
						}.bind(this));
					}*/
					this._imgonload = this._startAfterLoad.bind(this, start_index, current.getElement(), temp);
					if( Prototype.Browser.IE ){
						temp.onload = this._imgonload;
					}else{
						temp.observe('load', this._imgonload);
					}
				}
				temp.src = images[i];
			}
		}
	}
});
