(function() {

    /**
     * The accordionview module provides a widget for managing content in an accordion.
     * @module accordionview
     * @requires yahoo, dom, event, element, animation
     *
     * By Marco van Hylckama Vlieg (marco@i-marco.nl)
     * Some inspiration taken from the YUI TabView widget
     *
     * THIS IS A WORK IN PROGRESS
     *
     */
    /**
     * A widget to control accordion views.
     * @namespace YAHOO.widget
     * @class AccordionView
     * @extends YAHOO.util.Element
     * @constructor
     * @param {HTMLElement | String | Object} el(optional) The html 
     * element that represents the AccordionView, or the attribute object to use. 
     * An element will be created if none provided.
     * @param {Object} attr (optional) A key map of the AccordionView's 
     * initial attributes.  Ignored if first arg is attributes object.
     */

	YAHOO.widget.AccordionView = function(el, attr) {
	
		if(attr.collapsible !== false) {
			attr.collapsible = true;
		}
		
		if(!YUD.get(el)) {
			alert('creating accordions on the fly is not implemented yet.\nThere is no list in your markup with id \'' + el + '\'');
			return false;
        	el = _createAccordionViewElement.call(this, el, attr);
		}

		this._initList(el, attr);
		
		YAHOO.widget.AccordionView.superclass.constructor.call(this, el, attr); 
	};

	YAHOO.extend(YAHOO.widget.AccordionView, YAHOO.util.Element);

	var proto = YAHOO.widget.AccordionView.prototype, YUD = YAHOO.util.Dom, YUE = YAHOO.util.Event, YUA = YAHOO.util.Anim, YUS = YAHOO.util.Selector;

	proto.dataConnections = {};
	
	proto.cachedData = {};
	
	proto.root = null;

    /**
     * The className to add when building from scratch. 
     * @property CLASSNAME
     * @default "yui-accordionview"
     */
    proto.CLASSNAME = 'yui-accordionview';
	
	proto._initList = function(el, attr) {
		
		console.log('initlist ');
		console.log(attr);
		
		this.id = el;
		this.root = document.getElementById(el);
		
		if(attr.width) {
			YUD.setStyle(this.root, 'width', attr.width);
		}
		aItems = this.collapseAccordion();
		if(attr.expandItem) {			
			YUD.removeClass(aItems[attr.expandItem], 'hidden');			
			YUD.addClass(YUD.getElementsByClassName('yui-accordion-toggle', 'a', this.root)[attr.expandItem], 'active');
			YUD.addClass(el.previousSibling, 'active');
		}
		
		YUE.on(el, 'click', this.handleClicks, attr, this);
	}

	proto.collapseAccordion = function() {
		
		if(this.root == null) {return;}
		
		var that = this;
		var aItems = YUD.getElementsByClassName('yui-accordion-content' ,'div', this.root);
		YUD.batch(aItems, function(e) {
			if(YUD.getElementsByClassName('indicator', 'span', e.parentNode).length == 0) {
				el = document.createElement('span');
				YUD.addClass(el, 'indicator');
				e.parentNode.firstChild.appendChild(el);
			}
			if(YUD.hasClass(that.root.parentNode, 'yui-accordion-content')) { return; }
			else {
				YUD.removeClass(e.parentNode.firstChild, 'active');
				YUD.addClass(e, 'hidden');
			}
			});
		return aItems;
	}
	
	/**
     * Adds an Accordion panel to the AccordionView instance.  
     * If no index is specified, the panel is added to the end of the tab list.
     * @method addPanel
     * @param {Object} attr A key map of the Panel's properties
     * @param {Integer} index The position to add the tab. 
     * @return void
     */
	
	proto.addPanel = function(attr, index) {
		var panels = YUD.getElementsByClassName('yui-accordion-panel', 'li', this)
		var panelParent = document.createElement('li');
		YUD.addClass(panelParent, 'yui-accordion-panel');
		var panelLink = document.createElement('a');
		var indicator = document.createElement('span');
		YUD.addClass(indicator, 'indicator');
		panelLink.appendChild(indicator);
		YUD.addClass(panelLink, 'yui-accordion-toggle');
		panelLink.appendChild(document.createTextNode(attr.label));
		panelLink.href = attr.href || '#';
		panelParent.appendChild(panelLink);
		panelContent = document.createElement('div');
		panelContent.innerHTML = attr.content;
		YUD.addClass(panelContent, 'yui-accordion-content');
		panelParent.appendChild(panelContent);
		if((index !== null) && (index !== 'undefined')) {
			panelBefore = this.getPanel(index);
			this.insertBefore(panelParent, this.getPanel(index));
		}
		else {
			this.appendChild(panelParent);
		}
		if(attr.expand) {
			this.collapseAccordion();
			YUD.removeClass(panelContent, 'hidden');
			YUD.addClass(panelLink, 'active');
		}
		else {
			YUD.addClass(panelContent, 'hidden');
		}
			
	}
	
	proto.removePanel = function(index) {
		this.removeChild(YUD.getElementsByClassName('yui-accordion-panel', 'li', this)[index]);		
	}
	
	proto.getPanel = function(index) {
		var panels = YUD.getElementsByClassName('yui-accordion-panel', 'li', this);
		return panels[index];
	}

	proto.handleClicks = function(ev, attr) {

		YUE.stopPropagation(ev);			

		function toggleItem(el, elClicked) {
			if(!elClicked) {
				elClicked = el.parentNode.firstChild;
			}
			var oOptions = {};
			var hideAfter = false;
			if(YUD.hasClass(el, 'hidden')) {
				YUD.setStyle(el, 'display', 'block');
				var toHeight = el.offsetHeight;
				YUD.setStyle(el, 'height', 0)
				oOptions = {height: {from: 0, to: toHeight}};
				YUD.removeClass(el, 'hidden');
			}
			else {
				oOptions = {height: {from: el.offsetHeight, to: 0}};
				hideAfter = true;
			}
			if(attr.animate) {
				var speed = (attr.animationSpeed) ? attr.animationSpeed : 1;
				var effect = (attr.effect) ? attr.effect : YAHOO.util.Easing.easeBoth;
				var oAnimator = new YUA(el, oOptions, speed, effect);
				if(hideAfter) {
					YUD.removeClass(elClicked, 'active');
					oAnimator.onComplete.subscribe(function(){
						YUD.addClass(el, 'hidden');
						YUD.setStyle(el, 'height', 'auto');
						YUD.setStyle(el, 'display', 'none');
					});
				}
				else {
					oAnimator.onComplete.subscribe(function(){
						YUD.setStyle(el, 'height', 'auto');
					});					
					YUD.addClass(elClicked, 'active');
				}
				oAnimator.animate();
			}
			else {
				if(hideAfter) {
					YUD.addClass(el, 'hidden');
					YUD.setStyle(el, 'height', 'auto');
					YUD.setStyle(el, 'display', 'none');
					YUD.removeClass(elClicked, 'active');
				}
				else {
					YUD.removeClass(el, 'hidden');
					YUD.setStyle(el, 'height', 'auto');
					YUD.addClass(elClicked, 'active');
				}
			}
		}
						
		eTargetListNode = YUE.getTarget(ev).parentNode;
		
		
		var containedPanel = YUD.getElementsByClassName('yui-accordion-content', 'div', eTargetListNode)[0]; 
				
		if(attr.collapsible === false) {
			if (!YUD.hasClass(containedPanel, 'hidden')) {
				YUE.preventDefault(ev);
				return false;
			}
		}
		else {
			if(!YUD.hasClass(containedPanel, 'hidden')) {
				toggleItem(containedPanel);
				YUE.preventDefault(ev);
				return false;				
			}
		}

		if(attr.expandable !== true) {
			var allPanels = YUD.getElementsByClassName('yui-accordion-content', 'div', this.root);
		
			// skip panels within a panel
				
			for(element in allPanels) {
				if(this.id == allPanels[element].parentNode.parentNode.id) {
					var mustToggle = YUD.hasClass(allPanels[element], 'hidden');
					if(!mustToggle) {
						toggleItem(allPanels[element]);
					}
				}
			}
		}
		toggleItem(containedPanel, YUE.getTarget(ev));
		YUE.preventDefault(ev);
	}

    var _createAccordionViewElement = function(id, attr) {
        var el = document.createElement('ul');
		el.id = id;
        if ( this.CLASSNAME ) {
            el.className = this.CLASSNAME;
        }       
      return el;
    };

    /**
     * Provides a readable name for the AccordionView instance.
     * @method toString
     * @return String
     */
    proto.toString = function() {
        var name = this.get('id') || this.get('tagName');
        return "AccordionView " + name; 
    };
})();
