rio.Application.require("components/box");

rio.components.Accordion = rio.Component.create(rio.components.Box, "Accordion", {
	requireCss: "accordion",
	attrReaders: ["panes", "accordionPanes"],
	attrAccessors: [["selectedPaneIndex", 0]],
	methods: {
		initialize: function() {
			if (!this.getAccordionPanes()) {
				this._accordionPanes = this.getPanes().map(function(pane) {
					var accordionPane = new rio.components.AccordionPane({
						header: pane.header,
						body: pane.body,
						onSelect: pane.onSelect
					});
			
			
					return accordionPane;
				}.bind(this));
			} else if (!Object.isArray(this.getAccordionPanes())) {
				this._accordionPanes = [this.getAccordionPanes()];
			}
			
			this.getAccordionPanes().each(function(accordionPane) {
				accordionPane.bind("selected", function(selected) {
					if (selected) {
						this.setSelectedPaneIndex(this.getAccordionPanes().indexOf(accordionPane));
					}
				}.bind(this));
			}.bind(this));
		
			this.resize.bind(this).defer();
		},

		buildHtml: function() {
			var accordionHtml = this.boxHtml();
			this.getAccordionPanes().each(function(ap) { return accordionHtml.insert(ap.html()); });
			accordionHtml.addClassName("accordion");
		
			this.bind("selectedPaneIndex", function(index) {
				var toShow = this.getAccordionPanes()[index];
				var toHide = this.getAccordionPanes().detect(function(ap) { return ap.getSelected() && ap != toShow; });
			
				if (!toHide) { 
					toShow.bodyHtml().show();
					toShow.setSelected(true);
					return;
				}

				this.getAccordionPanes().each(function(ap) { ap.setSelected(false); });
			
				toShow.setSelected(true);
				toShow.bodyHtml().show();
				toHide.bodyHtml().hide();
			
				// (function() {
				// 	var effects = [new Effect.BlindDown(toShow.bodyHtml(), {
				// 		duration: 0.5,
				// 		sync: true,
				// 		// transition: Effect.Transitions.sinoidal
				// 	})];
				// 	if (toHide) {
				// 		effects.push(new Effect.BlindUp(toHide.bodyHtml(), {
				// 			duration: 0.5,
				// 			sync: true,
				// 			// transition: Effect.Transitions.sinoidal
				// 		}));
				// 	}
				// 	new Effect.Parallel(effects, {
				// 		duration: 0.5, 
				// 		queue: {
				// 			position: 'end', 
				// 			scope: 'accordionAnimation'
				// 		},
				// 		afterUpdate: function() {
				// 		}.bind(this),
				// 		afterFinish: function() {
				// 			toShow.setSelected(true);
				// 			toHide.setSelected(false);
				// 			this.resize();
				// 		}.bind(this)
				// 	});
				// 
				// }).bind(this).defer();
			}.bind(this));

			Element.observe(window, "resize", this.resize.bind(this));

			return accordionHtml;
		},
	
		resize: function() {
			this.getAccordionPanes().each(function(pane) {
				pane.setBodyHeight(this.bodyHeight());
			}.bind(this));
		},
	
		bodyHeight: function() {
			var bodyHeight = this.html().getHeight();
			var headersHeight = this.getAccordionPanes().inject(0, function(acc, pane) {
				return acc + pane.getHeaderHeight();
			}.bind(this));
			return bodyHeight - headersHeight;
		}
	}
});

rio.components.AccordionPane = rio.Component.create(rio.components.Base, "AccordionPane", {
	attrReaders: ["header", "body", ["onSelect", Prototype.emptyFunction]],
	attrAccessors: [["selected", false]],
	attrHtmls: ["header", "body"],
	methods: {
		buildHtml: function() {
			return rio.Tag.div([this.headerHtml(), this.bodyHtml()], { className: "pane" });
		},

		buildHeaderHtml: function() {
			var headerHtml = rio.Tag.h1(this.getHeader(), { className: "paneHeader" });
			this.bind("selected", function(selected) {
				headerHtml[(selected ? "addClassName" : "removeClassName")]("selected");
				if (selected) {
					this.getOnSelect()();
				}
			}.bind(this));
			headerHtml.observe("click", function() { this.setSelected(true); }.bind(this));
			return headerHtml;
		},

		buildBodyHtml: function() {
			var bodyHtml = rio.Tag.div(this.getBody(), { className: "paneBody" });
			if (this.getSelected()) { bodyHtml.show(); } else { bodyHtml.hide(); }
			return bodyHtml;
		},

		getHeaderHeight: function() {
			return this.headerHtml().totalHeight();
		},

		setBodyHeight: function(height) {
			this.bodyHtml().style.height = height;
		}
	}
});