// form.js

// preload the dialog image
var preloaded = new Image(520, 230);
preloaded.src = "../../Content/images/backgrounds/postalCodeDialog.jpg";


var PrePingSellers = [
    '0000-2744'
];


// all methods in DataAccess retrieve data from the server
var DataAccess = {

    apiServerUrl: "http://api.ecardeal.com",

    //apiServerUrl: "http://localhost:59392",

    apiServerQueryStart: "apiId=" + apiId,

    // when sending cars to the api that contain an ampersand, URL encoding is not enough
    // due to a bug in .NET in how it handles paths.
    cleanData: function (data) {
        return data.replace("&", "__and__");
    },

    getDealers: function (Id, year, manufacturer, model, postalCode, callback) {
        $.ajax({
            cache: false,
            url: DataAccess.apiServerUrl + "/lead/current/dealers.jsonp",
            data: DataAccess.apiServerQueryStart + "&SellerDtxId=" + Id + "&Year=" + year + "&Make=" + this.cleanData(manufacturer) + "&Model=" + this.cleanData(model) + "&PostalCode=" + postalCode,
            success: callback,
            dataType: 'jsonp'
        });
    },

    getStyleInfo: function (year, manufacturer, model, callback) {
        $.ajax({
            url: DataAccess.apiServerUrl + "/vehicles/" + this.cleanData(manufacturer) + "/" + this.cleanData(model) + ".jsonp",
            data: DataAccess.apiServerQueryStart,
            success: callback,
            dataType: 'jsonp'
        });
    },


    getLocationInfo: function (postalCode, callback) {
        $.ajax({
            url: DataAccess.apiServerUrl + "/location/" + postalCode + ".jsonp",
            data: DataAccess.apiServerQueryStart,
            success: callback,
            dataType: 'jsonp'
        });
    },
    
    
    guessLocation: function (callback) {
        $.ajax({
            url: DataAccess.apiServerUrl + "/location/current.jsonp",
            data: DataAccess.apiServerQueryStart,
            success: callback,
            dataType: 'jsonp'
        });
    },


    validateFields: function (Id, firstName, lastName, address, city, state, postalCode, email, phone, callback) {
        $.ajax({
            cache: false,
            url: DataAccess.apiServerUrl + "/lead/validate.jsonp",
            data: DataAccess.apiServerQueryStart + "&SellerDtxId=" + Id + "&FirstName=" + firstName + "&LastName=" + lastName + "&Address=" + address + "&City=" + city + "&State=" + state + "&PostalCode=" + postalCode + "&Email=" + email + "&Phone=" + phone,
            type: 'GET',
            success: callback,
            dataType: 'jsonp'
        });
    },


    getMakes: function (callback) {
        $.ajax({
            url: DataAccess.apiServerUrl + "/vehicles.jsonp",
            data: DataAccess.apiServerQueryStart,
            dataType: 'jsonp',
            success: callback
        });
    },


    getModels: function (year, make, callback) {
        $.ajax({
            url: DataAccess.apiServerUrl + "/vehicles/" + this.cleanData(make) + ".jsonp",
            data: DataAccess.apiServerQueryStart,
            dataType: 'jsonp',
            success: callback
        });
    }
};  // end DataAccess



