var Accordion = 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;
				goingSection.setHidden();
				comingSection.setVisible();
				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;
		if (!this.elements.section.hasClassName(this.classNames.expanded)){
			this.elements.toggle.setStyle( {
				height :this.elements.toggle.getHeight() + 'px'
			}).hide();
			this.visible = false;
		}
		else{
			this.setVisible();
		}
	},

	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();
	}

});
