
// remove functionality from IE6
if(Browser.Engine.trident && Browser.Engine.trident4) {
    var StationPicker = new Class({});
}
else {

var StationPicker = new Class({

    Implements: Options,
    
    obj_optgroup_offset_cache: {},
    
    str_letters_id: null,
    str_select_id: null,
 
    /**
     * Constructor
     *
     * Sets up the extra navigational features such as the letter linking and tooltips. We cache
     * the offset positions (calculated) of each optgroup so we can quickly scroll the select
     * to the appropriate place. We have to do this (calculate them) due to various browsers
     * having issues with positional offsets and sizes within a select area.
     *
     * @param str str_letters_container_id  ID of the letters select area
     * @param str str_select_id  ID of the select element to apply this to
     * @return void
     */
    initialize: function(str_letters_container_id, str_select_id, str_select_all_id, obj_options) {
    
        this.setOptions(obj_options);
    
        this.str_letters_id = str_letters_container_id;
        this.str_select_id = str_select_id;
        
        // initially scroll the select to the top to prevent calculation bugs (but store so we can
        // move the select back to the correct position)
        var obj_scroll_current = $(str_select_id).getScroll();

        // assign event handler to the letters container
        $(this.str_letters_id).addEvent('click', this._event_letter_click.bindWithEvent(this));
        
        // show the letters selection div
        $(this.str_letters_id).setStyle('visibility', 'visible');
        
        // calculate and cache each option elements position
        var arr_elements = this.arr_options_lookup = $(this.str_select_id).getElements('*');
        var int_element_height = $(this.str_select_id).getScrollSize().y.round() / arr_elements.length;
        
        for(var i = 0, ilen = arr_elements.length; i < ilen; i++) {
        
            var obj_element = arr_elements[i];
            var str_label = obj_element.getProperty('label');
            
            // is this an optgroup (i.e. has a label)?
            if(str_label) {
                this.obj_optgroup_offset_cache[str_label] = i * int_element_height;
            }
        }
        
        // now find the first selected element and ensure we scroll to it
        var int_selected_idx = 0;
        
        for(var i = 0, ilen = arr_elements.length; i < ilen; i++) {
        
            if(arr_elements[i].selected) {
                int_selected_idx = i;
                break;
            }
        }
        
        // ie only
        if(Browser.Engine.trident) {
        
            // delay necessary in order to give the select area chance to initialise
            this._jump.delay(600, this, [int_selected_idx, null]);
        }
        
        // all other browsers
        else {
        
	        // move the select area to the first found item
	        var int_offset = (int_selected_idx - 1) * int_element_height;
	        this._jump(null, int_offset);
	    }
                
        // listen to the "select all" element for click events
        $(str_select_all_id).addEvent('click', this.select_all.bind(this));
    },
    
    
    
    /**
     * Event to handle the clicking of a shortcut letter. Checks to see if it's a valid letter and scrolls
     * the select area to the correct optgroup.
     *
     * @param obj obj_event  Event object to inspect
     * @return void
     */
    _event_letter_click: function(obj_event) {
    
        obj_event = new Event(obj_event);
        
        // retrieve the clicked target element
        var elm_target = $(obj_event.target);
        
        // is this an active span (e.g. clickable element)?
        if(elm_target.match('span.active')) {
        
            var elm_select = $(this.str_select_id);
            
            // get the letter from the span
            var str_letter = elm_target.get('html');
            
            var int_idx = null;
            var int_offset_px = null;
           
            // IE: mini-hack. We can't nicely scroll the select area like we do with every other
            // browser since IE doesn't realise it's been scrolled... so when the user clicks the
            // up and down arrows, it jumps to their last selection. Thus, for IE, we turn off
            // auto scrolling and use a select/deselect item trick (at the correct place) to cause
            // the select area to jump to the desired area.
            if(Browser.Engine.trident) {
            
	            var arr_options = this.arr_options_lookup;
	            
	            // find the optgroup index for the clicked letter
	            for(var i = 0, ilen = arr_options.length; i < ilen; i++) {
	            
	                if(arr_options[i].get('tag') == 'optgroup' && arr_options[i].get('label') == str_letter) {
	                    break;
	                }
	            }
	            
	            int_idx = i + 7;

	            // need to trigger the scroll to the item 7th below this optgroup (in order for the optgroup
	            // to be at the top of the select area
	            var elm_closest_option = arr_options[int_idx];
	            
	            // if the item we've chosen is an optgroup, we need to select the previous option element
	            if(elm_closest_option && elm_closest_option.get('tag') == 'optgroup') {
	               int_idx--;
                   elm_closest_option = arr_options[int_idx];
                }
                
                // if the item we've selected is null, we've gone over the number of elements in the select, 
                // so just choose the last one
	            if(!elm_closest_option) {
	               int_idx = arr_options.length - 1;
	            }
	        }
	        
	        this._jump(int_idx, this.obj_optgroup_offset_cache[str_letter]);     
        }
    },
    
    
    
    /**
     * Utility method to jump the select area to the desired offset.
     * Accepts both a pixel offset (used for browsers that support scrolling) as well as an option
     * index (for IE)
     */
     _jump: function(int_idx, int_offset_px) {
     
         if(Browser.Engine.trident) {
         
             var arr_options = this.arr_options_lookup;
             
	         // in order for the select jumping to work, we need to jump to the first element first (select
	         // and deselect it) before proceeded to the index calculated above.
	         // Note: index[0] will be an optgroup
	         var elm_first = arr_options[1];
	         
	         var boo_selected = elm_first.selected;
	         
	         elm_first.selected = true;
	         elm_first.selected = false;
	         elm_first.selected = boo_selected;
	         
	         // and now finally we can jump to the correct option
	         var elm_option = arr_options[int_idx];
	         
	         var boo_selected = elm_option.selected;
	         
	         elm_option.selected = true;
	         elm_option.selected = false;
	         elm_option.selected = boo_selected;
	     }
	     
	     // non-ie browsers
	     else {
	     
	         // scroll to the requested optgroup (note: hack for Safari which focuses the control to activate the scroll)
	         new Fx.Scroll($(this.str_select_id), { onComplete: this._focus_select.bind(this) }).start(0, int_offset_px);   
	     }
     },
    
    
    /**
     * Primarily a hack for Safari. This browser (plus others possibly) implement the scroll of the select area correctly
     * but fail to actually update the contents. So the scrollbar moves, but not the select's content. By focusing the
     * control we ensure these browsers re-render the content post effect completion.
     *
     * @return void
     */
    _focus_select: function() {
    
       $(this.str_select_id).focus(); 
    },
    
    
    
    /**
     * Sets all stations in the select options list to be selected.
     *
     * @return false
     */
    select_all: function() {
        
        $(this.str_select_id).getElements('option').setProperty('selected', true);

        return false;
    }

});

}