// The form function handles most basic form functionality and displays
function Form() { }
Form.prototype.init = function () {
    var self = this;

    // when a trim is changed we must change the MSRP and invoice
    var MSRP = $("#trimSelect option:selected").attr("data-MSRP");
    var invoice = $("#trimSelect option:selected").attr("data-invoice");

    if (MSRP != '$0') {
        $(".MSRP").text("MSRP: " + MSRP);
    }

    if (invoice != '$0') {
        $(".invoice").text("Invoice: " + invoice);
    }

    var keepGoing = function (postalCode) {
        // apply the zipcode if one was retrieved from a dialog
        if (postalCode != null && postalCode != "") {
            $("#PostalCode").val(postalCode);
        }

        // do a ping back to server to get a list of dealers
        //var list = new DealerList();
        //list.init();

        // get rebate information
        //var oneCar = new OneCar();
        //oneCar.showShortIncentives();

        // activate the rest of the the panels on the page and trim selection
        self.imageSwitcherInit();
        self.cityStateInit();
        self.styleInformationInit();

        // make sure phone is put together at all times
        self.phoneInit();

        // validate fields on form submit
        $("form").submit(function () {
            return self.validateFields();
        });
    }

    var dialog = new PostalCodeDialog();
    dialog.init(function (postalCode) {
        keepGoing(postalCode);
    });

    // Disable this and the following "keepGoing(null)", and enable the above script
    // to have a popup asking for zip code to appear when the page loads.
    //    $("#PostalCode").focus(function () {
    //        $("#PostalCode").one('blur', function () {
    //            if ($("#PostalCode").val().length == 5) {
    //                keepGoing($("#PostalCode").val());
    //            }
    //            else {
    //                keepGoing(null);
    //            }

    //        });
    //    });
    //    keepGoing(null);
};


Form.prototype.validateFields = function () {
    // start up the wait gif
    var waitCursorImage = $("<img/>")
                                .attr("src", "../../Content/images/common/ajax-loader.gif")
                                .attr("id", "waitCursor")
                                .css("position", "absolute")
                                .css("top", ($(window).width() / 2) - 64)
                                .css("left", ($(window).height() / 2 - 7));

    var waitCursorPanel = $("<div></div>")
                                .attr("id", "waitCursorPanel")
                                .css("position", "absolute")
                                .css("height", $(document).height() + 'px')
                                .css("width", $(document).width() + 'px')
                                .css("top", '0px')
                                .css("left", '0px')
                                .addClass("transparentCover")
                                .append(waitCursorImage);

    $("body").append(waitCursorPanel);

    // check for missing or empty data
    var message = '';
    $("#FirstName,#LastName,#Address,#City,#stateSelect,#PostalCode,#Email,#Phone").each(function () {
        if ($.trim($(this).val()) == '') {
            message += $(this).attr("Name") + "\n";
        }
        else if ($(this).attr("id") == "Email") {
            if ($(this).val().indexOf('.') > 0 && $(this).val().indexOf('@') > 0) {
                // do nothing
            }
            else {
                message += "Please enter a valid email.\n";
            }
        }
    });

    if (message != '') {
        message = "Please fill in the following:\n" + message;
        alert(message);
        $("#waitCursorPanel").remove();
    }
    else {
        // check against more advanced validation
        DataAccess.validateFields($("#Id").val(), $("#FirstName").val(), $("#LastName").val(), $("#Address").val(), $("#City").val(), $("#stateSelect").val(), $("#PostalCode").val(), $("#Email").val(), $("#Phone").val(), function (result) {
            if (result.SUCCESS.toLowerCase() == "false") {
                if (result.FIELDS) {
                    var message = "The following fields have invalid values:\n";
                    for (var i = 0; i < result.FIELDS.length; i++) {
                        message += result.FIELDS[i] + "\n";
                    }
                    message += result.ERROR_MESSAGE;
                    alert(message);
                } else if (result.ERROR_MESSAGE) {
                    alert(result.ERROR_MESSAGE);
                }
                else {
                    alert("There was an error submitting the form. Please try again later.");
                }
                $("#waitCursorPanel").remove();
            }
            else {
                // submit the form
                $("form").unbind("submit");
                $("form").submit();
            }
        });
    }
    return false;
};


Form.prototype.phoneInit = function () {
    // if the phone field is already filled out then put it in the child fields
    var number = $("#Phone").val();
    if (number.length == 10) {
        $("#phone1").val(number.substring(0, 3));
        $("#phone2").val(number.substring(3, 6));
        $("#phone3").val(number.substring(6, 10));
    }

    // keep hidden field up to date
    $("#phone1,#phone2,#phone3").blur(function () {
        $("#Phone").val($("#phone1").val() + $("#phone2").val() + $("#phone3").val());
    });

    // clear the field on focus
    $("#phone1,#phone2,#phone3").focus(function () {
        $(this).val("");
    });

    $("#phone1,#phone2").keypress(function () {
        if ($(this).val().length >= 2) {
            $(this).val($(this).val().substring(0, 3));

            // we have to switch
            var field = this;
            window.setTimeout(function () {
                if ($(field).attr("id") == "phone1") {
                    $("#phone2").focus();
                } else {
                    $("#phone3").focus();
                }
            }, 50);
        }
    });
};


