// JavaScript Document
var Tabs = new Class({

  Implements: [Events, Options],
	
	options: {
		tabs: '.tab-anchors li',
		panels: '.tab-panel',
		disableClass: 'disabled',
		start: 0,
		observeDuration: 200,
		forceLinks: false
		//onShow: $empty(tab, panel, anchor),
		//onClose: $empty(tab, panel, anchor),
		//onReady: $empty()
	},
	
	initialize: function(container, options){
		
		this.setOptions(options);
		this.container = document.id(container);
		this.tabs = new Hash(); // contains pairs of tabs and panels with anchor as id
		this.anchors = new Array(); // contains all available tab ids
		this.handlers = this.container.getElements(this.options.tabs);
		
		this.current = null;
		this.defaultTab = null;

        this.handlers.each(function(handler){
		   this.addTab(handler);
			 var link = handler.getElement('a');
			 if (handler.hasClass('disabled') && link){
				 link.addEvent('click', function(event){
				   event.preventDefault()
				 });
			 }
			 if (handler.hasClass('default')){
				 this.defaultTab = link.get('href').replace('#','');
			 }
		}, this);
		
		// init default tab
		if (!this.defaultTab) this.defaultTab = this.anchors[this.options.start];
		var hash = new URI().get('fragment');
		var onLoadScroll = false;
    	if (this.tabs.has(hash)){
			 this.defaultTab = hash;
		} else {
			var targetElement = document.id(hash);
			if (targetElement){
				var panelID = this.getTabFromElement(targetElement);
				if (panelID) this.defaultTab = panelID;
				onLoadScroll = true;
			}
		}
		if (this.defaultTab){
			this.show(this.defaultTab);
			if (onLoadScroll){
				var position = document.id(hash).getPosition(document.body);
				document.id(document.body).scrollTo(0, position.y);
			}
		}
		
		// force links
		if (this.options.forceLinks){
			var links = document.id(document.body).getElements('a[href^=#]');
			links.each(function(link){
				var anchor = link.get('href').replace('#','');
				if (anchor){
					link.addEvent('click', function(event){
					  event.preventDefault();
						this.show(anchor)
					}.bind(this));
				}
			}, this);
		} else {
			// run observer
			this.repeater = this.observe.periodical(this.options.observeDuration, this);
		}
		this.container.addClass('ready');
		this.fireEvent('ready', this);
		
		return this;
		
	},
	
	addTab: function(handler){
		var anchor = handler.getElement('a').get('href');
    if (anchor.test(/^#(.)+$/)){
			var panel =  this.container.getElement(anchor);
			if (panel){
				anchor = anchor.replace('#', '');
				this.tabs.set(anchor, {
				  tab: handler,
					panel: panel.removeProperty('id').hide(),  // remove id to prevent browser from jumping in page
					anchor: anchor
				});
				this.anchors.include(anchor);
			}
		}
	},
	
	getTabFromElement: function(element){
		var tabKey = null;
		if (!element) return tabKey;
		
		var panel = element.getParent('div.tab-panel');
		
		if (!panel) return tabKey;
		
		this.tabs.each(function(tab, key){
			if (tab.panel.uid == panel.uid){
				tabKey = key;
			}
		});
		
		return tabKey;
	},
	
	show: function(id){
		if (id == '') id = this.defaultTab;
		if (this.tabs.has(id)){
			var tabPanel = this.tabs.get(id);
			if (this.current){
				this.current.tab.removeClass('active');
				this.current.panel.hide();
				this.fireEvent('close', [this.current.tab, this.current.panel, this.current.anchor]);
			}
			var tabPanel = this.tabs.get(id);
			tabPanel.tab.addClass('active');
			tabPanel.tab.getElement('a').blur();
			tabPanel.panel.show();
			this.current = tabPanel;
			
			if (this.options.forceLinks) window.location.hash = '#'+id;
            this.fireEvent('show', [tabPanel.tab, tabPanel.panel, id]);
			
			this.fireEvent('change', this.tabs);
		} else {
			// try to look for blocks inside tabs
			this.tabs.each(function(tab, key){
				var block = tab.panel.getElement('#'+id);
				if (block){
					if (this.current && this.current.anchor != key){
						this.current.tab.removeClass('active');
						this.current.panel.hide();
						this.fireEvent('close', [this.current.tab, this.current.panel, this.current.anchor]);
					}
					
					var tabPanel = this.tabs.get(key);
					tabPanel.tab.addClass('active');
					tabPanel.panel.show();
					this.current = tabPanel;
				}
			}, this);
		}
		
		this.current.hash = id;
	},
	
	observe: function(){
		var hash = window.location.hash.replace('#', '').toString();
		var current = this.current.hash;
		if (hash != current && hash != ''){ this.show(hash); }
	},
	
	toElement: function(){
		return this.container;
	}
		
});

var SimpleCarousel = new Class({

  Extends: Fx.Scroll,
	
	options: {
		// Fx.Scroll options
		duration: 500,
		link: 'cancel',
		transition: 'cubic:out',
		mode: 'horizontal',
		wheelStops: false,
		// static carousel options
		loop: true,
		auto: false,
		interval: 0,
		visible: 1,  // number of visible items
		size: false, // overrides item dimensions
		childSelector: ':first-child > div',
		contentSelector: ':first-child'
	},
	
	initialize: function(element, options){
		this.parent(element, options);
		
		this.elements = this.element.getElements(this.options.childSelector);
		this.count = this.elements.length;
		this.content = this.element.getElement(this.options.contentSelector);
		this.current = 0;
		this.index = 0;
		
		// set width
		this.size = this.options.size ? this.options.size : this.elements[0].getSize().x;
		this.content.setStyle('width', this.elements.length*this.size);

		// auto move
		this.scrollTimer = null;
		if (this.options.auto){
			this.autoScroll('start');
		}
		
		// self events
		this.addEvents({
		  'complete': function(){
				this.fireEvent('scrollComplete', this.index);
			}
		});
		this.fireEvent('ready');
		
		return this;
		
	},
	
	getCount: function(){
		return this.elements.length;
	},
	
	getCurrent: function(){
		return this.index;
	},
	
	toNext: function(steps){
		if (steps == undefined) steps = 1;
		for (var i = 0; i<steps; i++){
			if (this.current+this.options.visible == this.count){
				if (this.options.loop){
					var scroll = this.element.getScroll();
					var element = this.content.getFirst();
					element.dispose();
					this.set(scroll.x-this.size, scroll.y)
					element.inject(this.content, 'bottom');
					this.index = ++this.index%this.count;
				} else {
					this.current = 0;
					this.index = 0;
				}
			} else {
				this.current++;
				this.index = ++this.index%this.count;
			}
		}
		this.toElement(this.elements[this.index]);
		
		return this;
	},
	
	toPrevious: function(steps){
		if (steps == undefined) steps = 1;
		for (var i = 0; i<steps; i++){
			if (this.current == 0){
				if (this.options.loop){
					var scroll = this.element.getScroll();
					var element = this.content.getLast();
					element.dispose();
					this.set(scroll.x+this.size, scroll.y)
					element.inject(this.content, 'top');
					this.index--;
					if (this.index < 0) this.index = this.count-1;
				} else {
					this.current = this.count-1;
					this.index = this.count-1;
				}
			} else {
				this.current--;
				this.index--;
				if (this.index < 0) this.index = this.count-1;
			}
		}
		this.toElement(this.elements[this.index]);
		
		return this;
	},
	
	toItem: function(index){
	  if (this.options.auto) this.autoScroll('stop');
		
		if (index == 'next') index = (this.index+1)%this.count;
		if (index == 'prev') index = this.index-1;
		if (index < 0) index = this.count-1;
	

		var stepToPrevious = (index < this.index ? this.index - index : this.index + this.count - index);
		var stepToNext = (index > this.index ? index - this.index : index + this.count - this.index);

    if (stepToPrevious < stepToNext){
			this.toPrevious(stepToPrevious);
		} else {
			this.toNext(stepToNext);
		}
		
		if (this.options.auto) this.autoScroll('start');
		return this;
	},
	
	autoScroll: function(command){
		switch (command){
			case 'start':
			  this.scrollTimer = this.toNext.periodical(this.options.interval, this);
			break;
			case 'stop':
			  $clear(this.scrollTimer);
			break;
		}
		
		return this;
	}


});

var Slideshow = new Class({
	
	Implements: [Events, Options],

  options: {
		// onStart: $emtpy()
		// onReady: $empty()
		path: '/images/page-bg-{i}.jpg', // dynamic loading OR image folder
		images: [], // predefined images
		auto: true,
		duration: 10000,
		fxDuration: 500,
		range: 0
	},
	
  initialize: function(container, options){
		this.container = document.id(container);
		
		this.setOptions(options);
		
		this.paths = [];
		if (this.options.images.length){
			var length = this.options.images.length;
			for (var i = 1; i < length; i++){
				this.paths.push(this.options.path + this.options.images[i]);
			}
		} else {
			for (var i = 1; i < this.options.range; i++){
				this.paths.push(this.options.path.substitute({i: i}));
			}
		}
		
		this.slides = [];
		this.slides.push(this.container.getElement('.image'));
		this.current = 0;
		this.slideFx = [];
		this.slideFx[0] = new Fx.Tween(this.slides[0], { property: 'opacity', duration: this.options.fxDuration, link: 'cancel' }).set(1);
		this.count = 1;
		this.timer = null;
		
		
		this.images = new Asset.images(this.paths, {
		  onComplete: function(){
				this.fireEvent('build');
			}.bind(this)
		});
		
		// class events
		this.addEvents({
		  'build': function(){ this.createSlides(); },
			'start': function(){ this.start(); }
		});
		
	},
	
	createSlides: function(){
		this.images.each(function(image, index){
			this.slides[index+1] = new Element('div', {
			  'class': 'image',
				'styles': {
					'background-image': 'url('+image.src+')'
				}
			});
			this.slideFx.include(new Fx.Tween(this.slides[index+1], { property: 'opacity', duration: this.options.fxDuration, link: 'cancel' }).set(0));
			this.slides[index+1].inject(this.container);
		}, this);
		
		this.count = this.slides.length;
		
		this.fireEvent('ready');
		if (this.options.auto) this.fireEvent('start');
	},
	
	start: function(){
		this.timer = this.move.periodical(this.options.duration, this);
	},
	
	move: function(){
		this.slideFx[this.current].start(0);
		this.current = ++this.current%this.count;
		this.slideFx[this.current].start(1);
	},
	
	show: function(index){
		this.slideFx[this.current].start(0);
		this.current = index;
		this.slideFx[this.current].start(1);
	}
	
});

// observe click events and calls registered methods
var Observer = {
	
	init: function(){
		this.body = document.id(document.body);
		
		this.body.addEvent('click', this.check.bind(this));
		
		this.stack = new Array();
		
	},
	
	register: function(func, bind){
		this.stack.include(func.bind(bind));
		return func;
	},
	
	unregister: function(func){
		this.stack.erase(func);
		return func;
	},
	
	check: function(){
		this.stack.each(function(func){
		  if (func != undefined) func.run();
			this.unregister(func);
		}, this);
	}
 };
