//basic model/observer adapted from http://www.bennadel.com/resources/projects/cormvc

// Create a closed memory space for the application definition and instantiation.
// This way, we keep the global name space clean.
(function ($) {

    /**
    * @constructor
    */
    function KeyValueCollection() {
        this.backingStore = {};
    }
    KeyValueCollection.prototype.addPair = function (key, value) {
        this.backingStore[key] = value;
    };
    KeyValueCollection.prototype.getValue = function (key) {
        return this.backingStore[key];
    };
    KeyValueCollection.prototype.contains = function (key) {
        return (this.backingStore[key] != null);
    };
    KeyValueCollection.prototype.each = function (fn) {
        return $.each(this.backingStore, fn);
    };
    KeyValueCollection.prototype.length = function () {
        //anything faster??
        var l = 0;
        $.each(this.backingStore, function (i, element) {
            l = l + 1;
        });
        return l;
    };

    function formatMonth(mIndex) {
        if (mIndex == 11) return 12;
        else return mIndex + 1;
    }

    /**
    * functionality for picking date range based on single date selection (used w/ rate calendar)
    *
    * @constructor
    */
    function DateRange(beginDate, endDate) {
        this.beginDate = beginDate;
        this.endDate = endDate;
        this.rangeOpen = true;
    }

    DateRange.prototype.updateDateRange = function (selectedDate) {
        if (this.rangeOpen) {
            this.beginDate = selectedDate;
            this.endDate = new Date(this.beginDate); //pass by val and set to same day then increment 1 day
            this.endDate.setDate(this.beginDate.getDate() + 1);
            this.rangeOpen = false;
        }
        else {
            if (selectedDate < this.beginDate) {
                this.endDate = this.beginDate;
                this.beginDate = selectedDate;
            }
            else if (selectedDate > this.beginDate) {
                //do nothing if ==
                this.endDate = selectedDate;
            }
            this.rangeOpen = true;
        }
        //fillDateFields();
    };

    /**
    * @constructor
    */
    function RateCalendar() {
        this.dateRange = {};
    }

    RateCalendar.prototype.newDateRange = function (beginDate, endDate) {
        this.dateRange = new DateRange(beginDate, endDate);
    };

    /**
    * @constructor
    */
    function RoomRateGroup(description) {
        //        this.ratePlanGroup = {
        //            RatePlanGroupCode: groupCode,
        //            Description: description
        //        };
        this.description = description;
        this.roomRates = [];
    }

    /**
    * @constructor
    */
    function Package(data) {
        this.data = data;
    }
    Package.prototype.getDescription = function () {
        alert(this.data.ShortDescription);
    };

    /**
    * @constructor
    */
    function CRS() {
        this.model = {
            RoomStays: [],
            RatePlanGroups: new KeyValueCollection(),
            RatePlanFilter: "all",
            CrsUrl: "",
            RateCalendar: new RateCalendar(),
            FirstSearchInitiated: false
        };
        this.roomStayViews = [];
        this.searchParameters = {
            Arrival: new Date(),
            Departure: new Date(),
            Adults: 0,
            Children: 0,
            _duration: 0,
            _y: 0,
            _m: 0,
            _d: 0
        };
        this.uiConfiguration = {
            HasCustomLandingView: false
        };
    }
    CRS.prototype.newKeyValueCollection = function () {
        return new KeyValueCollection();
    };
    CRS.prototype.updateRoomStays = function (roomStays) {
        this.model.RoomStays = roomStays;
        this.model.RatePlanGroups = new KeyValueCollection();
        //very redundant to cycle thru and re-add ratePlanGroups but most straightforward way to do it
        for (i = 0; i < roomStays.length; i += 1) {
            var ratePlans = roomStays[i].RatePlans;
            for (j = 0; j < ratePlans.length; j += 1) {
                this.model.RatePlanGroups.addPair(ratePlans[j].RatePlanGroup, ratePlans[j].RatePlanGroupDescription);
            }
        }
        this.model.FirstSearchInitiated = true;
        //reset RatePlanFilter to rack if currently applied filter is no longer applicable
        if (!this.model.RatePlanGroups.contains(this.model.RatePlanFilter)) {
            this.model.RatePlanFilter = 'all';
        }
        $('#tabs_container .rsObserver').trigger('roomStaysUpdated');
    };
    //getters/setters?? -not yet
    CRS.prototype.updateSearchParms = function (arrivalDate, departureDate, adults, children) {
        this.searchParameters.Arrival = arrivalDate;
        this.searchParameters.Departure = departureDate;
        this.searchParameters.Adults = adults;
        this.searchParameters.Children = children;

        var one_day = 86400000;
        var timeDiff = departureDate.getTime() - arrivalDate.getTime();
        this.searchParameters._duration = Math.ceil(timeDiff / one_day);

        this.searchParameters._y = arrivalDate.getFullYear();
        this.searchParameters._m = formatMonth(arrivalDate.getMonth());
        this.searchParameters._d = arrivalDate.getDate();

        $('.searchParmsObserver').trigger('searchParmsUpdated');
    };
    CRS.prototype.setRatePlanFilter = function (ratePlanGroupCode) {
        this.model.RatePlanFilter = ratePlanGroupCode;
        $('#tabs_container .rsObserver').trigger('roomStaysUpdated');
    };
    //let CRS obj centrally manage serivce url's
    //getUrl functions with parms simply bind those parms to the url - they don't change internal state
    CRS.prototype.setBaseUrl = function (url) {
        this.model.CrsUrl = url;
    };
    CRS.prototype.getBaseUrl = function () {
        return this.model.CrsUrl;
    };
    CRS.prototype.getUrl = function () {
        var y = this.searchParameters._y;
        var m = this.searchParameters._m;
        var d = this.searchParameters._d;
        var days = this.searchParameters._duration;
        var ad = this.searchParameters.Adults;
        var ch = this.searchParameters.Children;
        //alert(this.model.CrsUrl);

        return this.model.CrsUrl + y + "/" + m + "/" + d + "/" + days + "/" + ad + "/" + ch + "/";
    };
    CRS.prototype.getUrlDateRange = function (arrivalDate, departureDate) {
        var y = arrivalDate.getFullYear();
        var m = formatMonth(arrivalDate.getMonth());
        var d = arrivalDate.getDate();
        var one_day = 86400000;
        var timeDiff = departureDate.getTime() - arrivalDate.getTime();
        var days = Math.ceil(timeDiff / one_day);
        var ad = this.searchParameters.Adults;
        var ch = this.searchParameters.Children;

        return this.model.CrsUrl + y + "/" + m + "/" + d + "/" + days + "/" + ad + "/" + ch + "/";
    };
    CRS.prototype.formatMonth = function (mIndex) {
        return formatMonth(mIndex);
    };
    CRS.prototype.getRoomStay = function (propertyID) {
        var rs;
        var ratePlanFilter = this.model.RatePlanFilter;
        $.each(this.model.RoomStays, function (i, roomStay) {
            if (roomStay.LocationDescription == propertyID) //sketchy id but all we have
            {
                if (ratePlanFilter == "all") {
                    rs = roomStay;
                }
                else {
                    //get all rp's with selected rpg and only include rates contained
                    var ratePlanCodes = [];
                    $.each(roomStay.RatePlans, function (i, ratePlan) {
                        if (ratePlan.RatePlanGroup == ratePlanFilter) {
                            ratePlanCodes.push(ratePlan.RatePlanCode);
                        }
                    });

                    //clone RoomStay
                    rs = $.extend(true, {}, roomStay);
                    rs.RoomRates = [];

                    //build new RoomRate array with only filtered rp's
                    var roomRates = [];
                    $.each(roomStay.RoomRates, function (i, roomRate) {
                        if ($.inArray(roomRate.RatePlanCode, ratePlanCodes) !== -1) {
                            rs.RoomRates.push($.extend(true, {}, roomRate));
                        }
                    });
                }
                return false;
            }
        });
        return rs;
    };
    CRS.prototype.getRoomStays = function () {
        var roomStays = [];
        var ratePlanFilter = this.model.RatePlanFilter;
        $.each(this.model.RoomStays, function (i, roomStay) {
            var rs;
            if (ratePlanFilter == "all") {
                rs = roomStay;
            }
            else {
                //get all rp's with selected rpg and only include rates contained
                var ratePlanCodes = [];
                $.each(roomStay.RatePlans, function (i, ratePlan) {
                    if (ratePlan.RatePlanGroup == ratePlanFilter) {
                        ratePlanCodes.push(ratePlan.RatePlanCode);
                    }
                });

                //clone RoomStay
                rs = $.extend(true, {}, roomStay);
                rs.RoomRates = [];

                //build new RoomRate array with only filtered rp's
                var roomRates = [];
                $.each(roomStay.RoomRates, function (i, roomRate) {
                    if ($.inArray(roomRate.RatePlanCode, ratePlanCodes) !== -1) {
                        rs.RoomRates.push($.extend(true, {}, roomRate));
                    }
                });
            }
            roomStays.push(rs);
        });
        return roomStays;
    };
    CRS.prototype.getRatePlanGroupDescription = function (ratePlanCode, roomStay) {
        $.each(roomStay.RatePlans, function (i, ratePlan) {
            if (ratePlan.RatePlanCode == ratePlanCode) {
                return ratePlan.RatePlanGroupDescription;
            }
        });
        return "";
    };
    CRS.prototype.getRatePlanGroups = function () {
        return this.model.RatePlanGroups;
    };
    CRS.prototype.getRoomRatesByRatePlanGroup = function (roomStay) {
        var ratePlanLUT = new KeyValueCollection();
        var ratePlanGroupLUT = new KeyValueCollection();
        var groupedRoomRatesCollection = new KeyValueCollection();

        $.each(roomStay.RatePlans, function (i, ratePlan) {
            ratePlanLUT.addPair(ratePlan.RatePlanCode, ratePlan.RatePlanGroup);
            ratePlanGroupLUT.addPair(ratePlan.RatePlanGroup, ratePlan.RatePlanGroupDescription);
        });

        ratePlanGroupLUT.each(function (k, v) {
            var rrGroup = new RoomRateGroup(v);
            groupedRoomRatesCollection.addPair(k, rrGroup);
        });

		$.each(roomStay.RoomRates, function (i, roomRate) {
            var rpg = ratePlanLUT.getValue(roomRate.RatePlanCode);
            var roomRateGroup = groupedRoomRatesCollection.getValue(rpg);
            roomRateGroup.roomRates.push(roomRate);
        });

        return groupedRoomRatesCollection;
    };
    CRS.prototype.newRoomStayView = function (viewElement) {
        return new RoomStayView(viewElement);
    };
    CRS.prototype.addRoomStayView = function (viewElement) {
        var rsv = new RoomStayView(viewElement);
        this.roomStayViews.push(rsv);
        return rsv;
    };
    CRS.prototype.getRoomStayView = function (viewID) {
        var rsv;
        $.each(this.roomStayViews, function (i, roomStayView) {
            if (roomStayView.identifier == viewID) {
                rsv = roomStayView;
                return false;
            }
        });
        return rsv;
    };
    CRS.prototype.initDateRange = function (beginDate, endDate) {
        this.model.RateCalendar.newDateRange(beginDate, endDate);
    };
    CRS.prototype.FirstSearchInitiated = function () {
        return this.model.FirstSearchInitiated;
    };
    CRS.prototype.setUIConfiguration = function (uiConfigParms) {
        this.uiConfiguration = uiConfigParms;
    };
    CRS.prototype.getUIConfiguration = function () {
        return this.uiConfiguration;
    };

    /**
    * @constructor
    */
    function RoomStayView(viewElement) {
        //RoomStayView has collection of RoomStays because in some situations RoomStays & UI panels are not 1:1
        this.model = {
            RoomStays: []
        };
        this.identifier = viewElement.attr('id');
        this.viewElement = viewElement;
        this.headerText = viewElement.text();
        this.roomElementLookup = crs.newKeyValueCollection();
        this.roomTypeCategoryList = [];
    }
    RoomStayView.prototype.clearRoomStays = function () {
        this.model.RoomStays = [];
    };
    RoomStayView.prototype.addRoomStay = function (roomStay) {
        this.model.RoomStays.push(roomStay);
    };
    RoomStayView.prototype.initView = function () {
        var roomCount = 0;
        $.each(this.model.RoomStays, function (i, roomStay) {
            if (roomStay != null) roomCount += roomStay.RoomRates.length || 0;
        });
        if (roomCount > 0) {
            var heading = this.headerText + ' (' + roomCount + ')';
            this.viewElement.html(heading);
        }
        else this.viewElement.html(this.headerText);

        var roomList = $('#' + this.identifier).attr("rel");
        $('.roomRate', roomList).remove(); //remove previous query results

        var roomStays = this.model.RoomStays;
        var roomLUT = this.roomElementLookup;
        var roomTypeRoomCount = this.roomTypeCategoryList;

        var getPackageDescription = function (ratePlanCode, roomStay) {
            var rpDesc = "";
            $.each(roomStay.RatePlans, function (i, ratePlan) {
                if (ratePlan.RatePlanCode == ratePlanCode) {
                    if (ratePlan.RatePlanGroup != 'rack') {
                        rpDesc = ratePlan.RatePlanGroupDescription;
                        return false;
                    }
                }
            });
            return rpDesc;
        };

        var getRatePlanGroupCode = function (ratePlanCode, roomStay) {
            var ratePlanGroup = "";
            $.each(roomStay.RatePlans, function (i, ratePlan) {
                if (ratePlan.RatePlanCode == ratePlanCode) {
                    ratePlanGroup = ratePlan.RatePlanGroup;
                    return false;
                }
            });
            return ratePlanGroup;
        };

        //associative arrays really obj hashes in js so array['something'] and array.length don't operate on the same underlying obj
        //roomList limits scope to local ul
        $('ul.v-tabs li a', roomList).each(function (i, o) {
            var rt = roomTypeRoomCount[$(o).attr("rel")];
            if (rt != null) rt[1] = 0; //reset room count
        });

        //not looping thru the whole crs model, just the local RoomStays - each panel can have more than one RoomStay
        $.each(roomStays, function (i, roomStay) {
            if ((roomStay != null) && (roomStay.RoomRates != null)) {
                $.each(roomStay.RoomRates, function (j, roomRate) {
                    var roomElement = roomLUT.getValue(roomRate.RoomType.RoomTypeCode);
                    if (roomElement != null) {
                        if (roomTypeRoomCount[roomElement] == null) {
                            roomTypeRoomCount[roomElement] = [];
                            //roomTypeRoomCount[roomElement][0] = roomRate.RoomType.RoomTypeDescription;
                            roomTypeRoomCount[roomElement][1] = 0;
                        }
                        roomTypeRoomCount[roomElement][1] += 1;
                        var roomTypeLI = $("ul.v-tabs li a[rel ='" + roomElement + "']", roomList).parent();
                        var roomRateElem = $('#roomRateTemplate').clone();
                        //$(roomRateElem).attr("id", "property" + i + "roomType" + j);
                        $(roomRateElem).attr("id", "rt-" + roomRate.RoomType.RoomTypeCode + '-' + roomRate.RatePlanCode); //THIS WILL NEED TO CHANGE WHEN PKGS ARE ADDED
                        $(roomRateElem).attr("class", "roomRate");
                        $('.description', roomRateElem).html(roomRate.RoomType.RoomTypeDescription);
                        var pkgDescription = getPackageDescription(roomRate.RatePlanCode, roomStay);
                        if (pkgDescription != "") {
                            $('.package span', roomRateElem).html(pkgDescription);
                            $('.package span', roomRateElem).attr("class", getRatePlanGroupCode(roomRate.RatePlanCode, roomStay));
                        }
                        else {
                            $('.package', roomRateElem).remove();
                        }
                        $('.avgDailyRate', roomRateElem).html("$" + roomRate.Rates[0].DailyRates[0].Amount.toFixed(2));
                        $('.bookLink', roomRateElem).click(function () {

                            //$('.crr', roomRateElem).submit();
                            setTimeout(function () { $('.crr', roomRateElem).submit(); }, 0); //ie6 compat
                        });
                        $('.rcLink', roomRateElem).click(function () {
                            $(this).trigger('rcLinkClick', [roomRate]);
                        });
                        $('.crr', roomRateElem).attr("action", roomRate.BookingUrl);
                        //redundant memory-wise to copy common roomStay stuff into state form but might be the simplest way
                        $('.rsRequestParms', roomRateElem).val(roomStay.RequestParms);
                        $('.rsParmChecksum', roomRateElem).val(roomStay.ParmChecksum);
                        $('.requestParms', roomRateElem).val(roomRate.RequestParms);
                        $('.parmChecksum', roomRateElem).val(roomRate.ParmChecksum);
                        roomTypeLI.append(roomRateElem);
                    }
                });
            }
        });

        //roomList limits scope to local ul
        $('ul.v-tabs li a', roomList).each(function (i, o) {
            // alert(o);
            //alert($(o).attr("rel"));
            var rt = roomTypeRoomCount[$(o).attr("rel")];
            //alert(cnt);
            if (rt != null) {
                //can't short circuit b/c rt isn't ever used if roomType and element#id are never bound
                if (rt[0] == null) {
                    rt[0] = $(o).html(); //set to original markup based <a> content
                }
                if (rt[1] > 0) {
                    $(o).html(rt[0] + ' (' + rt[1] + ')');
                }
                else $(o).html(rt[0]);
            }
            else {
                rt = [];
                rt[0] = $(o).html(); //set to original markup based <a> content
                rt[1] = 0;
            }
        });
    };

    // Create a new instance of the application and store it in the window.
    window.crs = new CRS();

    // When the DOM is ready, run the application.
    //$(function(){
    //	window.application.run();
    //});

    // Return a new application instance.
    return (window.crs);
})(jQuery);