Form.prototype.cityStateInit = function () {
    // automatically fill in city and state based on postal code
    $("#PostalCode")
        .blur(function () {
            if ($(this).val() != null && $(this).val() != '') {
                DataAccess.getLocationInfo($(this).val(), function (data) {
                    if (data != null) {
                        $('#PostalCode').val(data.Zip);
                        $("#stateSelect").val(data.State);
                        $("#City").val(data.City);
                        var list = new DealerList();
                        list.init();
                    }
                });
            }
        }
    ).blur();
};


Form.prototype.styleInformationInit = function () {

    function setupStyleInfo() {
        // when a trim is changed we must set the style id
        $("#StyleId").val($("#trimSelect option:selected").attr("data-styleid"));

        // when a trim is changed we must change the MSRP
        var MSRP = $("#trimSelect option:selected").attr("data-msrp");
        if (MSRP != '$0') {
            $(".msrp").text("MSRP: " + MSRP);
        }
    }

    // get style information and use it throughout the form
    DataAccess.getStyleInfo($("#Year").val(), $("#Make").val(), $("#Model").val(), function (data) {
        $("#trimSelect").change(function () {
            setupStyleInfo();
        });
    });

    setupStyleInfo();
};


Form.prototype.imageSwitcherInit = function () {
    // create an in-memory copy of the image to get it's native size
    window.image = new Image();
    window.image.src = $("#bigCar").attr("src");

    // if it is only 1 pixel large when the image is finished loading then hide the whole area.
    window.intervalId = setInterval(function () {
        if (window.image.complete) {
            clearInterval(window.intervalId);

            // image is loaded so do test
            if (image.width == 1 && image.height == 1) {
                $(".colc,cold").html("");
            }
            else {
                $("#car1,#car2,#car3,#car4").click(function () {
                    $("#bigCar").attr("src", $(this).attr("src"));
                });
            }
        }
    }, 200);
};



// Postal Code dialog comes up when the page is hit without a postal code
var PostalCodeDialog = function() { };
PostalCodeDialog.prototype.init = function (completeCallback) {
    var self = this;
    this.callback = completeCallback;
    if ($("#PostalCode").val() == null || $("#PostalCode").val() == "") {
        //this.drawDialog();
        DataAccess.guessLocation(function (location) {
            $("#PostalCode").val(location.Zip);
            $("#City").val(location.City);
            $("#stateSelect").val(location.State);
            self.attachEvents();
//            var list = new DealerList();
//            list.init();
            completeCallback(location.Zip);
        });
    } else {
        completeCallback();
    }
};


PostalCodeDialog.prototype.drawDialog = function () {
    var overlay = $("<div></div>")
                    .attr("id", "postalCodeDialogOverlay")
                    .addClass("postal-code-dialog-overlay")
                    .addClass("transparentCover")
                    .css("position", "absolute")
                    .css("height", $(document).height() + 'px')
                    .css("width", $(document).width() + 'px')
                    .css("top", '0px')
                    .css("left", '0px')
                    .css("zIndex", "100");

    var dialog = $("<div></div>")
                    .attr("id", "postalCodeDialog")
                    .addClass("postal-code-dialog-frame")
                    .css("position", "absolute")
                    .css("height", '230px')
                    .css("width", '520px')
                    .css("background", "url('../../Content/images/backgrounds/postalCodeDialog.jpg') no-repeat left top")
                    .css("backgroundColor", "#000000")
                    .css("top", (($(window).height() / 2) - 115) + 'px')
                    .css("left", (($(window).width() / 2) - 260) + 'px')
                    .css("zIndex", "101");

    var p = $("<p></p>")
        .css("marginTop", "80px")
        .css("marginLeft", "40px")
        .css("marginRight", "40px")
        .css("fontFamily", "Georgia")
        .css("fontSize", "28px")
        .css("textAlign", "left")
        .text("Enter your zip code to find deals in your area:")
        .css("lineHeight", "40px")
        .appendTo(dialog);

    $("<input/>")
        .attr("id", "postalCodeDialogInput")
        .attr("type", "text")
        .addClass("postal-code-dialog-input")
        .css("fontSize", "28px")
        .css("width", "3em")
        .css("position", "relative")
        .css("left", "200px")
        .css("top", "-50px")
        .appendTo(dialog);

    // funny line of code below is due to write-once nonsense of IE
    dialog.html(dialog.html() + "<input type='image' id='postalCodeDialogButton' src='../../Content/images/buttons/check-deals.jpg' class='postal-code-dialog-button' value='Check Deals' style='position: relative; left: 230px; top: -37px'/>");
    
    overlay.appendTo(document.body);
    dialog.appendTo(document.body);
};


