var Sequence = Class.create();

Sequence.id_hash = {};

Sequence.prototype = {
  initialize: function ( list_el ) {
		this.list_element = $( list_el );
		if ( ! this.list_element ) {
			alert( "Sequence.initialize: Couldn't find parent element '" + list_el + "'");
		}
		Sequence.id_hash[ this.list_element.identify() ] = this;
		this.active_class = 'mvp-active';
		return;
	},

	items_collection: function () {
		return this.list_element.childElements();
	},

	items_count: function () {
		this.items_collection().count()
	},

	active_index: function () {
		// go figure out what the current index is
		var selected_index = -1;
    var found_it = this.items_collection().find( function ( element ) {
			selected_index ++;
			return element.hasClassName( this.active_class );
		} );
		var current_index = found_it ? selected_index : 0;
	},

	selection_function: function ( child_spec ) {
		var spec_value;

		// alert("Building selection_function for '" + child_spec + "'");

		if ( ! child_spec ) {
			alert( 'Sequence.activate: no child_spec!' );
		} 
		else if ( typeof(child_spec) == 'function' ) {
			return child_spec;
		} 
		else if ( typeof(child_spec) == 'object' && (child_spec.nodeType == Node.ELEMENT_NODE) ) {
			spec_value = $(child_spec).identify();
			return function ( el, count ) {
				return ( el.id == spec_value ) ? 1 : 0
			};
		} 
		else if ( typeof(child_spec) != 'string' && typeof(child_spec) != 'number' ) {
			alert( "Unsure how to test " + child_spec + " (" + typeof(child_spec) + ")" );
		}
		
		child_spec = child_spec + "";
		if ( spec_value = child_spec.match( /^[.](\S+)$/ ) ) {
			return function ( el, count ) {
				return el.hasClassName( spec_value[1] ) ? 1 : 0
			};
		} 
		else if ( spec_value = child_spec.match( /^[#][-](\S+)$/ ) ) {
			spec_value += "$";
			return function ( el, count ) {
				return el.id.match( spec_value[1] ) ? 1 : 0
			};
		} 
		else if ( spec_value = child_spec.match( /^[#](\S+)$/ ) ) {
			return function ( el, count ) {
				return ( el.id == spec_value[1] ) ? 1 : 0
			};
		} 
		else if ( child_spec == '0' ) {
			return function ( el, count ) {
				return 0
			};
		} 
		else if ( child_spec == '*' ) {
			return function ( el, count ) {
				return 1
			};
		} 
		else if ( spec_value = ( child_spec.match( /^(\d+)$/ ) )[1] ) {
			return function ( el, count ) {
				return ( count == spec_value ) ? 1 : 0
			};
		}
		else if ( spec_value = ( child_spec.match( /^([+-]\d+)$/ ) )[1] ) {
			var active_index = this.active_index();
			spec_value += active_index;
			spec_value %= this.items_count();
			return function ( el, count ) {
				return ( count == spec_value ) ? 1 : 0
			};
		}
		else {
			alert( "Unsure how to test '" + child_spec + "'" );
		}
	},

	on_children: function ( call_func ) {
		var count = 0;
		this.items_collection().each( function ( child_el ) {
			var trailing = child_el.identify().replace( /.*[-]/, "" );
			call_func( this, child_el, child_spec, count, trailing );
		} )
	},

	on_children_with_class: function ( class_name, active_func, inactive_func ) {
		var count = 0;
		this.items_collection().each( function ( child_el ) {
			var trailing = child_el.identify().replace( /.*[-]/, "" );
			var bool_current = child_el.hasClassName( class_name );
			if ( bool_current ) {
				if ( active_func ) {
					active_func( this, child_el, child_spec, count, trailing );
				}
			} else {
				if ( inactive_func ) {
					inactive_func( this, child_el, child_spec, count, trailing );
				}
			}
		} )
	},

	on_selection: function ( child_spec, active_func, inactive_func ) {
		var spec_function = this.selection_function( child_spec );
		var count = 0;
		this.items_collection().each( function ( child_el ) {
			var trailing = child_el.identify().replace( /.*[-]/, "" );
			var bool_flag = spec_function( child_el, ++ count );
			if ( bool_flag ) {
				if ( active_func ) {
					active_func( this, child_el, child_spec, count, trailing );
				}
			} else {
				if ( inactive_func ) {
					inactive_func( this, child_el, child_spec, count, trailing );
				}
			}
		} )
	},

	toggle_class: function ( child_spec, class_name, add_hook, drop_hook ) {
		var spec_function = this.selection_function( child_spec );
		var count = 0;
		this.items_collection().each( function ( child_el ) {
			var bool_flag = spec_function( child_el, ++ count );
			var bool_current = child_el.hasClassName( class_name );
			// alert( 'Checking: ' + [ spec_function, child_el, child_el.id, bool_flag, bool_current ].join(' / ') );
			if ( bool_flag ) {
				if ( ! bool_current ) {
					child_el.addClassName( class_name );
					if ( add_hook ) {
						var trailing = child_el.identify().replace( /.*[-]/, "" );
						add_hook( this, child_el, child_spec, count, trailing );
					}
				}
			} else {
				if ( bool_current ) {
					child_el.removeClassName( class_name );
					if ( drop_hook ) {
						var trailing = child_el.identify().replace( /.*[-]/, "" );
						drop_hook( this, child_el, child_spec, count, trailing );
					}
				}
			}
		} )
	},

	activate: function ( child_spec ) {
		this.activate_auto_clear();
		this.toggle_class( child_spec, this.active_class, this.onactivate, this.ondeactivate );
	},

	on_active: function ( active_func, inactive_func ) {
		this.on_children_with_class( this.active_class, active_func, inactive_func );
	},


	// Auto Advance behavior
	activate_automatically: function ( seconds_delay, increment ) {
		this.activate_auto_delay = seconds_delay || this.activate_auto_delay || 3;
		this.activate_auto_incr = increment || this.activate_auto_incr || "+1";

		// alert( "activate_auto: " + seconds_delay );
		var this_sequence = this;
		this.timeout_id = setTimeout( 
			function () { 
				this_sequence.activate( this_sequence.activate_auto_incr );
				this_sequence.activate_automatically();
			}, 
			this.activate_auto_delay * 1000 
		);
	},
	activate_auto_clear: function () {
		// alert( "activate_auto_step: " + this.activate_auto_incr );
		if ( this.timeout_id ) {
			clearTimeout( this.timeout_id );
			this.timeout_id = 0
		}
	},

	// Click to activate behavior
	clickable_observe_events: function () {
		var this_sequence = this;
		this.items_collection().each( function ( child_el ) {
			Event.observe( child_el, 'click', function ( event ) {
		  	this_sequence.activate( child_el )
			} )
		} )
	},
	
	// Dynamic child creation with option to clone from a prototype instance.
	create_child_with_id: function ( child_id ) {
		var new_child;
		
		var clone_div = this.list_element.select('div.mvp-seq-cloneme').first();
		if ( clone_div ) {
			// alert ( 'create_child_with_id: cloning from ' + clone_div );
			new_child = clone_div.cloneNode(true);
			new_child.removeClassName('mvp-seq-cloneme');
		} else {
			// alert ( 'create_child_with_id: creating new div' );
			new_child = document.createElement('div'); 
			new_child.addClassName('mvp-seq-item');
			// The tag name and initial class applied to it should be controlled by
			// variables instead of being hard-coded above. 
		}
		new_child.id = child_id;
		//alert("Inserting new child:" + new_child.id + " in " + this.list_element.id);
		this.list_element.insert( new_child );
		return new_child;
	},
	
	// Ajax fetch behavior
	child_by_id_or_ajax: function ( child_id, ajax_url, ajax_params ) {
		var panel_div = $( child_id );
		if ( ! panel_div ) {
			// alert ( 'child_by_id_or_ajax: building for ' + child_id );
			panel_div = this.create_child_with_id( child_id );
			new Ajax.Updater ( 
				panel_div, ajax_url, { method: 'get', parameters: ajax_params, insertion: '', evalScripts: true } 
			);
		}
		return panel_div;
	},
	activate_by_id_or_ajax: function ( child_id, ajax_url, ajax_params ) {
		// alert ( 'activate_by_id_or_ajax: fetching for ' + child_id );
		var child_el = this.child_by_id_or_ajax( child_id, ajax_url, ajax_params );
		// alert ( 'activate_by_id_or_ajax: alerting for ' + child_id );
		this.activate( child_el )
	},

	// Layout behaviors -- incomplete
	layout_adjacent: function () {
	},
	layout_column: function () {
	}
	
};

Sequence.for_element = function ( list_el ) {
	if ( ! list_el ) {
		alert( "Sequence.for_element called without an element" );
	}
	var list_id = $( list_el ).identify();
	// alert ( 'Sequence.for_element: ' + list_id + " / " + Sequence.id_hash + " / " + Sequence.id_hash[ list_id ] + " / " + ( Sequence.id_hash[ list_id ] ? 1 : 0 ) );
	return ( Sequence.id_hash[ list_id ] || new Sequence ( list_el ) );
};

var mvp_seq = function ( element ) {
	var seq = Sequence.for_element( element );
	// alert ( 'mvp_seq: ' + element + " / " + seq );
	return seq;
	return Sequence.for_element( element );
}

