var pmtchooser = (function($) {
    // TourChoice houses the currently selected values. When all of the values
    // are in place, the "take me to my tour" link is displayed and is 
    // dispatched to a URL based on the joined values of the various options.
    var TourChoice = function(button_selector) {
        this.button_selector = button_selector;
        this.base = "";
        this.reset();
    };
    jQuery.extend(TourChoice.prototype, {
        set_base: function() {
            base = $('base');
            if(base.length > 0) {
                this.base = base.attr('href');
            }
        },
        
        reset: function(newvalues)  {
            var reset_vals = jQuery.extend({
                ability: '',
                terrain: '',
                terrainpark: '',
                challenge: ''
            }, newvalues || {});
            jQuery.extend(this, reset_vals);

            // Special rule: there's no selection box displayed for 'terrain'
            // when 'historic tour' is chosen as ability. But the destination
            // is 'historic10', so the 'terrain' is explicitly set here if
            // ability is set to 'historic'
            //
            // Selecting the 'ability' marker calls this function, since
            // normally one uses it to start a fresh tour choice. Other 
            // selections set attributes manually.
            if(this.ability == 'historic') { this.terrain = '10'; }
            
            return this;
        },

        is_valid: function() {
            return (
                (this.ability == 'historic')
                || ((this.ability == 'family') && this.terrain)
                || (this.ability && this.terrain && this.challenge)
            );
        },

        as_array: function() {
            return [
                this.ability, this.terrain, this.terrainpark, this.challenge
            ];
        },

        // IE seemed to have issues with 'toString'
        as_string: function() { return this.as_array().join(''); },
        toString: function() { return this.as_string(); },
        
        as_url: function() { return this.base + this.as_string(); },

        // update_button_display() will render the 'take me to my tour'
        // button or hide it, depending on the values of the form elements.
        update_button_display: function() {
            if(this.is_valid()) {
                $(this.button_selector)
                    .attr('href', this.as_url())
                    .fadeIn('fast');
            }
            else {
                $(this.button_selector)
                    .attr('href', '#')
                    .fadeOut('fast');
            }
        },
        
        visit: function() {
            if(this.is_valid())
                window.location = this.as_url();
        }
    });
    
    var tourchoice = new TourChoice('#selectlink');
    
    // Deals with the controls in the "select ability" box
    var Ability = {
        respond_to_click: function(field) {
            if(!field.checked)
                return;
            var field_value = field.value;
            tourchoice.reset({ability: field_value});

            Ability.clear_other_fields(field.form);
            Ability.hide_other_boxes();
            
            tourchoice.update_button_display();
            
            // There are no terrain controls for 'historic' tour choice, so
            // the terrain controls don't need to be displayed/re-displayed.
            if(field_value != 'historic') {
                $('#terraincontrols-'+field.value).show();
                $('#terrainselect').fadeIn('fast');
            }
        },
        
        mark_related: function(label) {
            label = $(label);
            var related_field = $('#'+label.attr('for')).get(0);
            related_field.checked = true;
            Ability.respond_to_click(related_field);
        },
        
        // Clears the next set of fields (radio buttons of name 'terrain'),
        // and then tells the Terrain system to clear the next batch.
        clear_other_fields: function(form) {
            $("input:radio[@name='terrain']", form).attr('checked', false);
            Terrain.clear_other_fields(form);
        },

        // The terrainselect box shows different options depending on the
        // value of 'ability'. Each group of options is in the 'tc-group'
        // class. Even though the 'terrainselect' box itself is being 
        // hidden, the tc-groups are hidden first to prevent any browser
        // anomolies, and so that when ability choices change, there's
        // no flicker of a previously-displayed group.
        hide_other_boxes: function() {
            $('#terrainselect div.tc-group').hide();
            $('#terrainselect').hide();
            Terrain.hide_other_boxes();
        }
    };
    
    // Deals with the controls in the "select terrain" box
    var Terrain = {
        respond_to_click: function(field) {
            if(!field.checked)
                return;
            tourchoice.terrain = field.value;
            tourchoice.update_button_display();
            
            // The 'family' tour has no challenge selection options.
            // The 'black' (black diamond) ability choice adds a terrain
            // park choice to the final selection. 
            if(tourchoice.ability != 'family') {
                if(tourchoice.ability == 'black') {
                    $('#terrainparkcontrols').show();
                }
                $('#challengeselect').fadeIn();
            }
        },
        
        mark_related: function(label) {
            label = $(label);
            var related_field = $('#'+label.attr('for')).get(0);
            related_field.checked = true;
            Terrain.respond_to_click(related_field);
        },
        
        clear_other_fields: function(form) {
            $("input:radio[@name='challenge']", form).attr('checked', false);
            $('#black-terrainpark').attr('checked', false);
            tourchoice.terrainpark = '';
        },
        
        hide_other_boxes: function() {
            $('#terrainparkcontrols,#challengeselect').hide();
        }
    };
    
    // Deals with the controls in the "select challenge" box.
    var Challenge = {
        respond_to_click: function(field) {
            if($(field).is(':checkbox'))
                return Challenge.on_checkbox_click(field);
            
            if(!field.checked)
                return;
            tourchoice.challenge = field.value;
            tourchoice.update_button_display();
        },

        on_checkbox_click: function(field) {
            if(field.checked)
                tourchoice.terrainpark = field.value;
            else
                tourchoice.terrainpark = '';
            tourchoice.update_button_display();
        },
        
        mark_related: function(label) {
            label = $(label);
            var related_field = $('#'+label.attr('for')).get(0);
            if($(related_field).is(':radio'))
                related_field.checked = true;
            else
                related_field.checked = !related_field.checked;
            Challenge.respond_to_click(related_field);
        }
    };
    
    $(document).ready(function() {
        tourchoice.set_base();
        Ability.hide_other_boxes();
        $('#selectlink')
            .hide()
            .click(function() {
                tourchoice.visit();
                return false;
            });
        
        $("input:radio[@name='ability']")
            .click(function() { Ability.respond_to_click(this); });
        $("#abilityselect label")
            .css({'cursor': 'pointer'})
            .click(function() { Ability.mark_related(this); });

        $("input:radio[@name='terrain']")
            .click(function() { Terrain.respond_to_click(this); });
        $("#terrainselect label")
            .css({'cursor': 'pointer'})
            .click(function() { Terrain.mark_related(this); });

        $("input:radio[@name='challenge']")
            .click(function() { Challenge.respond_to_click(this); });
        $("input:checkbox[@name='terrainpark']")
            .click(function() { Challenge.on_checkbox_click(this); });
        $("#challengeselect label")
            .css({'cursor': 'pointer'})
            .click(function() { Challenge.mark_related(this); return false; });
    });
    
    // EXPORT
    return {
        'tourchoice': tourchoice
    };
})(jQuery);