PostalCodeDialog.prototype.attachEvents = function () {
    var self = this;

    // if the window is resized, reposition the dialog and resize the overlay
    $(window).resize(function () {
        $("#postalCodeDialogOverlay")
            .css("height", $(document).height() + 'px')
            .css("width", $(document).width() + 'px');

        $("#postalCodeDialog")
            .css("top", (($(window).height() / 2) - 115) + 'px')
            .css("left", (($(window).width() / 2) - 260) + 'px');
    });

    // get the value of the zip code box and use it in the form
    $("#postalCodeDialogButton").click(function () {
        var input = $("#postalCodeDialogInput");
        input.disabled = true;

        // validate the zip code first
        if (input.val() != null && $.trim(input.val()) != "") {
            DataAccess.getLocationInfo(input.val(), function (info) {
                if (info != null && info.City != null && info.City != "") {
                    // good zip code, continue
                    self.close();
                    self.callback(input.val());
                } else {
                    alert("Please enter a valid zip code.");
                    input.disabled = false;
                }
            });
        }
    });

    // get when you press "enter" in the textbox, activate the button
    $("#postalCodeDialogInput").keydown(function (evt) {
        if (evt.keyCode == '13') {
            evt.preventDefault();
            $("#postalCodeDialogButton").click();
        }
    });

    $("#postalCodeDialogInput").focus();
};


PostalCodeDialog.prototype.close = function () {
    $("#postalCodeDialog").remove();
    $("#postalCodeDialogOverlay").remove();


    // when the dialog is closed we need to create a tracking impression
    var queryString = "?";
    $("input[name]").each(function (index, element) {
        if (index != 0) { queryString += "&" }
        queryString += $(this).attr("name") + "=" + $(this).val();
    });
    $("<iframe></iframe>")
        .attr("id", "trackingFrame")
        .attr("src", "/Form/InputPostalCode" + queryString)
        .css("width", "1px")
        .css("height", "1px")
        .css("visibility", "hidden")
        .width("1")
        .height("1")
        .appendTo("body");
};



// Dealer list controls the list of dealers
var DealerList = function () { };
DealerList.prototype.init = function () {
    // start up the wait gif and clear the drawing area
    var waitCursorImage = $("<img/>")
                                .attr("src", "../../Content/images/common/ajax-loader.gif")
                                .attr("id", "waitCursor")
                                .css("position", "relative")
                                .css("top", "80px")
                                .css("left", "75px");

    var waitCursorPanel = $("<div></div>")
                                .attr("id", "waitCursorPanel")
                                .css("height", "240px")
                                .css("width", "262px")
                                .append(waitCursorImage);

    $("#dealerlisting").empty().append(waitCursorPanel);
    this.showDealers();
};


