var UnicAccordion = Class.create({
	initialize: function(id, options){
		this.id = id;
		this.root = $(id);
		if (!this.root) return false;
		this.options = Object.extend({
			cancelEvent: true,
			classNames: { section: 'section', title: 'title', toggle: 'toggle', expanded: 'expanded' },
			mutuallyExclusive: true,
			effectDuration: .3,
			disabled: false
		}, options || {});
		if (this.options.disabled) this.disable();
		this.accordionEffectOptions = $H({
			duration: this.options.effectDuration,
			queue: { position: 'end', limit: 1, scope: id }
		});
		this.elements = {
			sections: $$('#' + id + ' .' + this.options.classNames.section),
			titles:	 $$('#' + id + ' .' + this.options.classNames.title),
			toggles:	$$('#' + id + ' .' + this.options.classNames.toggle)
		};
		this.activeSection = false;
		this.setupAccordionSections();
		this.fireEvent('initialized');
	},
	
	setupAccordionSections: function(){
		this.sections = [];
		for (var i=0; i < this.elements.sections.length; i++) {
			this.sections.push(new AccordionSection(i, this));
		};
		
		this.root.observe('click', this.rootObserver.bind(this));
	},
	
	rootObserver: function(e){
		var el = e.element();
		if (el.up('.' + this.options.classNames.title)) el = el.up('.' + this.options.classNames.title);
		
		if (el.match('.' + this.options.classNames.title)) {
			
			if (!this.disabled) this.fireEvent('clicked');
			
			if (this.options.cancelEvent) e.stop();
			
			el.blur();
			
			if (this.disabled) return;
			
			var comingSection = this.sections.find(function(section){
			return !section.visible && section.elements.title == el;
			});
			var goingSection = this.sections.find(function(section){
			return section.visible;
			});
			
			if (comingSection && goingSection && this.options.mutuallyExclusive){
			this.showAnotherSection(comingSection, goingSection);
			} else {
			if (comingSection) this.showSection(comingSection);
			else {
				for (var i = this.sections.length - 1; i >= 0; i--){
				if (this.sections[i].elements.title == el) goingSection = this.sections[i];
				};
				this.hideSection(goingSection);
			}
			} 
		}
	},
	
	showAnotherSection: function(comingSection, goingSection){
		if (comingSection.disabled || goingSection.disabled) return;
		new Effect.Parallel([
			new Effect.BlindDown(comingSection.elements.toggle, { sync: true }),
			new Effect.BlindUp(goingSection.elements.toggle, { sync: true })
		],
		this.accordionEffectOptions.merge({
			afterFinish: function(){
			goingSection.setHidden();
			comingSection.setVisible();
			}
		}).toObject());
	},
	
	hideSection: function(goingSection){
		if (goingSection.disabled) return;
		goingSection.elements.toggle.blindUp(
			this.accordionEffectOptions.merge({
			afterFinish: goingSection.setHidden.bind(goingSection)
			}).toObject()
		);
	},
	
	showSection: function(comingSection){
		if (comingSection.disabled) return;
		comingSection.elements.toggle.blindDown(
			this.accordionEffectOptions.merge({
			afterFinish: comingSection.setVisible.bind(comingSection)
			}).toObject()
		);
	},
	
	fireEvent: function(state){
		document.fire(this.id + ':' + state, { accordion: this });
	},
	
	disable: function(){
		this.disabled = true;
		this.root.addClassName('disabled');
		this.fireEvent('disabled');
	},
	
	enable: function(){
		this.disabled = false;
		this.root.removeClassName('disabled');
		this.fireEvent('enabled');
	},
	
	toggleDisabled: function(){
		if (this.disabled) this.enable();
		else this.disable();
	}
});

var AccordionSection = Class.create({
	initialize: function(i, accordion){
		this.index = i;
		this.accordion = accordion;
		this.classNames = accordion.options.classNames;
		this.elements = {
			section: accordion.elements.sections[i],
			title:	 accordion.elements.titles[i],
			toggle:	accordion.elements.toggles[i]
		};
		this.disabled = false;
		this.elements.toggle.setStyle({ height: this.elements.toggle.getHeight() + 'px' }).hide();
		this.visible = false;
	},
	
	setHidden: function(){
		if (this.elements.section.hasClassName(this.classNames.expanded))
			this.elements.section.removeClassName(this.classNames.expanded);
		this.visible = false;
		this.fireEvent('hidden');
	},
	
	setVisible: function(){
		this.elements.section.addClassName(this.classNames.expanded);
		this.visible = true;
		this.accordion.activeSection = this;
		this.fireEvent('shown');
	},
	
	fireEvent: function(state){
		document.fire(this.accordion.id + 'Section:' + state, { accordion: this.accordion, section: this });
	},
	
	disable: function(){
		this.disabled = true;
		this.elements.section.addClassName('disabled');
		this.fireEvent('disabled');
	},
	
	enable: function(){
		this.disabled = false;
		this.elements.section.removeClassName('disabled');
		this.fireEvent('enabled');
	},
	
	toggleDisabled: function(){
		if (this.disabled) this.enable();
		else this.disable();
	}
});
