var NXC = NXC || {};
NXC.Tree = new Class( {

	Implements: [Options, Events],

	options: {
		containerCSSClass      : 'nxc-tree',
		nodesSelector          : 'li',
		nodesContainerSelector : 'ul',
		togglerCSSClasses      : {
			open  : 'nxc-tree-expande-open',
			close : 'nxc-tree-expande-close'
		},
		openedNodeID           : false
	},

	container       : false,
	expandeTogglers : [],

	initialize: function( contaner, options ) {
		this.setOptions( options );

		this.container = document.id( contaner );
		this.container.addClass( this.options.containerCSSClass );

		/* Marckup requirment */
		this.insertLastNodes();
		this.insertExpandeTogglers();
		this.installExpandeTogglers();
		this.hideAllNodesContainers();
		this.openDefaultNode();
	},

	insertLastNodes: function() {
		this.container.getElements( this.options.nodesContainerSelector ).each( function( nodesContainer ) {
			new Element( 'li', { 'class': 'nxc-tree-node-last' } ).inject( nodesContainer, 'bottom' );
		}.bind( this ) );
	},

	hideAllNodesContainers: function() {
		this.container.getElements( this.options.nodesContainerSelector ).each( function( nodesContainer ) {
			this.closeNodesContainer( nodesContainer );
		}.bind( this ) );

		this.container.getChildren( this.options.nodesContainerSelector ).each( function( nodesContainer ) {
			this.openNodesContainer( nodesContainer );
		}.bind( this ) );
	},

	closeNodesContainer: function( nodesContainer ) {
		nodesContainer.setStyle( 'display', 'none' );
		this.updateLastNodeHeight( nodesContainer );
		nodesContainer.store( 'opened', false );
	},

	openNodesContainer: function( nodesContainer ) {
		nodesContainer.setStyle( 'display', 'block' );
		this.updateLastNodeHeight( nodesContainer );
		nodesContainer.store( 'opened', true );
	},

	updateLastNodeHeight: function( nodesContainer ) {
		var lastNode = nodesContainer.getParent().getNext();
		if( $type( lastNode ) == 'element' && lastNode.hasClass( 'nxc-tree-node-last' ) ) {
			var height = 8;
			if( nodesContainer.getStyle( 'display' ) == 'block' ) {
				height += nodesContainer.getStyle( 'height' ).toInt();
			}
			lastNode.setStyle( 'height', height + 'px' );
		}
	},

	insertExpandeTogglers: function() {
		this.container.getElements( this.options.nodesSelector ).each( function( node ) {
			if( node.getChildren( this.options.nodesContainerSelector ).length > 0 ) {
				var toggler = new Element( 'a', { 'class' : this.options.togglerCSSClasses.open } ).inject( node, 'top' ).store( 'opened', false );

				this.expandeTogglers.include( toggler );
			}
		}.bind( this ) );
	},

	installExpandeTogglers: function() {
		this.expandeTogglers.each( function( toggler ) {
			toggler.addEvent( 'click', function( event ) {
				event.stop();

				var opened = toggler.retrieve( 'opened' );
				toggler.removeClass( this.options.togglerCSSClasses.open );
				toggler.removeClass( this.options.togglerCSSClasses.close );
				toggler.addClass( opened ? this.options.togglerCSSClasses.open : this.options.togglerCSSClasses.close );
				var nodesContainer = toggler.getParent().getChildren( this.options.nodesContainerSelector )[0];
				if( opened ) {
					this.closeNodesContainer( nodesContainer );
				} else {
					this.openNodesContainer( nodesContainer );
				}
				toggler.store( 'opened', !opened );
			}.bind( this ) );
		}.bind( this ) );
	},

	openDefaultNode: function() {
		var node = document.id( this.options.openedNodeID );
		if( $type( node ) == 'element' ) {
			var childContainer = node.getChildren( this.options.nodesContainerSelector );
			if( childContainer.length > 0 ) {
				this.openNodesContainer( childContainer[0] );
			}
			while( node.getParent().retrieve( 'opened', false ) === false ) {
				this.openNodesContainer( node.getParent() );
				this.hideNodeExpandToggler( node );
				node = node.getParent().getParent();
			}
			this.hideNodeExpandToggler( node );
		}
	},

	hideNodeExpandToggler: function( node ) {
		var toggler = node.getElement( 'a.' + this.options.togglerCSSClasses.open );
		if( $type( toggler ) == 'element' ) {
			toggler.removeClass( this.options.togglerCSSClasses.open );
			toggler.addClass( this.options.togglerCSSClasses.close );
			toggler.store( 'opened', true );
		}		
	}
} );