// shows the list of dealers to the consumer
DealerList.prototype.showDealers = function () {
       
    // sub-function acts on a dealer list
    function applyDealers(data) {
        // we have the dealers, now display them
        var template = '<div class="dealerdetails"><div class="dealercheck"><input class="dealerCheckboxes" name="Dealers[{index}].Selected" checked="checked" type="checkbox" /></div><div class="name"><p class="dealertitle">{title}</p><p> {city}, {state} {postalcode}<br />{distance} Mile(s)</p></div>\n';
        var hiddenDetailTemplate = '<input type="hidden" name="Dealers[{index}].{fieldname}" value="{fieldvalue}" />';

        $("#dealerlisting")
            .empty()
            .css("minHeight", "240px")
            .css("minWidth", "300px")
            .css("maxWidth", "560px")
            .css("width", "100%")
            .css("overflow-x", "hidden");

        if (data.length > 0) {
            if (data.length == 1) {
                $("#howManyDealers").html("Compare deals from the dealer below:");
            }
            else {
                $("#howManyDealers").html("Compare deals from the dealers below:");
            }

            for (var i = 0; i < data.length; i++) {
                var infoBox = template
                                .replace(/\{index\}/, i)
                                .replace(/\{title\}/, capitalizeFirstLetter(data[i].Name.replace(/;/, "<br/>")))
                                .replace(/\{city\}/, data[i].City)
                                .replace(/\{state\}/, data[i].State)
                                .replace(/\{postalcode\}/, data[i].PostalCode)
                                .replace(/\{distance\}/, Math.round(data[i].Distance));
                $("#dealerlisting").html($("#dealerlisting").html() + infoBox);

                $("#dealerHiddenDetails").append(hiddenDetailTemplate
                                                    .replace(/\{index\}/, i)
                                                    .replace(/\{fieldname\}/, "Name")
                                                    .replace(/\{fieldvalue\}/, data[i].Name));

                $("#dealerHiddenDetails").append(hiddenDetailTemplate
                                                    .replace(/\{index\}/, i)
                                                    .replace(/\{fieldname\}/, "Street")
                                                    .replace(/\{fieldvalue\}/, data[i].Street));

                $("#dealerHiddenDetails").append(hiddenDetailTemplate
                                                    .replace(/\{index\}/, i)
                                                    .replace(/\{fieldname\}/, "State")
                                                    .replace(/\{fieldvalue\}/, data[i].State));

                $("#dealerHiddenDetails").append(hiddenDetailTemplate
                                                    .replace(/\{index\}/, i)
                                                    .replace(/\{fieldname\}/, "City")
                                                    .replace(/\{fieldvalue\}/, data[i].City));

                $("#dealerHiddenDetails").append(hiddenDetailTemplate
                                                    .replace(/\{index\}/, i)
                                                    .replace(/\{fieldname\}/, "PostalCode")
                                                    .replace(/\{fieldvalue\}/, data[i].PostalCode));

                $("#dealerHiddenDetails").append(hiddenDetailTemplate
                                                    .replace(/\{index\}/, i)
                                                    .replace(/\{fieldname\}/, "Distance")
                                                    .replace(/\{fieldvalue\}/, data[i].Distance));

                $("#dealerHiddenDetails").append(hiddenDetailTemplate
                                                    .replace(/\{index\}/, i)
                                                    .replace(/\{fieldname\}/, "ReservationId")
                                                    .replace(/\{fieldvalue\}/, data[i].ReservationId));

                $("#dealerHiddenDetails").append(hiddenDetailTemplate
                                                    .replace(/\{index\}/, i)
                                                    .replace(/\{fieldname\}/, "Price")
                                                    .replace(/\{fieldvalue\}/, data[i].Price));
            }

            // make sure the checkboxes update to true/false in a way that the server understands
            // (the element won't bind to the model if "value" is not set)
            $(".dealerCheckboxes").change(function () {
                if (this.checked == true) {
                    $(this).attr("value", "true");
                }
                else {
                    $(this).attr("value", "false");
                }
            }).change();
        }
        else {
            $("#howManyDealers")
                .css("text-align", "left")
                .html("<h1 style=\"margin-top: 20px;text-align: left;\">Find dealers in your area!</h1><p style=\"margin-top: 20px;\">Please fill out the form to the left to be contacted by a dealer near you.</p>");

            $("#dealerlisting")
                .css("minHeight", "180px")
                .css("height", "180px")
                .css("overflow-x", "hidden");
        }
    }
    
    var fromCookie = $.cookie('dealerCookie');
    
    if (fromCookie) {
        applyDealers($.evalJSON(fromCookie));
        
        // delete cookie content
        $.cookie('dealerCookie', null);
    }
    else {
        // Do a call to get back a list of dealer "data"
        DataAccess.getDealers($("#Id").val(), $("#Year").val(), $("#Make").val(), $("#Model").val(), $("#PostalCode").val(), function (data) {
            applyDealers(data);
        });
    }
};


