var Accordion = Class.create({
	initialize: function(element, options) {
		var DefaultOptions = {
			type: "vertical",
			event: "click",
			toggle_class: "accordion-toggle",
			active_class: "accordion-active",
			content_class: "accordion-content",
			toggle_location: "before"
		};

		if (!options) { 
			options = {};
		}
		
		this.options = Object.extend(Object.extend({ }, DefaultOptions), options);

		this.accordion = $(element);

		if (!this.accordion) {
			throw ("Attempted to initalize accordion with undefined element: " + element);
		}

		this.toggleClass = this.options.toggle_class;
		this.activeClass = this.options.active_class;
		this.contentClass = this.options.content_class;
		this.type = this.options.type;
		this.toggleLocation = this.options.toggle_location;

		this.contents = this.accordion.select('.' + this.contentClass);
		this.togglers = this.accordion.select('.' + this.toggleClass);
		this.current = (this.toggleLocation == "before") ? this.accordion.select('.' + this.activeClass)[1] : this.accordion.select('.' + this.activeClass)[0];
		this.isAnimating = false;
		this.toExpand = null;

		if(this.type == 'vertical') {
			this.maxHeight = this.contents.max(function(e) {
				return e.getHeight();
			});
		}

		this.initialHide();
		this.adjust_zindex();
		
		if(this.current) {
			(this.toggleLocation == "before") ? this.current.previous('.' + this.toggleClass).addClassName(this.activeClass) : this.current.next('.' + this.toggleClass).addClassName(this.activeClass);
			
			if (this.type == 'vertical' && this.current.getHeight() != this.maxHeight) { 
				this.current.setStyle({height: this.maxHeight + "px"});
			}
		}

		//this.accordion.select("." + this.toggleClass).invoke("observe", this.options.event, this.toggle.bindAsEventListener(this));
		this.accordion.on(this.options.event, "." + this.toggleClass, function(event, element) {
			event.stop();
			this.toggle(element);
		}.bind(this));
	},

	toggle: function(el) {
		//var el = e.findElement("." + this.toggleClass);

		if (!this.isAnimating) {
			this.toExpand = (this.toggleLocation == "before") ? el.next('.' + this.contentClass) : el.previous('.' + this.contentClass);
			this.animate();
			//e.stop();
			return false;
		}
	},

	initialHide: function() {
		this.contents.each(function(e) {
			e.setStyle({'display': 'block'});

			if (e == this.current) {
				return;
			}

			if(this.type == 'horizontal') {
				e.setStyle({width: 0});
			}
			else {
				e.setStyle({height: 0});
			}
		}.bind(this));
	},

	animate: function() {
		var effects = [];
		var on_options = {
			sync: true,
			scaleFrom: 0,
			scaleContent: false,
			scaleMode: 'contents',
			scaleX: false,
			scaleY: true
		};
		var off_options = {
			sync: true,
			scaleContent: false,
			scaleX: false,
			scaleY: true
		};

		if(this.type == 'vertical-multiple') {
			if (this.toggleLocation == "before") {
				if (this.toExpand.previous('.' + this.toggleClass).hasClassName(this.activeClass)) {
					effects.push(new Effect.Scale(this.toExpand, 0, off_options));
					this.toExpand.previous('.' + this.toggleClass).removeClassName(this.activeClass);
					this.toExpand.removeClassName(this.activeClass);
	
				} else {
					effects.push(new Effect.Scale(this.toExpand, 100, on_options));
					this.toExpand.previous('.' + this.toggleClass).addClassName(this.activeClass);
					this.toExpand.addClassName(this.activeClass);
				}
			
			} else {
				if (this.toExpand.next('.' + this.toggleClass).hasClassName(this.activeClass)) {
					effects.push(new Effect.Scale(this.toExpand, 0, off_options));
					this.toExpand.next('.' + this.toggleClass).removeClassName(this.activeClass);
					this.toExpand.removeClassName(this.activeClass);
	
				} else {
					effects.push(new Effect.Scale(this.toExpand, 100, on_options));
					this.toExpand.next('.' + this.toggleClass).addClassName(this.activeClass);
					this.toExpand.addClassName(this.activeClass);
				}
			}

		} else {
			if (this.toExpand == this.current) {
				return;
			}

			if(this.type == 'horizontal') {
				on_options.scaleX = off_options.scaleX = true;
				on_options.scaleY = off_options.scaleY = false;
			}
			else {
				on_options.scaleMode = {originalHeight: this.maxHeight, originalWidth: this.accordion.getWidth()};
			}
			
			effects.push(new Effect.Scale(this.toExpand, 100, on_options));
			effects.push(new Effect.Scale(this.current, 0, off_options));
			
			this.adjust_zindex();


			// remove the active state from the current toggler
			(this.toggleLocation == "before") ? this.current.previous('.' + this.toggleClass).removeClassName(this.activeClass) : this.current.next('.' + this.toggleClass).removeClassName(this.activeClass);

			// remove the active state from the current content
			this.current.removeClassName(this.activeClass);

			// add the active state from the new toggler
			(this.toggleLocation == "before") ? this.toExpand.previous('.' + this.toggleClass).addClassName(this.activeClass) : this.toExpand.next('.' + this.toggleClass).addClassName(this.activeClass);

			// add the active state from the new content
			this.toExpand.addClassName(this.activeClass);
		}

		new Effect.Parallel(effects, {
			duration: .5,
			fps: 25,
			queue: {position: 'end', scope: this.accordion.id + "Animation"},
			beforeStart: function() {
				this.isAnimating = true;
			}.bind(this),
			afterFinish: function() {
				this.current = this.toExpand;
				this.isAnimating = false;
			}.bind(this)
		});
	},
	
	adjust_zindex: function() {
		var base_zindex = this.contents.size();
		var active_content_index = this.toExpand ? this.contents.indexOf(this.toExpand) : this.contents.indexOf(this.current);
		var new_zindex = 0;
		var class_name = "";
		
		this.togglers.invoke("removeClassName", "accordion-toggle-before").invoke("removeClassName", "accordion-toggle-after");

		this.contents.each(function(c, index) {
			if (index != active_content_index) {
				new_zindex = (index < active_content_index) ? new_zindex + 1 : new_zindex - 1;
				class_name = (index < active_content_index) ? "accordion-toggle-before" : "accordion-toggle-after";
				c.setStyle({
					zIndex: new_zindex
				});
				
				(this.toggleLocation == "before") ? c.previous('.' + this.toggleClass).addClassName(class_name).setStyle({zIndex: new_zindex}) : c.next('.' + this.toggleClass).addClassName(class_name).setStyle({zIndex: new_zindex});
			} else {
				c.setStyle({
					zIndex: base_zindex
				});
				(this.toggleLocation == "before") ? c.previous('.' + this.toggleClass).setStyle({zIndex: base_zindex}) : c.next('.' + this.toggleClass).setStyle({zIndex: base_zindex});
				new_zindex = base_zindex;
			}
		}.bind(this));
	}
});