$(document).ready(function () {
    var arrDate = new Date();
    var depDate; // = new Date();
    var uiConfig = crs.getUIConfiguration();
    if ((uiConfig.DefaultArrivalDate != null) && (uiConfig.DefaultDepartureDate != null) && (uiConfig.DefaultArrivalDate != '0001-01-01')) {
        var datepart = uiConfig.DefaultArrivalDate.split('-');
        var dateStr = datepart[1] + '/' + datepart[2] + '/' + datepart[0];
        arrDate = new Date(Date.parse(dateStr));
        datepart = uiConfig.DefaultDepartureDate.split('-');
        dateStr = datepart[1] + '/' + datepart[2] + '/' + datepart[0];
        depDate = new Date(Date.parse(dateStr));
    }
    else {
        arrDate.setDate(arrDate.getDate() + 1);
        depDate = new Date(arrDate.getFullYear(), arrDate.getMonth(), arrDate.getDate() + 1);
    }

    crs.updateSearchParms(arrDate, depDate, 2, 0);

    var crsUrl = $.address.baseURL() + "/search/";
    crs.setBaseUrl(crsUrl);

    //still need fillDateFields() to kick off manual update before events are fully registered
    fillDateFields();

    $("#searchQuery .arrival").datepicker({
        onSelect: function (dateText, inst) {
            arrDate = new Date(Date.parse(dateText));
            //temporary - redo
            depDate = new Date(arrDate); //pass by val and set to same day then increment 1 day
            depDate.setDate(arrDate.getDate() + 1);
            crs.updateSearchParms(arrDate, depDate, crs.searchParameters.Adults, crs.searchParameters.Children);
            $("#searchQuery .departure").val(formatMonth(depDate.getMonth()) + '/' + depDate.getDate() + '/' + depDate.getFullYear());
        }
    });
    $("#searchQuery .departure").datepicker({
        onSelect: function (dateText, inst) {
            depDate = new Date(Date.parse(dateText));
            crs.updateSearchParms(crs.searchParameters.Arrival, depDate, crs.searchParameters.Adults, crs.searchParameters.Children);
        }
    });
    $("#searchQuery .adults").change(function () {
        crs.updateSearchParms(crs.searchParameters.Arrival, crs.searchParameters.Departure, $('option:selected', this).val(), crs.searchParameters.Children);
    });
    $("#searchQuery .children").change(function () {
        crs.updateSearchParms(crs.searchParameters.Arrival, crs.searchParameters.Departure, crs.searchParameters.Adults, $('option:selected', this).val());
    });

    //monitor for deep linked url from the outside (widget or otherwise)
    $.address.externalChange(function () {
        var _address = $.address.path();
        if (_address != '/') {
            var parms = $.address.pathNames();
            var l3Fragment = getTabUrlFragment(_address);
            if (l3Fragment.length > 0) {
                parms.shift();
            }
            var arr = crs.searchParameters.Arrival;
            var dep = crs.searchParameters.Departure;
            var ad = crs.searchParameters.Adults;
            var ch = crs.searchParameters.Children;
            try {
                if (parms.length > 5) {
                    var y = parms.shift();
                    var m = parms.shift();
                    var d = parms.shift();
                    var len = parseInt(parms.shift(), 10);
                    var dateStr = m + '/' + d + '/' + y;
                    arr = new Date(Date.parse(dateStr));
                    dep = new Date(arr);
                    dep.setDate(arr.getDate() + len);
                    ad = parseInt(parms.shift(), 10);
                    ch = parseInt(parms.shift(), 10);

                    crs.updateSearchParms(arr, dep, ad, ch);
                    availabilitySearch();
                }
                else if (parms.length == 1) {
                    //alert('jnk');
                    $.getJSON($.address.baseURL() + '/package/' + parms.shift() + '/', null, function (data) {

                        var today = new Date();
                        var pBegin = $.fullCalendar.parseISO8601(data.Dates.Begin, true),
                            pEnd = $.fullCalendar.parseISO8601(data.Dates.End, true);
                        if (today < pEnd) {
                            if (arr < pBegin) {
                                //push up to pkg begin
                                arr = pBegin;
                            }
                            else if (arr >= pEnd) {
                                //today has been determined valid so fallback to it
                                arr = today;
                            }
                            else {
                                //loop thru any blackout dates and push arrival ahead
                                $.each(data.Dates.BlackoutDate, function (i, bDate) {
                                    if ((arr >= bDate.Begin) && (arr <= bDate.End)) {
                                        arr = new Date(bDate.End.getFullYear(), bDate.End.getMonth(), bDate.End.getDate() + 1);
                                    }
                                });
                            }
                            //just always default dep to 1 day later
                            dep = new Date(arr.getFullYear(), arr.getMonth(), arr.getDate() + 1);
                            crs.setRatePlanFilter(data.PackageID);

                            crs.updateSearchParms(arr, dep, ad, ch);
                            availabilitySearch();
                        }
                        else {
                            //package over
                            alert("The offer " + data.ShortDescription + " is no longer available.");
                        }
                    });
                }
            }
            catch (Error) {
                //ignore url fragment
                alert(Error);
            }
        }
    });

    $('#searchAvailability').click(function () {
        availabilitySearch();
    });

    $('.searchParmsObserver').bind('searchParmsUpdated', function () {
        var dateParm = crs.searchParameters.Arrival;
        $('.arrival', this).val(formatMonth(dateParm.getMonth()) + '/' + dateParm.getDate() + '/' + dateParm.getFullYear());
        dateParm = crs.searchParameters.Departure;
        $('.departure', this).val(formatMonth(dateParm.getMonth()) + '/' + dateParm.getDate() + '/' + dateParm.getFullYear());
        $('.adults', this).val(crs.searchParameters.Adults);
        $('.children', this).val(crs.searchParameters.Children);
        $('.adults option[value=' + crs.searchParameters.Adults + ']', this).attr("selected", "selected");
        $('.children option[value=' + crs.searchParameters.Children + ']', this).attr("selected", "selected");
        //alert(crs.searchParameters.Children);

        //update url
        var l3Fragment = getTabUrlFragment($.address.path());
        if (l3Fragment.length > 0) l3Fragment += '/'; //only add slash if not empty
        var spPath = l3Fragment + crs.searchParameters._y + '/' + crs.searchParameters._m + '/' + crs.searchParameters._d + '/';
        spPath += crs.searchParameters._duration + '/' + crs.searchParameters.Adults + '/' + crs.searchParameters.Children + '/';
        $.address.value(spPath);
    });

    $('#searchResults').bind('roomStaysUpdated', function () {
        $('#searchResults').empty();

        if ($('#tabComparison').length == 0) {
            var compareAll = $('#tabIsolatedRightTemplate').clone();
            $(compareAll).attr("class", "tabIsolatedRight");
            $(compareAll).attr("id", "tabComparison");
            //register click handler
            $('li a.tab', compareAll).click(function () {
                $('#tabs_container .tabs > li.active').removeClass('active');
                $('#tabs_container .tabIsolatedRight.active').removeClass('active');
                $(this).closest('.tabLeft').addClass('active');
                $(this).closest('.tabIsolatedRight').addClass('active');
                $('#tabs_container > .tabbed_content > div.active').removeClass('active');
                $(this.rel).addClass('active');
                //append l3 parms to tab generated address
                var curTab = getTabUrlFragment($.address.path());
                var curFragment = $.address.value(); //might be something other than a tab
                if ((curFragment.length > 0) && (curTab.length > 0)) {
                    $.address.value($.address.value().replace(curTab, this.rel.substring(1)));
                }
                else if (curFragment.length > 0) {
                    $.address.value(this.rel.substring(1) + curFragment);
                }
                else {
                    $.address.value(this.rel.substring(1));
                }
            });
            $('#tabs_container').prepend(compareAll);
        }

        var roomStays = crs.getRoomStays();
        $.each(roomStays, function (i, roomStay) {
            var property = $('#searchResultPropertyTemplate').clone();
            var propertyID = "property" + i; //save as var for use in :last jquery filters
            $(property).attr("id", propertyID);
            $(property).attr("class", "searchResultProperty");
            $('.propertyName', property).html(roomStay.LocationDescription);
            $('#searchResults').append(property);

            var roomRateGroupC = crs.getRoomRatesByRatePlanGroup(roomStay)
            roomRateGroupC.each(function (rateGroupCode, roomRateGroup) {

                if (roomRateGroup.roomRates.length > 0) {
                    //alert(roomRateGroup.description);
                    property.append("<h4>" + roomRateGroup.description + "</h4");

                    var roomTypeTable = $('#searchResultRoomTypeTblTemplate').clone();
                    //alert(propertyID + rateGroupCode);
                    $(roomTypeTable).attr("id", propertyID + rateGroupCode);
                    $(roomTypeTable).attr("class", "searchResultRoomTypes");

                    $.each(roomRateGroup.roomRates, function (j, roomRate) {
                        var roomType = $('#searchResultRoomTypeTemplate').clone();
                        $(roomType).attr("id", "cmp-" + roomRate.RoomType.RoomTypeCode + roomRate.RatePlanCode);
                        $(roomType).attr("class", "searchResultRoomType");
                        $('.description', roomType).html(roomRate.RoomType.RoomTypeDescription);
                        $('.avgRate', roomType).html("$" + roomRate.Rates[0].DailyRates[0].Amount.toFixed(2) + " Avg Daily");
                        $('td', roomType).filter(':last').addClass('last');

                        $('.calLink', roomType).click(function () {
                            displayRateCalendar(roomRate);
                        });

                        var roomRateElem = $("#rt-" + roomRate.RoomType.RoomTypeCode + "-" + roomRate.RatePlanCode);
                        $('.bookLink:not(.calLink)', roomType).click(function () {
                            setTimeout(function () { $('.crr', roomRateElem).submit(); }, 0); //ie6 compat
                        });

                        roomTypeTable.append(roomType);
                    });


                    property.append(roomTypeTable);
                    //alert(roomTypeTable);
                }
            });

            /*$.each(roomStay.RoomRates, function (j, roomRate) {
            var roomType = $('#searchResultRoomTypeTemplate').clone();
            $(roomType).attr("id", "cmp-" + roomRate.RoomType.RoomTypeCode);
            $(roomType).attr("class", "searchResultRoomType");
            $('.description', roomType).html(roomRate.RoomType.RoomTypeDescription);
            $('.avgRate', roomType).html("$" + roomRate.Rates[0].DailyRates[0].Amount.toFixed(2) + " Avg Daily");
            $('td', roomType).filter(':last').addClass('last');

            $('.calLink', roomType).click(function () {
            displayRateCalendar(roomRate);
            });

            var roomRateElem = $("#rp-" + roomRate.RoomType.RoomTypeCode);
            $('.bookLink:not(.calLink)', roomType).click(function () {
            setTimeout(function () { $('.crr', roomRateElem).submit(); }, 0); //ie6 compat
            });

            $('.searchResultRoomTypes', property).append(roomType);
            });*/

            $('#' + propertyID + ' .searchResultRoomType').filter(':last').addClass('last');
        });

        $('.roomRate .rcLink').bind('rcLinkClick', function (event, roomRate) {
            displayRateCalendar(roomRate);
        });
    });

    //assign RoomStay and RoomType bindings
    var view = crs.addRoomStayView($('#t-sun-valley-lodge'));
    var lut = view.roomElementLookup;
    /*lut.addPair('DY', '#LD');
    lut.addPair('LD', '#LD');
	lut.addPair('LM', '#LM');
    lut.addPair('MZ', '#LM');
    lut.addPair('LS', '#LS');
    lut.addPair('LB', '#LB');
    lut.addPair('PS', '#PS');
    lut.addPair('FS', '#FS');*/
	lut.addPair('LB1K', '#LB');
	lut.addPair('LB2Q', '#LB');
	lut.addPair('LD1K', '#LD');
	lut.addPair('LD2Q', '#LD');
	lut.addPair('LFS', '#FS');
	lut.addPair('LM1K', '#LM');
	lut.addPair('LM2D', '#LM');
	lut.addPair('LPS', '#PS');
	lut.addPair('LS1Q', '#LS');

    view = crs.addRoomStayView($('#t-sun-valley-inn'));
    lut = view.roomElementLookup;
    /*lut.addPair('IA', '#IA');
    lut.addPair('ID', '#ID');
    lut.addPair('IQ', '#ID');
    lut.addPair('IJ', '#IJ');
    lut.addPair('IF', '#IF');
    lut.addPair('IY', '#IY');
    lut.addPair('IP', '#IP');
    lut.addPair('IS', '#IS');*/
	lut.addPair('IA', '#IA');
	lut.addPair('ID1K', '#ID');
	lut.addPair('ID2Q', '#ID');
	lut.addPair('IFS', '#IF');
	lut.addPair('IJS', '#IJ');
	lut.addPair('IM1K', '#IY');
	lut.addPair('IM1Q', '#IY');
	lut.addPair('IM2D', '#IY');
	lut.addPair('IPS', '#IP');
	lut.addPair('IS1Q', '#IS');

    view = crs.addRoomStayView($('#t-condominiums'));
    lut = view.roomElementLookup;
    /*lut.addPair('AB', '#LAP');
    lut.addPair('A2', '#LAP');
    lut.addPair('A3', '#LAP');
    lut.addPair('2A', '#LAP');
    lut.addPair('3A', '#LAP');
    lut.addPair('AT', '#C2');
    lut.addPair('CS', '#CS');
    lut.addPair('C1', '#C1');
    lut.addPair('C2', '#C2');
    lut.addPair('C3', '#C3');
    lut.addPair('C4', '#C4');*/
	lut.addPair('2BLA', '#LAP');
	lut.addPair('3BLA', '#LAP');
	lut.addPair('L2A2', '#LAP2');
	lut.addPair('L2A3', '#LAP2');
	lut.addPair('LAB', '#LAP');
	lut.addPair('LAS2', '#LAP');
	lut.addPair('LAS3', '#LAP');
	lut.addPair('W1', '#DW');
	lut.addPair('W2', '#DW');
	lut.addPair('W3', '#DW');
	lut.addPair('1C1K', '#C1');
	lut.addPair('1C1Q', '#C1');
	lut.addPair('2C2B', '#C2');
	lut.addPair('2C3B', '#C2');
	lut.addPair('3C3B', '#C3');
	lut.addPair('3C4B', '#C3');
	lut.addPair('3C5B', '#C3');
	lut.addPair('AT', '#C2');
	lut.addPair('C4', '#C4');
	lut.addPair('CS1Q', '#CS');

    view = crs.addRoomStayView($('#t-cottages'));
    lut = view.roomElementLookup;
    //lut.addPair('EC', '#EC');
	lut.addPair('DCT', '#vt21');
	lut.addPair('GCT', '#vt22');
	lut.addPair('HCT', '#vt23');
	lut.addPair('LCT', '#vt24');
	lut.addPair('PCT', '#vt25');
	lut.addPair('SCT', '#vt26');
	lut.addPair('VCT', '#vt27');

    $('#t-sun-valley-lodge').bind('roomStaysUpdated', function () {
        var view = crs.getRoomStayView('t-sun-valley-lodge');
        view.clearRoomStays();
        view.addRoomStay(crs.getRoomStay('Sun Valley Lodge'));
		view.initView();
    });

    $('#t-sun-valley-inn').bind('roomStaysUpdated', function () {
        var view = crs.getRoomStayView('t-sun-valley-inn');
        view.clearRoomStays();
        view.addRoomStay(crs.getRoomStay('Sun Valley Inn'));
        view.initView();
    });

    $('#t-condominiums').bind('roomStaysUpdated', function () {
        var view = crs.getRoomStayView('t-condominiums');
        view.clearRoomStays();
        view.addRoomStay(crs.getRoomStay('Deluxe Condominium'));
        view.addRoomStay(crs.getRoomStay('Standard Condominium'));
        view.initView();
    });

    $('#t-cottages').bind('roomStaysUpdated', function () {
        var view = crs.getRoomStayView('t-cottages');
        view.clearRoomStays();
        view.addRoomStay(crs.getRoomStay('Cottages'));
        view.initView();
    });

    function availabilitySearch() {
        if ($('#searchQuery .messages').length == 0) {
            $('#searchQuery').append("<div class='messages'></div>");
        }
        $('#searchQuery .messages').empty();

        var searchStatus = $('#searchProcessingTemplate').clone();
        $(searchStatus).attr("class", "searchStatus");
        $(searchStatus).attr("id", "searchStatus");
        $('#searchQuery').append(searchStatus);

        $.getJSON(crs.getUrl(), null, function (data) {
            $('#searchQuery #searchStatus').remove();

            if (data.RoomStays) {
                crs.updateRoomStays(data.RoomStays);

                var uiConfig = crs.getUIConfiguration();
                if (uiConfig.HasCustomLandingView) {
                    //$('#group-logo').fadeOut(100);
                    //$('#bookingUIWrapper').fadeIn(400);
                    $('#group-logo').hide();
                    $('#bookingUIWrapper').fadeIn(300);
                }

                var roomCount = 0;
                $.each(crs.model.RoomStays, function (i, roomStay) {
                    $.each(roomStay.RoomRates, function (j, roomRate) {
                        roomCount++;
                    });
                });

                var ratePlanGroups = crs.getRatePlanGroups();
                if (ratePlanGroups.length() > 1) {
                    //will always be 1 rpg (rack)
                    var ratePlanFilter = $('#multiRatePlanTemplate').clone();
                    var rpDropdown = $('#rpSelect', ratePlanFilter);

                    ratePlanGroups.each(function (k, v) {
                        rpDropdown.append("<option value='" + k + "'>" + v + "</option>");
                    });
                    $(ratePlanFilter).attr("class", "ratePlanMessage");
                    $(ratePlanFilter).attr("id", "ratePlanFilter");

                    //doing this after append in case 'rack' (default predefined) is the selected item
                    $("option[value*='" + crs.model.RatePlanFilter + "']", rpDropdown).attr('selected', 'selected');

                    rpDropdown.change(function () {
                        crs.setRatePlanFilter($("option:selected", rpDropdown).attr('value'));
                        rpDropdown.blur();
                    });
                    $('#searchQuery .messages').append(ratePlanFilter);
                }

                if (roomCount > 0) {
                    $('#searchQuery .messages').append("<p>Your search returned " + roomCount + " lodging options. Browse the options by property or compare all options in the sections below.</p>");
                }

                $.each(data.ResponseMessages, function (i, responseMessage) {
                    if (responseMessage.MessageType > 0) {
                        $('#searchQuery .messages').append("<p class='error'>" + responseMessage.MessageText + "</p>");
                    }
                    else {
                        $('#searchQuery .messages').append("<p>" + responseMessage.MessageText + "</p>");
                    }
                });
            }
        });
    }

    function displayRateCalendar(roomRate) {
        //new DateRange object for calendar
        crs.initDateRange(crs.searchParameters.Arrival, crs.searchParameters.Departure);
        //GET DATE FROM MODEL
        var d = crs.searchParameters.Arrival.getDate();
        var m = crs.searchParameters.Arrival.getMonth();
        var y = crs.searchParameters.Arrival.getFullYear();
        $('#rateCalContainer .rateCalendar').fullCalendar({
            year: y,
            month: m,
            day: d,
            editable: false,
            header: {
                left: 'prev,next today',
                center: 'title',
                right: ''
            },
            events: $.fullCalendar.calendarData(crs.getUrl(), roomRate.RoomType.RoomTypeCode + '/' + roomRate.RatePlanCode),
            loading: function (isLoading, view) {
                if (isLoading) {
                    $.fancybox.showActivity();
                }
                else {
                    $.fancybox.hideActivity();
                }
            },
            dayClick: function (date, allDay, jsEvent, view) {
                //need to reference cal element with #cldr because it has been moved by lightwindow at this point
                var guestStay = $('#cldr').fullCalendar('clientEvents', 'crs.ArrivalDeparture');
                guestStay = guestStay[0];
                crs.model.RateCalendar.dateRange.updateDateRange(date);
                guestStay.start = crs.model.RateCalendar.dateRange.beginDate;
                guestStay.end = crs.model.RateCalendar.dateRange.endDate;
                $('#cldr').fullCalendar('updateEvent', guestStay);

                $('#btnChangeDate').removeAttr('disabled');
            },
            eventDrop: function (event, dayDelta, minuteDelta, allDay, revertFunc) {
                if (event.id == 'crs.ArrivalDeparture') {
                    $('#btnChangeDate').removeAttr('disabled');
                }
            },
            eventResize: function (event, dayDelta, minuteDelta, revertFunc) {
                if (event.id == 'crs.ArrivalDeparture') {
                    $('#btnChangeDate').removeAttr('disabled');
                }
            }
        });

        $.fancybox(
			$('#rateCalContainer .rateCalendar'),
			{
			    'autoDimensions': true,
			    'autoScale': true,
			    'centerOnScroll': true,
			    'scrolling': 'no',
			    onStart: function () {
			        $('#cldr').fullCalendar('render');
			        $('#cldr').prepend("<span class='calHeaderSupplament'>" + roomRate.RoomType.RoomTypeDescription + ", Nightly Rates</span");
			        $('#cldr').append("<div class='calFooterSupplament'><button class='btn' id='btnChangeDate' disabled='disabled'>Change Dates</button><button class='btn' id='btnCancel'>Cancel</button></div>");

			        //register button handlers
			        $('#btnChangeDate').click(function () {
			            crs.updateSearchParms(
						crs.model.RateCalendar.dateRange.beginDate,
						crs.model.RateCalendar.dateRange.endDate,
						crs.searchParameters.Adults,
						crs.searchParameters.Children);
			            $.fancybox.close();
			            availabilitySearch();
			        });

			        $('#btnCancel').click(function () {
			            $.fancybox.close();
			        });
			    },
			    onClosed: function () {
			        $('#rateCalContainer .rateCalendar').fullCalendar('destroy');
			        $('#cldr').empty();
			    }
			});
    }

    function fillDateFields() {
        var sParms = crs.searchParameters;
        $("#searchQuery .arrival").val(formatMonth(sParms.Arrival.getMonth()) + '/' + sParms.Arrival.getDate() + '/' + sParms.Arrival.getFullYear());
        $("#searchQuery .departure").val(formatMonth(sParms.Departure.getMonth()) + '/' + sParms.Departure.getDate() + '/' + sParms.Departure.getFullYear());
    }

    function formatMonth(mIndex) {
        //if (mIndex == 11) return 12;
        //else return mIndex + 1;
        //wtf??
        return mIndex + 1;
    }

    function getTabUrlFragment(path) {
        var tabNames = [];
        $('ul.tabs > li a').each(function (i, o) {
            tabNames.push($(o).attr('rel').substring(1));
        });
        var fragment = path.substring(1); //assume initial '/'
        var _tS = fragment.indexOf('/', 0); //look for fragment variables below l3 and strip them off
        if (_tS > -1) fragment = fragment.substring(0, _tS);
        if ($.inArray(fragment, tabNames) > -1) {
            return fragment;
        }
        else {
            return "";
        }
    }
});