// Make, model select box functionality
function VehicleSelectBox() {
    
    this.dealerCount = 0;
    this.isPingSeller = false;
    this.hasPingedDealers = false;
    
    var i;
    for (i = 0; i < PrePingSellers.length; i++) {
        if (apiId == PrePingSellers[i]) {
            this.isPingSeller = true;
            break;
        }
    }
    
}


VehicleSelectBox.prototype.init = function () {
    var self = this;

    var year = $("#Year").val();
    if (year == "") {
        year = new Date().getFullYear();
        $("#Year").val(year);
    }

    var makeSelect = this.populateMakes(year);
    makeSelect.change(function () {
        self.populateModels(year, makeSelect.val(), function () { 
            if (self.rotatorLink) {
                $("#modelSelect").val($(self.rotatorLink).attr("data-model"));
                self.rotatorLink = false;
                $("form#startHere").submit();
            }
        });
    });

    makeSelect.focus(function () {
        makeSelect.one('blur', function () {
            if (makeSelect.val() == "" || makeSelect.val() == "Select a Make" || makeSelect.val() == "MAKE" || makeSelect.val() == "noSelection") {
                self.errorMessage(this);
            }
            else {
                self.removeErrorMessage(this);
            }
        });
    });

    var modelSelect = $("#modelSelect");
    modelSelect.focus(function () {
        modelSelect.one('blur', function () {
            if (modelSelect.val() == "" || modelSelect.val() == "Select a Model" || modelSelect.val() == "MODEL" || modelSelect.val() == "noSelection") {
                self.errorMessage(this);
            }
            else {
                self.removeErrorMessage(this);
            }
        });
    });

    DataAccess.guessLocation(function (location) {
        $("#zipcode").val(location.Zip);

        $("#rotator .cola a,#rotator h3 a").each(function () {
            
            if (self.isPingSeller === true) {
                $(this).attr("href", "#");
                
                $(this).click(function () {
                    self.rotatorLink = this;
                    $("#makeSelect").val($(self.rotatorLink).attr("data-make"));
                    $("#makeSelect").change();
                });
                
            } else {
                $(this).attr("href", $(this).attr("href") + location.Zip);
            }
        });
    });

    var zipcode = $("#zipcode");
    zipcode.focus(function () {
        $(this).select();

        zipcode.one('blur', function () {
            if (zipcode.val() == "" || zipcode.val() == "ZIPCODE" || zipcode.val().length != 5) {
                self.errorMessage(this);
            }
            else {
                self.removeErrorMessage(this);
                
                if (self.isPingSeller ===  true) {
                    $("#rotator .cola a").each(function () {
                        $(this).attr("href", $(this).attr("href") + zipcode.val());
                    });
                }
            }
        });
    });

    $("form#startHere").submit(function () {
        if (self.isValid()) {
            if (self.isPingSeller === true) {
                
                if (self.dealerCount > 0) {
                    return true;
                }
                else {
                    var waitCursorPanel = $("<div></div>")
                                                .attr("id", "prePingWait")
                                                .css("position", "absolute")
                                                .css("top", '0px')
                                                .css("left", '0px')
                                                .width($(document).width())
                                                .height($(document).height())
                                                .css("background", "black")
                                                .css("zIndex", "100")
                                                .css("opacity", 0.5);

                    $(document.body).append(waitCursorPanel);
                    
                    // start up the wait gif
                    var waitCursorImage = $("<img/>");
                    waitCursorPanel.append(waitCursorImage);
                    waitCursorImage.attr("src", "../../Content/images/common/ajax-loader.gif")
                                   .attr("id", "waitCursorFirstPage")
                                   .css("position", "absolute")
                                   .css("top", ((waitCursorPanel.height() / 2) - 64) + 'px')
                                   .css("left", ((waitCursorPanel.width() / 2) - 7) + 'px');
                    
                    // start pinging
                    self.processPrePingSeller.call(self);
                }
                return false;
            }
            return true;
        }
        return false;
    });

    $("select#makeSelect").focus();
};


