/*
 * Copyright 2006, John Drinkwater <john@nextraweb.com>
 * Distributed under the terms of the MIT License.
 * Please note, this script isn't as DOM friendly as I would like, 
 * but IE, as always, has problems with <select> and <option>s
 * Version 1e, from http://ezri.nextraweb.com/examples/js/haiku/rev1e/componentselect.js
 */

function addEvent( object, type, handler ) {
	if ( object.addEventListener ) {
		object.addEventListener( type, handler, false );
	} else if ( object.attachEvent ) {
		object.attachEvent( [ 'on', type ].join( '' ),handler );
	} else {
		object[ [ 'on', type ].join( '' ) ] = handler;
	}
}
// From Prototype
function $( ) {
    var elements = new Array( );
    for ( var i = 0; i < arguments.length; i++ ) {
        var element = arguments[ i ];
        if ( typeof element == 'string' )
            element = document.getElementById( element );
        if ( arguments.length == 1 )
            return element;
        elements.push( element );
    }
    return elements;
}

// take the current selection, and make a haiku/component
function updateSelection( set, level ) {

	var text, i, component = '';
	for ( i = 1; i <= level + 1 ; i++ ) { 
		if ( componentSelector[ set ][ i ].selectedIndex != -1 ) {
			text = componentSelector[ set ][ i ].options[ componentSelector[ set ][ i ].selectedIndex ].text;
			if ( text != '' )
				component += text + '/';
		}
	}
	hiddenComponent[ set ].value = component.substring( 0, component.length - 1 );
}

/*
	The user has changed the selected component
 */
function selectComponent( e ) {

	// because IE has never made it easy..
	var caller;
	if ( !e ) var e = window.event;
	if ( e.target ) caller = e.target; else if ( e.srcElement ) caller = e.srcElement;
	if ( caller.nodeType == 3 ) // defeat Safari bug
		caller = caller.parentNode;
	var level = caller.stage; 
	var set = caller.set;
	
	updateSelection( set, level ); 

	// bomb out if this is a last choice
	if ( level >= maxBranches )
		return;
	
	// remove any <select>s to the right of us
	var remover;
	for ( i = maxBranches; i > level; i-- ) {
		if ( null != ( remover = componentSelector[ set ][ i ] ) ) {
			if ( remover.parentNode )
				 remover.parentNode.removeChild( remover );
		}
	}


	
	// check if the user back–pedalled to a non option
	// we no longer have '' choices
	var parentChoice = componentSelector[ set ][ level ].options[ componentSelector[ set ][ level ].selectedIndex ].text;
	//if ( parentChoice == '' )
	//	return;


	var choice, superChoice, previous = '', p, recursive = false, currentSelector = componentSelector[ set ][ level + 1 ];
	currentSelector.options.length = 0; 
	//currentSelector.options[ 0 ] = new Option( '', '' );
	
	for ( i = 0, p = 0; i < componentList.length ; i++ ) {
		choice = componentList[ i ][ level ]; 
		superChoice = componentList[ i ][ level - 1 ]; 
		if ( previous != choice && choice != null && superChoice == parentChoice ) {
			previous = choice;
			currentSelector.options[ p++ ] = new Option( choice, choice );
				
			if ( p == 1 && componentList[ i ][ level + 1 ] != null ) {
				recursive = true;
			}
		}
	}
	// Konq, hello!
	currentSelector.selectedIndex = 0;
	
	// avoid cases where there are no options, ie, we have selected a leaf
	if ( currentSelector.options.length < 1 )
		return;

	updateSelection( set, level ); 

	// We're done, add it back to the page
	var parent = caller.parentNode;
	var sibling = caller.nextSibling;
	if ( sibling != null )
		parent.insertBefore( currentSelector, sibling );
	else
		parent.appendChild( currentSelector );

	// does this branch continue?
	if ( recursive ) {
		var event = { target : currentSelector };
		selectComponent( event );
	}
}

/*
	This function deletes the <select> box, replaces it with a hidden input box, 
	and as many <select>s as the first/selected component had parts: this new element has an 
	event that triggers on change, to add or remove <select> boxes
 */
function reduceComponents( original, set ) {

	// check support, else use non-js method
	if ( !document.createElement || !original )
		return; 
	if ( !set ) set = window.components++;

	var i, sibling, parent = original.parentNode;
	// we assume the options never change between reduceComponents calls
	if ( componentList.length == 0 ) {
		for ( i = 0; i < original.options.length; i++ ) {
			componentList[ i ] = original.options[ i ].text.split( '/' );
			maxBranches = ( maxBranches < componentList[ i ].length ? componentList[ i ].length : maxBranches );
		}
		componentList.sort(); // so Trac can be lazy
	}

	componentSelector[ set ] = new Array();
	// create some replacement dropdowns
	for ( i = 1; i <= maxBranches; i++ ) {
		componentSelector[ set ][ i ] = document.createElement( 'SELECT' );
		componentSelector[ set ][ i ].id = 'component-componentSelector-' + set + '-' + i;
		componentSelector[ set ][ i ].className = 'haikucomponent';
		componentSelector[ set ][ i ].stage = i;
		componentSelector[ set ][ i ].set = set;
		addEvent( componentSelector[ set ][ i ], 'change', selectComponent );
		//addEvent( componentSelector[ set ][ i ], 'keyup', selectComponent );
	}

	// Setup the field to submit
	var currentSelector = componentSelector[ set ][ 1 ];
			hiddenComponent[ set ] = document.createElement( 'INPUT' );
			hiddenComponent[ set ].id = original.id;
			hiddenComponent[ set ].name = original.name;
			hiddenComponent[ set ].type = 'hidden';	

	// Take currently selected option, or the first
	if ( original.selectedIndex == -1 ) original.selectedIndex = 0;
	hiddenComponent[ set ].value = original.options[ original.selectedIndex ].text;
	subItems		  = hiddenComponent[ set ].value.split( '/' );

	// Populate choice(s)	
	var p, j, previous, parent = original.parentNode;
	for ( i = 0; i < subItems.length; i++ ) {
		
		currentSelector = componentSelector[ set ][ i + 1 ];
		//currentSelector.options[ 0 ] = new Option( '', '' );
		previous = null;
		for( j = 0, p = 0; j < componentList.length ; j++ ) {

			choice = componentList[ j ][ i ];
			if ( previous != choice && choice != null && componentList[ j ][ i - 1 ] == subItems[ i - 1 ] ) {
				previous = choice;					
				currentSelector.options[ p++ ] = new Option( choice, choice );
				if ( choice == subItems[ i ] ) {
					currentSelector.selectedIndex = p - 1;
				}
			}
		}	
		sibling = original;
		if ( sibling != null )
			parent.insertBefore( currentSelector, sibling );
		else
			parent.appendChild( currentSelector );
	}
	parent.replaceChild( hiddenComponent[ set ], original );
}

window.componentList = new Array( );
window.components = 0;
window.componentSelector = new Array( );
window.hiddenComponent = new Array( );
window.maxBranches = 0;

// For the ticket page
function connect() { reduceComponents( $( 'component' ) ); }

// For the query page, function coming !

addEvent( window, 'load', connect );

