var Flickr = new Class({
	/**
	 * class constructor
	 * @param string id
	 * @param object opt
	 */
	initialize: function(id,opt) {
		this.opts(id,opt); 
		this.setupSlider(); 
		this.indicator.setStyle('display','block'); 
		document.addEvent('keydown',this.keyListener.bind(this));
		/*document.addEvent('contextmenu', this.preventRightClick.bind(this));*/
		if(window.location.hash) {
			var pos = String(window.location.hash).substr(1); 
			var set = this.whichSet(pos); 
			var set_pos = this.whichSetPos(pos); 
			this.loadImg(this.opt.imgs[set].photos[set_pos].md,pos); 
		}
	},
	/**
	 * set class params
	 * @param string id
	 * @param object opt
	 */
	opts: function(id,opt) {
		this.id = id;
		this.el = $(id); 
		this.page = 1; 
		this.loading = false; 
		this.next = null; 
		this.prev = null; 
		this.current = null; 
		this.container = null; 
		this.indicator = $('indicator'); 
		this.indicatorFX = new Fx.Style(this.indicator,'opacity',{duration: 300}).set(0); 
		this.pos = 0; 
		this.transitioning = false; 
		this.total = null; 
		this.slider = {
			el: null,
			fx: null,
			prev: null, 
			next: null,
			scroll_to: null
		},
		this.slider_busy = false,
		this.opt = {
			slider: null,
			slider_prev: null,
			slider_next: null,
			tn_width: null,
			tn_height: null,
			tn_number: null,
			uri: null,
			imgs: []
		}; 
		Object.extend(this.opt,opt||{});
	},
	/**
	 * set slider width, events and effects
	 * @see Flickr::sliderBtns()
	 */
	setupSlider: function () {
		this.slider.el = $(this.opt.slider); 
		this.slider.fx = new Fx.Scroll(this.slider.el,{
			onComplete: function() {
				this.slider_busy = false; 
			}.bind(this)
		}); 
		this.slider.el.setStyle('width',Math.round(this.opt.tn_width*this.opt.tn_number)); 
		this.slider.prev = $(this.opt.slider_prev); 
		this.slider.prev.addEvent('click',this.sliderPrev.bind(this)); 
		this.slider.next = $(this.opt.slider_next); 
		this.slider.next.addEvent('click',this.sliderNext.bind(this)); 
		this.total = this.getTotal(); 
		this.sliderBtns(); 
	},
	/**
	 * set slider prev/next inactive className
	 */
	sliderBtns: function() {
		this.slider.prev.className = this.pos==0 ? 'off' : ''; 
		this.slider.next.className = this.pos>=(this.total.toInt()-this.opt.tn_number.toInt()) ? 'off' : '';  
	},
	/**
	 * slider's prev button event handler
	 * @param object e
	 * @see Flickr::sliderBtns()
	 */
	sliderPrev: function(e) {
		e = new Event(e).stop();
		if(this.pos<this.opt.tn_number) {
			this.slider.fx.scrollTo(0,0);
			this.pos=0;  
		} else {
			this.pos = this.pos.toInt()-this.opt.tn_number.toInt(); 
			var set = this.whichSet(this.pos);
			var width = this.pos*this.opt.tn_width; 
			var scroll_to = width+(set*3)+set; 	
			this.slider.fx.scrollTo(scroll_to,0); 
		}
		this.sliderBtns(); 
	},
	/**
	 * slider's next button event handler
	 * @param object e
	 * @see Flickr::sliderBtns()
	 */
	sliderNext: function(e) {
		e = new Event(e).stop();
		if(this.pos>=(this.total.toInt()-this.opt.tn_number.toInt())) {
			return false; 
		}
		this.pos = this.pos.toInt()+this.opt.tn_number.toInt(); 
		var set = this.whichSet(this.pos);
		var width = this.pos*this.opt.tn_width; 
		var scroll_to = width+(set*3)+set; 	
		this.slider.fx.scrollTo(scroll_to,0); 
		this.sliderBtns(); 
	},
	/**
	 * scroll slider instance to specific page number
	 * @param integer page
	 * @see Flickr::sliderBtns()
	 */
	sliderPage: function(page) {
		this.slider.scroll_to = this.opt.tn_width*this.opt.tn_number*(page-1); 
		this.slider.fx.scrollTo(this.slider.scroll_to,0); 
		this.sliderBtns(); 
	},
	/**
	 * scroll slider to first image in set
	 */
	sliderSet: function(set) {
		this.slider_busy = true; 
		var position = this.opt.imgs[set].photos[0].pos; 
		var width = this.opt.tn_width; 
		var scrollTo = Math.round(width*position); 
		this.sliderScrollTo(scrollTo); 
	},
	/**
	 * scroll slider instance to specific value
	 * @param integer value
	 * @see Flickr::sliderBtns()
	 */
	sliderScrollTo: function(value) {
		this.slider.fx.scrollTo(value,0); 
		this.sliderBtns(); 		
	},
	/**
	 * returns total number of images contained in slider
	 * @return integer
	 */
	getTotal: function() {
		var total = 0; 
		for(var i=0; i<this.opt.imgs.length; i++) {
			total += Number(this.opt.imgs[i].total); 
		}
		return total; 
	},
	/**
	 * returns set number for image position
	 * @param integer pos
	 * @return integer|boolean[false]
	 */
	whichSet: function(pos) {
		var total = 0; 
		for(var i=0; i<this.opt.imgs.length; i++) {
			if(pos>=total && pos<total+Number(this.opt.imgs[i].total)) {
				return i; 
			}
			total += Number(this.opt.imgs[i].total); 
		}
		return false; 
	},
	/**
	 * returns image's position within it's set
	 * @param integer pos
	 */
	whichSetPos: function(pos) {
		for(var j=0; j<this.opt.imgs.length; j++) {
			for(var i=0; i<this.opt.imgs[j].photos.length; i++) {
				if(this.opt.imgs[j].photos[i].pos==pos) {
					return i;  
				}
			}
		} 
	},
	/**
	 * returns the slider instance's page number for image position
	 * @param integer pos
	 */
	whichPage: function(pos) {
		var pages = Math.round(this.total/this.opt.tn_number)+1; 
		var low = 0; 
		var high = this.opt.tn_number; 
		for(var i=1; i<pages; i++) {
			/*alert(i+"\n"+pos+"\n"+low+"\n"+high);*/
			if(pos>=low && pos<high) {
				return i; 
			}
			low += this.opt.tn_number; 
			high = (i+1)*this.opt.tn_number; 
		}
	},
	/**
	 * load specified set
	 * @param integer set
	 */
	loadSet: function(set) {
		if(set==0) {
			this.loadImg(this.opt.imgs[0].photos[0].md,0); 
			this.pos = 0; 
		} else {
			this.loadImg(this.opt.imgs[set].photos[0].md,this.opt.imgs[set].photos[0].pos); 
			this.pos = this.opt.imgs[set].photos[0].pos; 
		}
		this.updateSlider(); 
	},
	/**
	 * load specific image
	 * @param string src
	 * @param integer pos
	 */
	loadImg: function(src,pos) {
		if(src==this.current || this.loading) { return false; }
		this.loading = true; 
		this.current = src; 
		this.pos = pos; 
		window.location = '#'+this.pos; 
		this.updateSlider(); 
		if(!this.container) {
			this.el.empty(); 
			this.container = new Element('div',{id:'img','styles':{'opacity':0}}); 
			this.container.injectInside(this.el);
			this.next = new Element('a',{
					id:'nextBtn',
					href:'#' 
				}); 
			this.next.addEvent('click',this.nextImage.bind(this)); 
			this.prev = new Element('a',{
					id:'prevBtn',
					href:'#'
				}); 
			this.prev.addEvent('click',this.prevImage.bind(this)); 
			this.prev.injectTop(this.el);
			this.next.injectTop(this.el);
		} else {
			this.container.empty(); 
		}
		this.container.setStyle('opacity',0);
		this.indicatorFX.start(0,1); 
		this.img = new Asset.image(src,{
				id: 'flickrImg',
				onload: this.loadComplete.bind(this)
			});
	}, 
	/**
	 * Flickr::loadImg() onComplete event handler
	 */
	loadComplete: function() {
		if(this.transitioning) { return false; } 
		this.transitioning = true; 
		this.container.setStyle('width',this.img.width+20);
		new Fx.Style(this.container,'height',{
				duration: 750,
				transition: Fx.Transitions.Quad.easeInOut, 
				onComplete: function() {
					this.indicatorFX.start(1,0); 
					var set = this.whichSet(this.pos)
					var set_pos = this.whichSetPos(this.pos); 
					var a = new Element('a',{'rel':'lightbox','href':this.opt.imgs[set].photos[set_pos].lg,'title':this.opt.imgs[set].photos[set_pos].title}); 
					this.img.injectInside(a); 
					a.injectInside(this.container); 
					var spanBG = new Element('span',{'class':'title','styles':{'width':this.img.width-10,'opacity':.6}}); 
					var span = new Element('span',{'class':'title nobg','styles':{'width':this.img.width-10}}).setText(this.opt.imgs[set].photos[set_pos].title);
						spanBG.injectInside(this.container);
						span.injectInside(this.container);

					var enlarge = a.clone().empty(); 
						enlarge.setProperty('alt','Enlarge'); 
						enlarge.setProperty('id','link_enlarge'); 
						enlarge.injectInside(span); 

					var showcase = new Element('a',{'id':'link_showcase','href':'#','alt':'Return to Galleries'}); 
						showcase.addEvent('click',this.loadGallery.bind(this)); 
						showcase.injectInside(span); 

					new Fx.Style(this.container,'opacity').start(0,1);
					this.loading = false; 
					this.transitioning = false; 
					Slimbox.scanPage(); 
				}.bind(this)
			}).start(this.container.getStyle('height').toInt(),this.img.height);
	},
	/**
	 * reloads top level gallery view 
	 */
	loadGallery: function(e) {
		e = new Event(e).stop(); 
		new Fx.Style(this.el,'opacity',{onComplete: function() {
			this.indicatorFX.start(0,1); 
			new Fx.Style(this.el,'height',{onComplete: function(){
					new Ajax(uri+'flickr.out/gallery.html',{method:'get',update:this.el, onComplete: function() {
						this.current = null; 
						this.pos = null; 
						this.indicatorFX.start(1,0); 
						new Fx.Style(this.el,'opacity').start(0,1); 
						this.el.setStyle('height',null); 
					}.bind(this)}).request(); 
				}.bind(this)}).start(this.el.getStyle('height'),250); 
		}.bind(this)}).start(1,0);
		this.container = null;
	},
	/**
	 * load next consective image
	 * @param object e
	 */
	nextImage: function(e) {
		if(this.pos==this.total-1 || this.pos=='undefined') { return false; }
		var pos = ++this.pos; 
		var set = this.whichSet(pos); 
		var set_pos = this.whichSetPos(pos); 
		var src = this.opt.imgs[set].photos[set_pos].md; 
		this.loadImg(src,pos); 
		try {
			e = new Event(e).stop();
		} catch(e) {}
	},
	/**
	 * load previous consecutive image
	 * @param object e
	 */
	prevImage: function(e) {
		if(this.pos<=0 || this.pos=='undefined') { return false; }
		var pos = --this.pos; 
		var set = this.whichSet(pos); 
		var set_pos = this.whichSetPos(pos); 
		var src = this.opt.imgs[set].photos[set_pos].md; 
		this.loadImg(src,pos); 
		try {
			e = new Event(e).stop();
		} catch(e) {}
	},
	/**
	 * listen for left/right keys
	 * @param object e
	 */
	keyListener: function(e){
		var code;
		if (!e) var e = window.event;
		if (e.keyCode) code = e.keyCode;
		else if (e.which) code = e.which;
		switch(code) {
			case 37: 
				this.prevImage(); 
				break; 
			case 39: 
				this.nextImage(); 
				break; 
		}
	},
	/**
	 * prevent right clicking
	 * @param object e
	 */
	preventRightClick: function(e) {
		if (((e.which) && (e.which == 3)) || ((e.button) && (e.button == 2)) || ((e.modifiers) && (e.modifiers == 2)) )
		e = new Event(e).stop();
	}, 
	/**
	 * scroll slider instance to current page
	 */
	updateSlider: function() {
		if(this.slider_busy) {
			return false; 
		}
		var width = this.pos*this.opt.tn_width; 
		var set = this.whichSet(this.pos);
		var value = width+(set*3)+set; 
		this.sliderScrollTo(value); 
		this.sliderBtns(); 
	}
});