VehicleSelectBox.prototype.populateMakes = function (year) {
    var makeSelect = $("select#makeSelect")
                                .empty()
                                .append($('<option value="noSelection">Select a Make</option>'))
                                .attr('disabled', 'disabled');

    DataAccess.getMakes(function (vehicles) {
        if (vehicles) {
            for (var i = 0; i < vehicles.length; i++) {
                makeSelect.append(
                    $('<option></option>')
                        .attr("value", vehicles[i].Make)
                        .text(vehicles[i].Make)
                );
            }

            makeSelect.removeAttr('disabled');
        }
    });
    return $("select#makeSelect");
};


VehicleSelectBox.prototype.populateModels = function (year, make, callback) {
    var modelSelect = $("select#modelSelect")
                                .empty()
                                .append($('<option value="noSelection">Select a Model</option>'))
                                .attr('disabled', 'disabled');

    DataAccess.getModels(year, make, function (vehicles) {
        if (vehicles) {
            for (var i = 0; i < vehicles.length; i++) {
                modelSelect.append(
                    $('<option></option>')
                        .attr("value", vehicles[i].Model)
                        .text(vehicles[i].Model)
                );
            }
            modelSelect.removeAttr('disabled');
            if (callback)
                callback();
        }
    });
    return $("select#modelSelect");
};


VehicleSelectBox.prototype.processPrePingSeller = function () {

    var self = this;
    
    // delete the cookie
    $.cookie('dealerCookie', null);

    DataAccess.getDealers(apiId, new Date().getFullYear(), $("#makeSelect").val(), $("#modelSelect").val(), $("#zipcode").val(), function (data) {
        
        $("#prePingWait").remove();
        self.dealerCount = data.length;
        
        if (self.dealerCount == 0) {
            $('<div><p style="text-align: center; width: 100%; font-weight: bold; font-size: 2em;">No deals found.</p><p style="text-align: center; width: 100%;"> No deals available for a ' + $("#makeSelect").val() + ' ' + $("#modelSelect").val() + ' in zip code ' + $("#zipcode").val() + '. Please try again with a different Make/Model.</p></div>').dialog({
                autoOpen: true,
                modal: true,
                position: "center",
                closeOnEscape: true,
                title: "Please try again...",
                
                buttons: {
                    "Ok": function () {
                        $(this).dialog("close");
                    }
                }
            });
        }
        else {
            
            $.cookie('dealerCookie', $.toJSON(data), { expires: 1 });
            $("input#submit_startHere").click();
            
        }
        
    });
    
};


VehicleSelectBox.prototype.errorMessage = function(field) {
    var inputId = $(field).attr("id");
    var messageTopDefault = "Field Required";

    if ($("#error_"+inputId).length <= 0) {
        var output = "\n<p id='error_"+inputId+"' class='error'>";
            output += "\n\t<strong>"+messageTopDefault+"</strong>";
            output += "\n</p>";

        // apend the output AFTER the form element
        $("#"+inputId).after(output);
        $("#"+inputId).addClass("errorFocus");
    }
};


VehicleSelectBox.prototype.removeErrorMessage = function (field) {
    var inputId = $(field).attr("id");

    if ($("#error_"+inputId).length > 0) {
        // apend the output AFTER the form element
        $("#error_"+inputId).remove();
        $("#"+inputId).removeClass("errorFocus");
    }
};


