var dropdown;

(function() {

var popup_list = new Array();
var current_box = false;
var last_box = false;
var jsoning = new Array();

// setup the change function
dropdown = {
    // ==== init ==================================================================================
    // creates the pretend select divs for those select statements that haven't been done yet
    // ============================================================================================
    init: function()
    {
        // get all selects
        var selects = $$('select');
        var selects_length = selects.length;
        
        // loop through them and retrieve their data
        for (var i = 0; i < selects_length; i ++)
        {
            // init vars
            var data = new Array();
            var select = selects[i];
            var options = select.getElementsByTagName('option');
            var options_length = options.length;
            
            // store the options
            for (var j = 0; j < options_length; j ++)
                data[j] = new Array(options[j].innerHTML, options[j].value, options[j].selected);
            
            // swap the form action
            var parent_form = this.get_form(select);
            if (parent_form.lang != 'no_change')
                parent_form.action = '/' + parent_form.className + '/';
            
            // create the new div
            var new_select = this.create_select(select, data);
            
            // remove the old select
            if (select.nextSibling.nextSibling && select.nextSibling.nextSibling.tagName && select.nextSibling.nextSibling.tagName.toLowerCase() == 'button') select.parentNode.removeChild(select.nextSibling.nextSibling);
            if (select.nextSibling && select.nextSibling.tagName && select.nextSibling.tagName.toLowerCase() == 'button') select.parentNode.removeChild(select.nextSibling);
            select.parentNode.removeChild(select);
        }
    },
    
    // ==== get_form ==============================================================================
    // element - the element to find the form parent of
    // returns the form element that's the parent of the given element to look for
    // ============================================================================================
    get_form: function(element)
    {
        var parent_name = element.parentNode.tagName.toLowerCase();
        if (parent_name != 'form' && parent_name != 'body')
            return this.get_form(element.parentNode);
        else
            return element.parentNode;
    },
    
    // ==== create_select =========================================================================
    // element - the select element to replace
    // data - an array of data to store with element
    // returns the newly created replacement div
    // ============================================================================================
    create_select: function(element, data)
    {
        // init vars
        var random = this.random();
        
        // place the new div in front of the select element
        var select = document.createElement('div');
        select.className = 'select_div';
        select.id = 'marco_' + random;
        select.name = element.name;
        select.random = random;
        select.innerHTML = '<span onselectstart="return false"></span>';
        element.parentNode.insertBefore(select, element);
        
        // add the popup
        var popup = document.createElement('div');
        popup.className = 'popup_div';
        popup.id = 'polo_' + random;
        popup.name = element.name;
        popup.random = random;
        popup.style.display = 'none';
        select.parentNode.insertBefore(popup, select);
        popup_list[popup_list.length] = popup;
        popup.tweener = new Fx.Tween(popup, {duration: 'short', fps: 100, link: 'cancel'});
        
        // add the input box
        var input = document.createElement('input');
        input.type = 'hidden';
        input.name = element.name + '_ajax';
        input.id = 'fish_' + random;
        input.random = random;
        select.parentNode.insertBefore(input, popup);
        
        // add the default text
        var data_length = data.length;
        for (var i = 0; i < data_length; i ++)
            if (data[i][2] == true)
            {
                select.firstChild.innerHTML = data[i][0];
                input.value = data[i][1];
            }
        if (!select.firstChild.innerHTML)
        {
            select.firstChild.innerHTML = data[0][0];
            input.value = data[0][1];
        }
        
        // build the popup data
        this.build_popup(popup, data, element.className == 'repeat_first');
        select.columns = popup.columns;
        
        // add the onclick event to the new select div
        var select = $('marco_' + random);
        select.addEvent('click', dropdown.open_popup);
        setTimeout(function() {select.addEvent('mouseenter', dropdown.in_box); select.addEvent('mouseleave', dropdown.out_box);}, 2);
    },
    
    // ==== random ================================================================================
    // returns a randomly generated id
    // ============================================================================================
    random: function()
    {
        var an_array = 'abcdefghijklmnopqurstuvwxyz1234567890';
        var result = '';
        for (var i = 0; i < 20; i ++)
             result += an_array.substr(Math.round(Math.random() * an_array.length), 1);
        return result;
    },
    
    // ==== built_popup ===========================================================================
    // element - the newly formed popup box
    // data - the array of options to add to our new fake select box
    // ============================================================================================
    build_popup: function(element, data, no_slice_first)
    {
        // remove the default option from the dropdown
        data = !no_slice_first ? data.slice(1, data.length) : data;
        
        // init sizes needed
        var size = data.length;
        var columns = Math.ceil(size / 20);
        var max_size = Math.ceil(size / columns);
        element.columns = columns;
        
        // add the columns to the popup
        for (var i = 0; i < columns; i ++)
        {
            // add the structure
            var struct = '<div class="head_col"></div><div class="main_col">' + this.add_popup_data(data, i, max_size) +  '</div><div class="foot_col"></div>';
            
            // add the columns to the popup
            if (i == 0 && columns == 1)
                element.innerHTML += '<div class="single_col">' + struct + '</div>';
            else if (i == 0)
                element.innerHTML += '<div class="first_col">' + struct + '</div>';
            else if (i != 0 && i + 1 != columns)
                element.innerHTML += '<div class="middle_col">' + struct + '</div>';
            else
                element.innerHTML += '<div class="end_col">' + struct + '</div>';
        }
        
        // get the width of the popup
        element.style.width = columns == 1 ? '156px' : ((columns - 1) * 150 + 155) + 'px';
        
        // get the height of the popup
        var max_height = 14 + (max_size * 17);
        element.style.height = '0';
        element.max_height = max_height;
    },
    
    // ==== add_popup_data ========================================================================
    // data - the array of options to add to our new fake select box
    // column - the column we're creating
    // max_size - the maximum size of the column in terms of number of options
    // ============================================================================================
    add_popup_data: function(data, column, max_size)
    {
        // get the data to loop through
        var new_data = data.slice(column * max_size, ((column + 1) * max_size));
        var new_size = new_data.length;
        
        // loop through and create the new a tags
        var result = '';
        for (var i = 0; i < new_size; i ++)
            result += '<span class="' + new_data[i][1] + '" onClick="dropdown.change_page(this)">' + new_data[i][0] + '</span>';
        if (max_size != new_size)
            result += '<em></em>';
        return result;
    },
    
    // ==== change_page ===========================================================================
    // element - the element that's been clicked to trigger a change page
    // ============================================================================================
    change_page: function(element)
    {
        // update the input with new chosen value
        var popup = element.parentNode.parentNode.parentNode;
        $('fish_' + popup.random).value = element.className;
        var span = $('marco_' + popup.random).getElementsByTagName('span')[0];
        span.innerHTML = element.innerHTML;
        
        // submit the form
        var form = this.get_form(element);
        if (this['send_' + form.className])
            this['send_' + form.className](popup);
        else
            form.submit();
    },
    
    // ==== send_resort_search_ajax ===============================================================
    // element - the element that's been clicked
    // ============================================================================================
    send_resort_search_ajax: function(element)
    {
        // stop the popups being clicked
        var get_string = '?';
        var form = this.get_form(element);
        var selects = form.getElementsByTagName('div');
        for (var i = 0; i < selects.length; i ++)
            if (selects[i].className == 'select_div')
            {
                // let the world know we're jsoning
                jsoning[jsoning.length] = selects[i].id;
                
                // remove the clicking option
                selects[i].removeEvent('click', dropdown.open_popup);
                
                // change the popups text to loading
                selects[i].firstChild.innerHTML = 'Loading ...';
                
                // store the get string
                var input = $('fish_' + selects[i].random);
                get_string += input.name + '=' + input.value + '&';
            }
        
        // check for a resort actually being updated
        if (element.name == 'resort')
            window.location = '/resort_search/' + get_string;
        
        // send the request for the new ajax
        var req = new Request.HTML({url: form.action + get_string, onSuccess: dropdown.send_resort_search_ajax_done});
        req.send();
    },
    
    // ==== send_resort_search_ajax_done ==========================================================
    // text - the html passed back from the ajax
    // ============================================================================================
    send_resort_search_ajax_done: function(text)
    {
        $('location').empty();
        $('location').style.display = 'none';
        $('location').adopt(text);
        dropdown.init();
        $('location').style.display = 'block';
    },
    
    // ==== send_deals_form =======================================================================
    // element - the popup that's been chosen
    // ============================================================================================
    send_deals_form: function(element)
    {
        // get the label to find out who's been altered
        var parent = element.parentNode;
        var labels = parent.getElementsByTagName('label');
        var label = labels[0];
        var type = label.htmlFor;
        var input = $('fish_' + element.random);
        
        // show / hide the dates options if needed
        if (type == 'deal_dates')
        {
            $('deal_date_select').className = input.value == 'anytime' ? 'no_bg break' : 'no_bg';
            $('deal_depart').className = input.value == 'anytime' ? 'greyed_out' : 'name_div';
            $('deal_return').className = input.value == 'anytime' ? 'break greyed_out' : 'break';
        }
        
        // get the correct resorts
        if (type == 'deal_country' || type == 'deal_region' || type == 'deal_resort')
            this.send_deals_form_ajax(element);
        
        // hide the prices if needed
        if (type == 'deal_type')
        {
            $('deal_type_select').className = input.value == 'flights' ? 'no_bg break' : 'no_bg';
            $('deal_price_select').style.display = input.value == 'flights' ? 'none' : 'block';
        }
    },
    
    // ==== send_review_form ======================================================================
    // element - the popup that's been chosen
    // ============================================================================================
    send_review_form: function(element)
    {
        // get the label to find out who's been altered
        var parent = element.parentNode;
        var labels = parent.getElementsByTagName('label');
        var label = labels[0];
        var type = label.htmlFor;
        var input = $('fish_' + element.random);
        
        if (type == 'review_a')
            $('stars_box').style.display = input.value == 'product' ? '' : 'none';
    },
    
    // ==== send_deals_form_ajax ==================================================================
    // element - the currently open popup
    // ============================================================================================
    send_deals_form_ajax: function(element)
    {
        // stop the popups being clicked
        var get_string = '?';
        var selects = $('resort_selection').getElementsByTagName('div');
        for (var i = 0; i < selects.length; i ++)
            if (selects[i].className == 'select_div')
            {
                // let the world know we're jsoning
                jsoning[jsoning.length] = selects[i].id;
                
                // remove the clicking option
                selects[i].removeEvent('click', dropdown.open_popup);
                
                // change the popups text to loading
                selects[i].firstChild.innerHTML = 'Loading ...';
                
                // store the get string
                var input = $('fish_' + selects[i].random);
                get_string += input.name + '=' + input.value + '&';
            }
        
        // send the request for the new ajax
        var req = new Request.HTML({url: '/deals_ajax/' + get_string, onSuccess: dropdown.send_deals_form_ajax_done});
        req.send();
    },
    
    // ==== send_deals_form_ajax_done =============================================================
    // text - the html passed back from the ajax
    // ============================================================================================
    send_deals_form_ajax_done: function(text)
    {
        $('resort_selection').empty();
        $('resort_selection').style.display = 'none';
        $('resort_selection').adopt(text);
        dropdown.init();
        $('resort_selection').style.display = 'block';
    },
    
    // ==== open_popup ============================================================================
    // e - the event from opening the popup
    // node - the element to open on override
    // note that here 'this' is the select div, and 'dropdown' is needed instead of 'this'
    // ============================================================================================
    open_popup: function(e, node)
    {
        // make sure we have a popup ready
        var element = e ? this : node;
        var pos = dropdown.get_abs_position(element, 'search_bar');
        var popup = $('polo_' + element.random);
        if (!popup) return;
        
        // check for any open popups first
        if (!node && dropdown.set_num_open() > 0)
        {
            dropdown.close_popup(false, true, element);
            return;
        }
        
        // change the select's image
        element.style.backgroundPosition = '131px -25px';
        
        // style the box with the important elements
        popup.style.top = (pos.y + 25) + 'px';
        popup.style.left = (pos.x + 0) + 'px';
        
        // show the popup
        popup.style.height = '0';
        popup.style.display = 'block';
        popup.tweener.popup_node = popup;
        popup.tweener.start('height', popup.max_height);
        last_box = current_box;
        
        // stop more open clicks from this select
        element.removeEvent('click', dropdown.open_popup);
        
        // hold up clicks to stop the open click interfering
        setTimeout(function() {dropdown.setup_popup_events(popup, true)}, 2);
    },
    
    // ==== setup_popup_events ====================================================================
    // popup - the popup element to attach the events to
    // is_opening - whether or not we are to be opening the popup, thus adding events or removing them
    // note that here 'this' is the select div, and 'dropdown' is needed instead of 'this'
    // ============================================================================================
    setup_popup_events: function(popup, is_opening)
    {
        // set up the func
        var func = is_opening ? 'addEvent' : 'removeEvent';
        
        // add event to document to get it flag up a click anywhere
        document[func]('click', dropdown.check_close_popup);
        
        // add event to close popup on pressing esc
        document[func]('keydown', dropdown.check_key_down);
    },
    
    // ==== check_key_down ========================================================================
    // e - the event from the key press
    // note that here 'this' is the select div, and 'dropdown' is needed instead of 'this'
    // ============================================================================================
    check_key_down: function(e)
    {
        if (e.code == 27)
            dropdown.close_popup();
    },
    
    // ==== close_popup ===========================================================================
    // e - the event from opening the popup
    // override - an override to close the popup even if over another popup
    // element - an element to passed back to open_popup if delayed opening
    // note that here 'this' is the select div, and 'dropdown' is needed instead of 'this'
    // ============================================================================================
    close_popup: function(e, override, element)
    {
        // loop through the popups
        var no_open = true;
        var checked = 0;
        for (var i = 0; i < popup_list.length; i ++)
        {
            // hide the popup
            popup_list[i].tweener.div_node = popup_list[i];
            popup_list[i].tweener.start('height', 0).chain(function()
            {
                // remove the related events
                dropdown.setup_popup_events(this.div_node, false);
                
                // make the select box clickable again
                var select = $('marco_' + this.div_node.random);
                if (select && !dropdown.in_array(jsoning, select.id))
                {
                    select.addEvent('click', dropdown.open_popup);
                    select.style.backgroundPosition = '131px 0';
                }
                
                // set off open_popup if needed
                if (element)
                {
                    no_open = false;
                    dropdown.open_popup(false, element);
                }
            });
        }
    },
    
    // ==== check_close_popup =====================================================================
    // checks to see if we're over a popup, and if so don't do anything
    // ============================================================================================
    check_close_popup: function(e)
    {
        if (current_box == false || last_box == current_box)
            dropdown.close_popup(e);
    },
    
    // ==== in_box ================================================================================
    // stores which box we're currently over
    // ============================================================================================
    in_box: function(e)
    {
        current_box = this;
    },
    
    // ==== out_box ===============================================================================
    // stores which box we're currently over
    // ============================================================================================
    out_box: function(e)
    {
        current_box = false;
    },
    
    // ==== set_num_open ==========================================================================
    // sets the number of popups that are open
    // ============================================================================================
    set_num_open: function()
    {
        temp_num = 0;
        for (var i = 0; i < popup_list.length; i ++)
        {
            if (parseInt(popup_list[i].style.height) > 0)
                temp_num++;
        }
        return temp_num;
    },
    
    // ==== get_abs_position ======================================================================
    // element - the element to get the absolute position of
    // id - if an id is set, that's the element to stop counting in on
    // returns an object with x and y variables that designate the position of the element
    // ============================================================================================
    get_abs_position: function(element, id)
    {
        // init vars
        var coords = {x:0, y:0};
        var id = id ? id : 'No Match';
        
        // get the coords of the node
        while (element && id != element.id)
        {
            // store the coords
            coords.x += element.offsetLeft;
            coords.y += element.offsetTop;
            
            // move to the parent element
            element = element.offsetParent;
        }
        
        // return the coords
        return coords;
    },
    
    // ==== in_array ==============================================================================
    // haystack - the array or object to search through
    // needle - the needle to search for
    // returns either true or false depending on if the needle was found in the haystack or not
    // ============================================================================================
    in_array: function(haystack, needle)
    {
        for (key in haystack)
            if (haystack[key] == needle)
                return true;
        return false;
    }
};

})();