VehicleSelectBox.prototype.isValid = function () {
    var isValid = false;
    var makeSelect = $("#makeSelect");
    var modelSelect = $("#modelSelect");
    var zipcode = $("#zipcode");

    if (makeSelect.val() == "" || makeSelect.val() == "Select a Make" || makeSelect.val() == "MAKE" || makeSelect.val() == "noSelection") {
        isValid = false;
    }
    else if (modelSelect.val() == "" || modelSelect.val() == "Select a Model" || modelSelect.val() == "MODEL" || modelSelect.val() == "noSelection") {
        isValid = false;
    }
    else if (zipcode.val() == "" || zipcode.val() == "ZIPCODE" || zipcode.val().length != 5) {
        isValid = false;
    }
    else {
        isValid = true;
    }
    return isValid;
};


// Vehicle image slide show on first page
function startImageSlides() {
    var init = $('#rotator').size();
    if (init != 0) {
        $('#rotator').innerfade({
            speed: 1000,
            timeout: 5000,
            type: 'sequence',
            containerheight: '170px',
            children: '.sample_deal_container'
        });
    }
}


// Capitalize First Letter of Each Word Like This
function capitalizeFirstLetter(s) {
    s = s.toLowerCase();
    var words = s.split(' ');
    var i;
    for (i = 0; i < words.length; i++) {
        words[i] = words[i].charAt(0).toUpperCase() + words[i].substring(1);
    }
    return words.join(' ');
}



// Cross Browser Xml Handling Functions
function XmlHandler(xmlstr) {
    this.xml = null;
    if (window.DOMParser) {
        var parser = new DOMParser();
        this.xml = parser.parseFromString(xmlstr, "text/xml");
    }
    else { // Internet Explorer
        this.xml = new ActiveXObject("Microsoft.XMLDOM");
        this.xml.async = "false";
        this.xml.loadXML(xmlstr);
    }
}


XmlHandler.prototype.evaluate = function (xpath) {
    if (window.DOMParser) {
        return this._docEvaluateArray(this.xml, xpath);
    }
    else { // internet explorer
        return this.xml.selectNodes(xpath);
    }
};


/// Recommended way from the mozilla dev site
// Example usage:
// var els = docEvaluateArray('//a');
// alert(els[0].nodeName); // gives 'A' in HTML document with at least one link
XmlHandler.prototype._docEvaluateArray = function (doc, expr, context, resolver) {
    doc = doc ? doc : (context ? context.ownerDocument : document);
    resolver = resolver ? resolver : null;
    context = context ? context : doc;

    var result = doc.evaluate(expr, context, resolver, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
    var a = [];
    for (var i = 0; i < result.snapshotLength; i++) {
        a[i] = result.snapshotItem(i);
    }
    return a;
};



// JS: Sort functions are uneven or broken between browsers so this is needed.
// Returns a sorted copy of the array that was passed in. The equalityTest
// parameter is a function that accepts two parameters and returns 0, 1, or -1
// like the function below.
function quicksort(array, equalityTest) {
    if (typeof equalityTest !== "function") {
        equalityTest = function (a, b) {
            if (a > b) {
                return 1;
            } else if (a < b) {
                return -1;
            }
            return 0;
        }
    }

    function part(a, leftIndex, rightIndex, pivotIndex) {
        var pivotValue = a.a[pivotIndex];
        a.a[pivotIndex] = a.a[rightIndex];
        a.a[rightIndex] = pivotValue;

        var storedIndex = leftIndex;
        var i;
        for (i = leftIndex; i < rightIndex; i++) {
            if (equalityTest(a.a[i], pivotValue) === -1) { // a.a[i] < pivotValue
                var t = a.a[i];
                a.a[i] = a.a[storedIndex];
                a.a[storedIndex] = t;
                storedIndex += 1;
            }
        }
        var t = a.a[storedIndex];
        a.a[storedIndex] = a.a[rightIndex];
        a.a[rightIndex] = t;
        return storedIndex;
    }

    function qsort(a, leftIndex, rightIndex) {
        if (rightIndex > leftIndex) {
            var pivotIndex = Math.round((leftIndex + rightIndex) / 2);
            var newPivotIndex = part(a, leftIndex, rightIndex, pivotIndex);
            qsort(a, leftIndex, newPivotIndex - 1);
            qsort(a, newPivotIndex + 1, rightIndex);
        }
    }
    var list = { a: array };
    qsort(list, 0, array.length - 1);
    return list.a;
}




