if (typeof Bricks == 'undefined') {
    var Bricks = {};
}

Bricks.module = function(name, moduleDefinition) {
    var names = name.split('.');
    var modulePart = Bricks;
    for (var i = 0, length = names.length; i < length; i += 1) {
        if (typeof modulePart[names[i]] == 'undefined') {
            if (i === (length - 1)) {
                modulePart[names[i]] = moduleDefinition(jQuery);
            } else {
                modulePart[names[i]] = {};
            }
        } else if (i === (length - 1)) {
            jQuery.extend(modulePart[names[i]], moduleDefinition(jQuery));
        }
        modulePart = modulePart[names[i]];
    }
};

Bricks.some = function(collection, predicate) {
    if (typeof Array.some === 'function') {
        return collection.some(predicate);
    }
    for (var i = 0, length = collection.length; i < length; i += 1) {
        var value = collection[i];
        if (predicate(value, i, collection)) {
            return true;
        }
    }
    return false;
};

Bricks.every = function(collection, predicate) {
    if (typeof Array.every === 'function') {
        return collection.every(predicate);
    }
    for (var i = 0, length = collection.length; i < length; i += 1) {
        var value = collection[i];
        if (!predicate(value, i, collection)) {
            return false;
        }
    }
    return true;
};

Bricks.map = function(collection, callback) {
    if (typeof Array.map === 'function') {
        return collection.map(callback);
    }
    var ret = [];
    for (var i = 0, length = collection.length; i < length; i += 1) {
        var value = collection[i];
        ret.push(callback(value, i, collection));
    }
    return ret;
};

Bricks.filter = function(collection, predicate) {
    if (typeof Array.filter === 'function') {
        return collection.filter(predicate);
    }
    var ret = [];
    for (var i = 0, length = collection.length; i < length; i += 1) {
        var value = collection[i];
        if (predicate(value, i, collection)) {
            ret.push(value);
        }
    }
    return ret;
};

Bricks.indexBy = function(collection, keySelector) {
    var index = {}, key = null;
    if (!jQuery.isFunction(keySelector)) {
        throw new TypeError();
    }
    for (var i = 0, length = collection.length; i < length; i += 1) {
        var value = collection[i];
        key = keySelector.call(null, value, i, collection);
        if (typeof index[key] === 'undefined') {
            index[key] = [];
        }
        index[key].push(value);
    }
    return index;
};

Bricks.uniqueIndexBy = function(collection, keySelector) {
    var index = {}, key = null;
    if (!jQuery.isFunction(keySelector)) {
        throw new TypeError();
    }
    for (var i = 0, length = collection.length; i < length; i += 1) {
        var value = collection[i];
        key = keySelector.call(null, value, i, collection);
        if (typeof index[key] === 'undefined') {
            index[key] = value;
        } else {
            throw new "Key '" + key + "' already present in unique index.";
        }
    }
    return index;
};

Bricks.forEach = function(collection, callback) {
    var thisObject = arguments[2] || null;
    if (!jQuery.isFunction(callback)) {
        throw new TypeError();
    }
    if (typeof Array.forEach === 'function') {
        return collection.forEach(callback, thisObject);
    }
    for (var i = 0, length = collection.length; i < length; i += 1) {
        var value = collection[i];
        callback.call(thisObject, value, i, collection);
    }
};

Bricks.find = function(collection, predicate) {
    if (!jQuery.isFunction(predicate)) {
        throw new TypeError();
    }
    for (var i = 0, length = collection.length; i < length; i += 1) {
        if (predicate(collection[i])) {
            return i;
        }
    }
    return -1;
};

/**
 * Based on getPageSize() by quirksmode.com
 *
 * @return Object Return an object with page width, height and window width, height
*/
Bricks.getPageSize = function() {
    var xScroll, yScroll;
    if (window.innerHeight && window.scrollMaxY) {	
        xScroll = window.innerWidth + window.scrollMaxX;
        yScroll = window.innerHeight + window.scrollMaxY;
    } else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac
        xScroll = document.body.scrollWidth;
        yScroll = document.body.scrollHeight;
    } else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
        xScroll = document.body.offsetWidth;
        yScroll = document.body.offsetHeight;
    }
    var windowWidth, windowHeight;
    if (self.innerHeight) {	// all except Explorer
        if (document.documentElement.clientWidth) {
            windowWidth = document.documentElement.clientWidth; 
        } else {
            windowWidth = self.innerWidth;
        }
        windowHeight = self.innerHeight;
    } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
        windowWidth = document.documentElement.clientWidth;
        windowHeight = document.documentElement.clientHeight;
    } else if (document.body) { // other Explorers
        windowWidth = document.body.clientWidth;
        windowHeight = document.body.clientHeight;
    }
    // for small pages with total height less then height of the viewport
    if (yScroll < windowHeight) {
        pageHeight = windowHeight;
    } else { 
        pageHeight = yScroll;
    }
    // for small pages with total width less then width of the viewport
    if (xScroll < windowWidth) {	
        pageWidth = xScroll;
    } else {
        pageWidth = windowWidth;
    }

    return {
        pageWidth: pageWidth, 
        pageHeight: pageHeight, 
        windowWidth: windowWidth, 
        windowHeight: windowHeight
    };
};
/**
  * Based on getPageScroll() by quirksmode.com
  *
  * @return Object Return an object with x,y page scroll values.
  */
Bricks.getPageScroll = function() {
    var xScroll, yScroll;
    if (self.pageYOffset) {
        yScroll = self.pageYOffset;
        xScroll = self.pageXOffset;
    } else if (document.documentElement && document.documentElement.scrollTop) {	 // Explorer 6 Strict
        yScroll = document.documentElement.scrollTop;
        xScroll = document.documentElement.scrollLeft;
    } else if (document.body) {// all other Explorers
        yScroll = document.body.scrollTop;
        xScroll = document.body.scrollLeft;
    }
    return {
        xScroll: xScroll,
        yScroll: yScroll
    };
};

Bricks.log = function(message) {
    if (window.console && window.console.log) {
        window.console.log(message);
    }
};

Bricks.toInt = function (value) {
    var defaultValue = (arguments.length == 2 ? arguments[1] : null);
    var intValue;
    if (jQuery.trim(value) === "0") return 0;
    if (/^[1-9][0-9]*$/.test(jQuery.trim(value))) {
        intValue = parseInt(jQuery.trim(value), 10);
        if (!isNaN(intValue)) {
            return intValue;
        }
    }
    return defaultValue;
};

Bricks.Keys = {
    LeftArrow: 37,
    UpArrow: 38,
    RightArrow: 39,
    DownArrow: 40,
    Return: 13,
    Escape: 27,
    Tab: 9,
    BackSpace: 8,
    Delete: 46
};

Bricks.module("Html", function ($) {

    var makeOptions = function (collection, options) {
        var html = '';
        var getValue = options.getValue || function (item) { return item; };
        var getText = options.getText || function (item) { return item; };
        var getCssClass = options.getCssClass || function (item, isSelected) { return ""; };
        var selectedValue = options.selectedValue || null;
        var defaultText = options.defaultText || null;
        var isSelected = false;
        var cssClass = '';
        Bricks.forEach(collection, function (item, index) {
            isSelected = getValue(item, index) === selectedValue;
            cssClass = getCssClass(item, isSelected);
            if (cssClass) {
                cssClass = ' class="' + cssClass + '"';
            }
            if (isSelected) {
                html += '<option value="' + getValue(item, index) + '" selected="selected"' + cssClass + '>' + getText(item, index) + '</option>';
            } else {
                html += '<option value="' + getValue(item, index) + '"' + cssClass + '>' + getText(item, index) + '</option>';
            }
        });
        if (defaultText) {
            html = '<option value="">' + defaultText + '</option>' + html;
        }
        return html;
    };

    var formatNumber = function (amount, roundToDecimal) {
        var numberPositivePatterns = [
            'n' // = 0
        ];
        var numberNegativePatterns = [
            '(n)',  // = 0
            '-n',   // = 1
            '- n',  // = 2
            'n-',   // = 3
            'n -'   // = 4
        ];
        var currencyPositivePatterns = [
            '$n',   // = 0
            'n$',   // = 1
            '$ n',  // = 2
            'n $'   // = 3
        ];
        var currencyNegativePatterns = [
            '($n)',     // = 0
            '-$n',      // = 1
            '$-n',      // = 2
            '$n-',      // = 3
            '(n$)',     // = 4
            '-n$',      // = 5
            'n-$',      // = 6
            'n$-',      // = 7
            '-n $',     // = 8
            '-$ n',     // = 9
            'n $-',     // = 10
            '$ n-',     // = 11
            '$ -n',     // = 12
            'n- $',     // = 13
            '($ n)',    // = 14
            '(n $)'     // = 15
        ];
        var options = { decimalSeparator: ',', groupSeparator: '.', currency: null, positivePattern: 0, negativePattern: 1 };
        var pattern;

        options = $.extend(options, arguments[2] || {});

        if (typeof amount !== 'number') {
            return amount;
        }

        if (amount < 0) {
            if (options.currency) {
                pattern = currencyNegativePatterns[options.negativePattern];
            } else {
                pattern = numberNegativePatterns[options.negativePattern];
            }
        } else {
            if (options.currency) {
                pattern = currencyPositivePatterns[options.positivePattern];
            } else {
                pattern = numberPositivePatterns[0];    // 0 is the only positive pattern
            }
        }

        amount = amount.toFixed(roundToDecimal);

        var nonDecimals = amount.toString().replace(/\.\d+$/, "");

        var decimals = "";
        for (var i = 0; i < roundToDecimal; i += 1) {
            decimals += "0";
        }

        if (amount.toString().indexOf('.') > -1) {
            decimals = amount.toString().replace(/^[^\.]+\./, "");
            for (var i = decimals.length; i < roundToDecimal; i += 1) {
                decimals += "0";
            }
        }

        decimals = decimals.substring(0, roundToDecimal);

        var formattedNumber = "";
        while (nonDecimals.length) {
            if (nonDecimals.length > 3) {
                formattedNumber = nonDecimals.substring(nonDecimals.length - 3) + formattedNumber;
                nonDecimals = nonDecimals.substring(0, nonDecimals.length - 3);
                if (nonDecimals === "-") {
                    formattedNumber = "-" + formattedNumber;
                    nonDecimals = "";
                } else if (nonDecimals.length) {
                    formattedNumber = options.groupSeparator + formattedNumber;
                }
            } else {
                formattedNumber = nonDecimals + formattedNumber;
                nonDecimals = "";
            }
        }
        formattedNumber = formattedNumber.replace(/^-/, '');

        if (options.currency) {
            return pattern.replace(/\$/, options.currency).replace(/n/, formattedNumber + options.decimalSeparator + decimals);
        }
        return pattern.replace(/n/, formattedNumber + options.decimalSeparator + decimals);
    };

    var makePrice = function (displayPrice) {
        var displayNormalPrice = arguments[1] || null;
        var showBeforePrice = arguments[2] || null;
        var bookingUrl = arguments[3] || null;

        var html = "";
        html += '<div class="bricks-lodging-price">';
        if (showBeforePrice) {
            html += '<div class="bricks-before-price">' + displayNormalPrice + '</div>';
        }
        if (bookingUrl) {
            html += '<div class="bricks-price"><a href="' + bookingUrl + '">' + displayPrice + '</a></div>';
        } else {
            html += '<div class="bricks-price">' + displayPrice + '</div>';
        }
        html += '</div>';
        return html;
    };

    var cssValue = function (value) {
        if (/^\d+px$/.test(value)) {
            return parseInt(value.replace(/px$/, ''), 10);
        }
        return 0;
    };

    var totalWidth = function (elem) {
        var width = elem.width();
        var widthModifiers = ['margin-left', 'border-left', 'padding-left', 'padding-right', 'border-right', 'margin-right'];
        Bricks.forEach(widthModifiers, function (widthModifier) {
            width += cssValue(elem.css(widthModifier));
        });
        return width;
    };

    var totalHeight = function (elem) {
        var height = elem.height();
        var heightModifiers = ['margin-top', 'border-top', 'padding-top', 'padding-bottom', 'border-bottom', 'margin-bottom'];
        Bricks.forEach(heightModifiers, function (heightModifier) {
            height += cssValue(elem.css(heightModifier));
        });
        return height;
    };

    var printInNewWindow = function (elem) {
        var options = arguments.length == 2 ? arguments[1] : {};
        var width = options.width || 750;
        var height = options.height || 400;
        var title = options.title || 'Print';
        var printWindow = window.open('', '_blank', 'width=' + width + ',height=' + height + ',scrollbars=yes,resizable=yes');

        if (options.doctype) {
            printWindow.document.writeln(options.doctype);
        }
        printWindow.document.writeln('<html>');
        printWindow.document.writeln('<head>');
        printWindow.document.writeln('<title>' + title + '</title>');
        if (options.stylesheetUrl) {
            printWindow.document.writeln('<link href="' + options.stylesheetUrl + '" type="text/css" rel="stylesheet" />');
        }
        if (options.styles) {
            printWindow.document.writeln('<style type="text/css">');
            printWindow.document.writeln(options.styles);
            printWindow.document.writeln('</style>');
        }
        printWindow.document.writeln('</head>');
        printWindow.document.writeln('<body>');
        if (options.containerId) {
            printWindow.document.writeln('<div id="' + options.containerId + '">');
        }
        printWindow.document.writeln($(elem).html());
        if (options.containerId) {
            printWindow.document.writeln('</div>');
        }
        printWindow.document.writeln('</body>');
        printWindow.document.writeln('</html>');
        printWindow.document.close();
        setTimeout(function () { printWindow.print(); }, 1000);
    };

    return {
        makePrice: makePrice,
        totalWidth: totalWidth,
        totalHeight: totalHeight,
        formatNumber: formatNumber,
        cssValue: cssValue,
        printInNewWindow: printInNewWindow,
        makeOptions: makeOptions
    };

});

Bricks.module("Dates", function($) {

    var Weekdays = { "Sunday": 0, "Monday": 1, "Tuesday": 2, "Wednesday": 3, "Thursday": 4, "Friday": 5, "Saturday": 6 };

    var days = function(days) {
        return days * 24 * 60 * 60 * 1000;
    };

    var weeks = function(weeks) {
        return weeks * days(7);
    }

    var weekdayName = function(date) {
        var names = ["sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"];
        return names[date.getDay()];
    };

    var firstDayInMonth = function(date) {
        return new Date(date.getFullYear(), date.getMonth(), 1);
    };

    var lastDayInMonth = function(date) {
        var nextMonth;

        if (date.getMonth() == 11) {
            nextMonth = new Date(date.getFullYear() + 1, 0, 1);
        } else {
            nextMonth = new Date(date.getFullYear(), date.getMonth() + 1, 1);
        }

        return new Date(nextMonth.getTime() - days(1));
    };

    var nextWeekday = function(weekday) {
        var options = arguments.length == 2 ? arguments[1] : {};
        var skipToday = typeof options.skipToday !== 'undefined' ? options.skipToday : false;
        var today = new Date();
        var date = new Date(today.getFullYear(), today.getMonth(), today.getDate());
        if (skipToday) {
            date = addDays(date, 1);
        }
        while (date.getDay() != weekday) {
            date = addDays(date, 1);
        }
        return date;
    };

    var addDays = function(date, daysCount) {
        return new Date(date.getTime() + days(daysCount));
    };

    var addMonths = function(date, monthCount) {
        var newDate = new Date(date.getTime());
        var direction = (monthCount < 0 ? -1 : 1);
        for (var i = 0; i < Math.abs(monthCount); i += 1) {
            if (direction === 1 && newDate.getMonth() === 11) {
                newDate = new Date(newDate.getFullYear() + 1, 0, 1);
            } else if (direction === -1 && newDate.getMonth() === 0) {
                newDate = new Date(newDate.getFullYear() - 1, 11, 1);
            } else {
                newDate = new Date(newDate.getFullYear(), newDate.getMonth() + direction, 1);
            }
        }
        var lastDay = lastDayInMonth(newDate);
        if (lastDay.getDate() < date.getDate()) {
            return lastDay;
        }
        return new Date(newDate.getFullYear(), newDate.getMonth(), date.getDate());
    };

    var diffDays = function(fromDate, toDate) {
        var diff = toDate.getTime() - fromDate.getTime();
        return Math.round(diff / days(1));
    };

    var zeroPad = function(number) {
        if (number < 10) {
            return "0" + number.toString();
        }
        return number.toString();
    };

    var toQueryStringDate = function(date) {
        return zeroPad(date.getMonth() + 1) + '/' + zeroPad(date.getDate()) + '/' + date.getFullYear();
    };

    var fromQueryStringDate = function(qsDate) {
        var parts = qsDate.split('/');
        if (parts.length === 3) {
            try {
                var month = parseInt(parts[0].replace(/^0/, ''), 10) - 1;
                var day = parseInt(parts[1].replace(/^0/, ''), 10);
                var year = parseInt(parts[2], 10);
                return new Date(year, month, day);
            } catch (ex) {
                // Pass
            }
        }
        return null;
    };

    var fromJsonDate = function(jsonDate) {
        if ((jsonDate == null) || (typeof (jsonDate.getFullYear) === 'function') || (typeof (jsonDate) !== 'string')) {
            return jsonDate;
        }
        return eval(jsonDate.replace(/^\/Date\((-?\d+)\)\/$/i, "new Date($1)"));
    };

    return {
        Weekdays: Weekdays,
        days: days,
        weeks: weeks,
        weekdayName: weekdayName,
        nextWeekday: nextWeekday,
        firstDayInMonth: firstDayInMonth,
        lastDayInMonth: lastDayInMonth,
        addDays: addDays,
        addMonths: addMonths,
        diffDays: diffDays,
        zeroPad: zeroPad,
        toQueryStringDate: toQueryStringDate,
        fromQueryStringDate: fromQueryStringDate,
        fromJsonDate: fromJsonDate
    };
});

Bricks.module("Items", function ($) {

    var create = function (availableItems, bookingTotalPrice, options) {
        var container = null;
        var currency = options.currency || "DKK";
        var decimalSeparator = options.decimalSeparator || ",";
        var groupSeparator = options.groupSeparator || ".";
        var positivePattern = typeof (options.positivePattern == 'number') ? options.positivePattern : 2;
        var negativePattern = typeof (options.negativePattern == 'number') ? options.negativePattern : 12;
        var selectedItems = arguments.length === 4 ? arguments[3] : [];

        var getItemId = function (elem) {
            var id = elem.attr('id');
            if (/^itemQuantity_\d+$/.test(id)) {
                return parseInt(id.replace(/^itemQuantity_/, ''), 10);
            }
            return null;
        };

        var getItem = function (itemId) {
            var items = Bricks.filter(availableItems, function (item) { return item.id === itemId });
            return items.length === 1 ? items[0] : null;
        };

        var setSelectedItem = function (item, quantity) {
            if (Bricks.every(selectedItems, function (selectedItem) { return selectedItem.id !== item.id; })) {
                selectedItems.push(item);
                selectedItems[selectedItems.length - 1].quantity = quantity;
            } else {
                for (var i = 0, length = selectedItems.length; i < length; i += 1) {
                    if (selectedItems[i].id === item.id) {
                        selectedItems[i].quantity = quantity;
                    }
                }
            }
        };

        var calculateTotal = function () {
            var totalPrice = bookingTotalPrice;
            Bricks.forEach(selectedItems, function (item) {
                totalPrice += item.unitSellPrice * item.quantity;
            });
            return totalPrice;
        };

        var calculateItemPrice = function (quantitySelector) {
            var tr = quantitySelector.closest('tr');
            try {
                var quantity = parseInt(quantitySelector.val(), 10);
                if (quantitySelector.is(':checkbox')) {
                    quantity = quantitySelector.attr('checked') ? quantitySelector.val() : 0;
                }
                var item = getItem(getItemId(quantitySelector));
                if (item) {
                    setSelectedItem(item, quantity);
                    var formatterOptions = {
                        decimalSeparator: decimalSeparator, 
                        groupSeparator: groupSeparator, 
                        positivePattern: positivePattern, 
                        negativePattern: negativePattern, 
                        currency: currency
                    };
                    $('.bricks-items-totalprice').html(Bricks.Html.formatNumber(calculateTotal(), 2, formatterOptions));
                    tr.find('.bricks-price-column').html(Bricks.Html.formatNumber(item.unitSellPrice * quantity, 2, formatterOptions));
                }
            } catch (ex) {
            }
        };

        var init = function (itemsContainer) {
            container = itemsContainer;
            container.find('.bricks-quantity-selector').live('change', function () { calculateItemPrice($(this)); }).each(function () { calculateItemPrice($(this)); });
        };

        return {
            init: init
        };
    };

    return {
        create: create
    };

});
Bricks.module("Search", function($) {

    var create = function(arrivalDateDayListId, arrivalDateMonthYearListId) {
        var container = null;

        var makeDayOptions = function(date, maxDay) {
            var html = '';
            for (var i = 1; i <= maxDay; i += 1) {
                html += '<option value="' + Bricks.Dates.zeroPad(date.getDate()) + '" class="' + Bricks.Dates.weekdayName(date) + '">' + date.getDate() + '</options>';
                date = new Date(date.getTime() + Bricks.Dates.days(1));
            }
            return html
        };

        var adjustDayList = function(monthYear) {
            var month = parseInt(monthYear.substr(0, 2).replace(/^0/, ''), 10);
            var year = parseInt(monthYear.substr(3), 10);
            var firstDayInMonth = new Date(year, month - 1, 1);
            var lastDayInMonth = Bricks.Dates.lastDayInMonth(firstDayInMonth);
            var selectedDay = $(container).find("#" + arrivalDateDayListId).val();
            $(container).find("#" + arrivalDateDayListId).html(makeDayOptions(firstDayInMonth, lastDayInMonth.getDate()));
            $(container).find("#" + arrivalDateDayListId).val(selectedDay);
        };

        var init = function(controlContainer, selectedDay, selectedMonthYear) {
            container = controlContainer;
            $(container).find('#' + arrivalDateMonthYearListId).val(selectedMonthYear);            
            adjustDayList(
                $(container).find("#" + arrivalDateMonthYearListId).change(function() {
                    adjustDayList($(this).val());
                }).val()
            );
            $(container).find("#" + arrivalDateDayListId).val(selectedDay);
        };

        return {
            init: init
        };
    };

    return {
        create: create
    };
});
Bricks.module("Lodging", function($) {

    var create = function(languageId) {

        var lodgingNames = null;
        var streetNames = null;

        var getLodgingNames = function(callback) {
            if (lodgingNames == null) {
                $.post('/BricksAjax.axd?controller=lodging&action=lodgingnames', { lan: languageId }, function(data) {
                    lodgingNames = data;
                    callback(lodgingNames);
                }, 'json');
            } else {
                callback(lodgingNames);
            }
        };

        var getStreetNames = function(callback) {
            if (streetNames == null) {
                $.post('/BricksAjax.axd?controller=lodging&action=streetnames', { lan: languageId }, function(data) {
                    streetNames = data;
                    callback(streetNames);
                }, 'json');
            } else {
                callback(streetNames);
            }
        };

        return {
            getLodgingNames: getLodgingNames,
            getStreetNames: getStreetNames
        };
    };

    return {
        create: create
    };
});
Bricks.module("Calendar", function ($) {

    var toInvariantDateString = function (date) {
        if (date) {
            return date.getFullYear() + '-' + Bricks.Dates.zeroPad(date.getMonth() + 1) + '-' + Bricks.Dates.zeroPad(date.getDate());
        }
        return null;
    };

    var create = function (searchContext, bookingOptions, options) {
        var container = null;
        if (typeof options.visible === 'undefined') options.visible = true;
        var errorPanel = typeof (options.errorPanel) == 'function' ? options.errorPanel : function () { };
        var loadingPanel = typeof (options.loadingPanel) == 'function' ? options.loadingPanel : function () { };
        var onUpdateCalendars = typeof (options.onUpdateCalendars) == 'function' ? options.onUpdateCalendars : function () { };
        var markSelected = !!options.markSelected;
        var selectedBookingOption = null;
        var selectedRange = {
            from: null,
            to: null
        };
        var eventHandlers = {};

        var fixDatesOnBookingOptions = function (bookingOptions) {
            // Convert .Net json dates to javascript dates
            return Bricks.map(bookingOptions, function (bookingOption) {
                bookingOption.arrivalDate = Bricks.Dates.fromJsonDate(bookingOption.arrivalDate);
                bookingOption.departureDate = Bricks.Dates.fromJsonDate(bookingOption.departureDate);
                bookingOption.dates = Bricks.map(bookingOption.dates, function (date) { return Bricks.Dates.fromJsonDate(date); });
                return bookingOption;
            });
        };

        bookingOptions = fixDatesOnBookingOptions(bookingOptions);

        var findBookingOption = function (arrivalDateStr) {
            var bookingOption = Bricks.filter(bookingOptions, function (bookingOption) { return (toInvariantDateString(bookingOption.arrivalDate) === arrivalDateStr); });
            if (bookingOption.length === 1) {
                return bookingOption[0];
            }
            return null;
        };

        var setSelectedRange = function (newSearchContext) {
            if (newSearchContext.arrivalDate && newSearchContext.duration) {
                selectedRange.from = newSearchContext.arrivalDate;
                selectedRange.to = Bricks.Dates.addDays(newSearchContext.arrivalDate, newSearchContext.duration - 1);
                selectedBookingOption = findBookingOption(toInvariantDateString(selectedRange.from));
            }
        };
        setSelectedRange(searchContext);

        var getDates = function (arrivalDateStr) {
            var bookingOption = findBookingOption(arrivalDateStr);
            if (bookingOption) {
                return Bricks.map(bookingOption.dates, function (date) { return toInvariantDateString(date); });
            }
            return [];
        };

        var bind = function (eventName, handler) {
            if (typeof (eventHandlers[eventName]) == 'undefined') {
                eventHandlers[eventName] = [];
            }
            eventHandlers[eventName].push(handler);
        };

        var unbind = function (eventName) {
            eventHandlers[eventName] = [];
        };

        var trigger = function (eventName) {
            var args = Array.prototype.slice.call(arguments);
            args.shift();
            if (eventHandlers[eventName]) {
                Bricks.forEach(eventHandlers[eventName], function (handler) {
                    if (typeof (handler) == 'function') {
                        handler.apply(null, args);
                    }
                });
            }
        };

        var updateCalendars = function (data) {
            loadingPanel('hide');
            errorPanel('hide');
            if (!data.error) {
                bookingOptions = fixDatesOnBookingOptions(data.bookingOptions);
                setSelectedRange(getSearchContext());
                container.find('.bricks-calendar-month').hide().remove();
                container.prepend(data.html);
                container.find('.bricks-calendar-month').fadeIn('fast');
                onUpdateCalendars();
                trigger('calendar:update', getSearchContextWithSelectedBookingOption());
            } else {
                errorPanel('show');
            }
        };

        var loadOptions = function () {
            return {
                months: options.monthsInCalendar,
                nextpageurl: options.nextPageUrl,
                visible: options.visible,
                weekdays: options.weekdays,
                optimize: options.optimize,
                markselected: markSelected,
                selfrom: toInvariantDateString(selectedRange.from),
                selto: toInvariantDateString(selectedRange.to)
            };
        };

        var getSelectedBookingOption = function () {
            return selectedBookingOption;
        };

        var forward = function (monthsToPage) {
            searchContext.arrivalDate = Bricks.Dates.addMonths(searchContext.arrivalDate, monthsToPage);
            loadingPanel('show');
            $.post('/BricksAjax.axd?controller=calendar&action=listmonths', $.extend(loadOptions(), searchContext.values()), function (data) {
                updateCalendars(data);
            }, 'json');
        };

        var back = function (monthsToPage) {
            searchContext.arrivalDate = Bricks.Dates.addMonths(searchContext.arrivalDate, -monthsToPage);
            loadingPanel('show');
            $.post('/BricksAjax.axd?controller=calendar&action=listmonths', $.extend(loadOptions(), searchContext.values()), function (data) {
                updateCalendars(data);
            }, 'json');
        };

        var update = function (newSearchContext) {
            searchContext = newSearchContext;
            setSelectedRange(searchContext);
            loadingPanel('show');
            $.post('/BricksAjax.axd?controller=calendar&action=listmonths', $.extend(loadOptions(), searchContext.values()), function (data) {
                updateCalendars(data);
            }, 'json');
        };

        var getSearchContext = function () {
            return searchContext.copy();
        };

        var getSearchContextWithSelectedBookingOption = function () {
            var options = arguments[0] || {};
            if (selectedRange.from && selectedBookingOption) {
                var newSearchContext = getSearchContext();
                if (!options.withLanguageId) {
                    newSearchContext.languageId = null;
                }
                newSearchContext.applyBookingOption(selectedBookingOption);
                return newSearchContext;
            }
            return getSearchContext();
        };

        var init = function (calendarContainer) {
            container = calendarContainer;
            var options = arguments[1] || {};
            var onShowBookingOption = options['onShowBookingOption'] || function () { };
            if (typeof onShowBookingOption !== 'function') onShowBookingOption = function () { };
            var onShowUnavailable = options['onShowUnavailable'] || function () { };
            if (typeof onShowUnavailable !== 'function') onShowUnavailable = function () { };
            var onShowNonChangeDay = options['onShowNonChangeDay'] || function () { };
            if (typeof onShowNonChangeDay !== 'function') onShowNonChangeDay = function() { };
            var onHideLayer = options['onHideLayer'] || function () { };
            if (typeof onHideLayer !== 'function') onHideLayer = function () { };
            var onBookingOptionClick = options['onBookingOptionClick'] || function () { };
            if (typeof onBookingOptionClick !== 'function') onBookingOptionClick = function () { };

            // Free days
            container.find('.bricks-calendar-free').live('mouseover', function (event) {
                var date = $(this).attr('data-date');
                var bookingOption = findBookingOption(date);
                if (bookingOption) {
                    onShowBookingOption($(this), bookingOption);
                } else {
                    onShowNonChangeDay($(this));
                }
                var datesToSelect = getDates(date);
                for (var i = 0, length = datesToSelect.length; i < length; i += 1) {
                    container.find('.bricks-calendar-free[data-date=' + datesToSelect[i] + '], .bricks-calendar-changeday[data-date=' + datesToSelect[i] + ']').addClass('bricks-calendar-selected');
                }
            }).live('mouseout', function (event) {
                container.find('.bricks-calendar-selected').removeClass('bricks-calendar-selected');
                onHideLayer();
            });

            // Change days
            container.find('.bricks-calendar-changeday, .bricks-calendar-option').live('mouseover', function (event) {
                var date = $(this).attr('data-date');
                var bookingOption = findBookingOption(date);
                if (bookingOption) {
                    onShowBookingOption($(this), bookingOption);
                } else {
                    onShowUnavailable($(this));
                }
                var datesToSelect = getDates(date);
                for (var i = 0, length = datesToSelect.length; i < length; i += 1) {
                    container.find('.bricks-calendar-free[data-date=' + datesToSelect[i] + '], .bricks-calendar-changeday[data-date=' + datesToSelect[i] + ']').addClass('bricks-calendar-selected');
                }
            }).live('mouseout', function (event) {
                container.find('.bricks-calendar-selected').removeClass('bricks-calendar-selected');
                onHideLayer();
            });

            container.find('.bricks-calendar-free, .bricks-calendar-changeday, .bricks-calendar-option').live('click', function (event) {
                var date = $(this).attr('data-date');
                var bookingOption = findBookingOption(date);
                if (bookingOption) {
                    if (onBookingOptionClick(event, $(this), bookingOption)) {
                        container.find('.bricks-calendar-selected').removeClass('bricks-calendar-selected');
                        window.location.href = bookingOption.bookingUrl;
                    }
                }
            });
        };

        return {
            init: init,
            forward: forward,
            back: back,
            update: update,
            bind: bind,
            unbind: unbind,
            getSearchContext: getSearchContext,
            getSearchContextWithSelectedBookingOption: getSearchContextWithSelectedBookingOption,
            getSelectedBookingOption: getSelectedBookingOption
        };
    };

    return {
        create: create
    };
});
Bricks.module("Navigator", function($) {

    var getUserLanguages = function(callback) {
        $.post('/BricksAjax.axd?controller=browserheader&action=listlanguages', {}, function(languages) {
            callback(Bricks.map(languages, function(language) {
                var separatorIndex = language.indexOf(';');
                if (separatorIndex > -1) {
                    return language.substring(0, separatorIndex).toLowerCase();
                }
                return language.toLowerCase();
            }));
        }, 'json');
    };

    var createCookie = function(name, value, days) {
        if (days) {
            var date = new Date();
            date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
            var expires = "; expires=" + date.toGMTString();
        }
        else var expires = "";
        document.cookie = name + "=" + value + expires + "; path=/";
    }

    var readCookie = function(name) {
        var nameEQ = name + "=";
        var ca = document.cookie.split(';');
        for (var i = 0; i < ca.length; i++) {
            var c = ca[i];
            while (c.charAt(0) == ' ') c = c.substring(1, c.length);
            if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
        }
        return null;
    }

    var eraseCookie = function(name) {
        createCookie(name, "", -1);
    }

    return {
        getUserLanguages: getUserLanguages,
        createCookie: createCookie,
        readCookie: readCookie,
        eraseCookie: eraseCookie
    };
});
Bricks.module("SearchBox", function ($) {

    function SearchBoxData() {
        var self = this;

        this.countries = function () {
            var result = [];
            Bricks.forEach(self.locations, function (location) {
                if (location.level == 0) {
                    result.push(location);
                }
            });
            return result;
        };
    }

    var create = function (languageId) {

        var getData = function (callback) {
            $.post('/BricksAjax.axd?controller=searchbox&action=getdata', { lan: languageId }, function (data) {
                if ($.isArray(data.facilities) && $.isArray(data.locations)) {
                    var searchBoxData = new SearchBoxData();
                    callback($.extend(searchBoxData, data));
                }
            }, 'json');
        };

        var count = function (searchContext, options, callback) {
            $.post('/BricksAjax.axd?controller=searchbox&action=count', $.extend({ lan: languageId }, options, searchContext.values()), function (data) {
                if (data.status == 'success') {
                    callback(data.count);
                }
            }, 'json');
        };

        return {
            getData: getData,
            count: count
        };
    };

    return {
        create: create
    };
});
Bricks.module("Validation", function ($) {

    var error = function (elem, errorMessage) {
        return { elem: elem, message: errorMessage };
    };

    var required = function (elem, errorMessage) {
        var dependent = (arguments.length == 3) ? arguments[2] : function () { return null; };
        if (elem.attr('data-default-text')) {
            if (Bricks.DefaultText.val(elem) !== '') {
                return dependent();
            } else {
                return { elem: elem, message: errorMessage };
            }
        }
        return (elem.val() != '') ? dependent() : { elem: elem, message: errorMessage };
    };

    var numeric = function (elem, errorMessage) {
        var dependent = (arguments.length == 3) ? arguments[2] : function () { return null; };
        var pattern = /^ *[1-9][0-9]* *$/;
        var value;
        if (pattern.test(elem.val())) {
            value = parseInt($.trim(elem.val()), 10);
            return (!isNaN(value)) ? dependent() : { elem: elem, message: errorMessage };
        }
        return { elem: elem, message: errorMessage };
    };

    var range = function (elem, minValue, maxValue, errorMessage) {
        var dependent = (arguments.length == 5) ? arguments[4] : function () { return null; };
        var value = parseInt($.trim(elem.val()), 10);
        if (!isNaN(value)) {
            return (minValue <= value && value <= maxValue) ? dependent() : { elem: elem, message: errorMessage };
        }
        return { elem: elem, message: errorMessage };
    };

    var checked = function (elem, errorMessage) {
        var dependent = (arguments.length == 3) ? arguments[2] : function () { return null; };
        if (elem.attr('checked')) {
            return dependent();
        }
        return { elem: elem, message: errorMessage };
    };

    var same = function (elemA, elemB, errorMessage) {
        var dependent = (arguments.length == 4) ? arguments[3] : function () { return null; };
        if (elemA.val() === elemB.val()) {
            return dependent();
        }
        return { elem: elemA, message: errorMessage };
    };

    var email = function (elem, errorMessage) {
        var dependent = (arguments.length == 3) ? arguments[2] : function () { return null; };
        var isEmail = /^[^@]+@\w+([-.]\w+)*\.\w+([-.]\w+)*$/i;
        if (isEmail.test(elem.val())) {
            return dependent();
        }
        return { elem: elem, message: errorMessage };
    };

    var clearErrorMarkers = function () {
        $('.bricks-error-marker').remove();
    };

    var addErrorMarker = function (elem, errorMarker) {
        if (!elem.next().hasClass('bricks-error-marker')) {
            elem.after('<span class="bricks-error-marker">' + errorMarker + '</span>');
        }
    };

    var removeErrorMarker = function (elem) {
        if (elem.next().hasClass('bricks-error-marker')) {
            elem.next().remove();
        }
    };

    return {
        error: error,
        required: required,
        numeric: numeric,
        range: range,
        checked: checked,
        email: email,
        same: same,
        clearErrorMarkers: clearErrorMarkers,
        addErrorMarker: addErrorMarker,
        removeErrorMarker: removeErrorMarker
    };

});
Bricks.module("LodgingList", function($) {

    var create = function() {

        var init = function(container, options) {
            if (arguments.length == 1) {
                options = {};
            }
            var applyBackgroundColors = typeof (options.applyBackgroundColors) === 'boolean' ? options.applyBackgroundColors : true;
            var applyBorderColors = typeof (options.applyBorderColors) === 'boolean' ? options.applyBorderColors : true;

            $(container).find('.bricks-lodging-listitem a').click(function(event) {
                event.stopImmediatePropagation();
            });

            $(container).find('.bricks-lodging-listitem').click(function(event) {
                event.preventDefault();
                var url = $(this).attr('data-url');
                window.location.href = url;
                return false;
            }).mouseover(function(event) {
                $(this).addClass('bricks-mouseover');
            }).mouseout(function(event) {
                $(this).removeClass('bricks-mouseover');
            });

            if (applyBackgroundColors || applyBorderColors) {
                $(container).find('.bricks-seasonprice-colorbox').each(function() {
                    if (applyBackgroundColors) {
                        jQuery(this).css('backgroundColor', jQuery(this).attr('data-color'));
                    }
                    if (applyBorderColors) {
                        jQuery(this).css('borderColor', jQuery(this).attr('data-color'));
                    }
                });
            }
        };

        return {
            init: init
        };
    };

    return {
        create: create
    };
});
Bricks.module("ViewLodging", function($) {

    var create = function() {
        var preloadedImages = false;

        var makeLargeImageHtml = function(thumbnail) {
            return '<img src="' + thumbnail.attr('data-large-image-url') + '" alt="' + thumbnail.attr('alt') + '" title="' + thumbnail.attr('title') + '" />';
        };

        var preloadImages = function(container) {
            preloadedImages = [];
            container.find('.bricks-lodging-image-thumbnails img').each(function() {
                var image = new Image();
                image.src = $(this).attr('data-large-image-url');
                preloadedImages.push(image);
            });
        };

        var init = function(container) {
            var largeImageContainer = container.find(".bricks-lodging-default-image");
            container.find(".bricks-lodging-image-thumbnails img").mouseover(function(event) {
                largeImageContainer.html(makeLargeImageHtml($(this)));
            });

            if (preloadedImages === false) {
                preloadImages(container);
            }

            container.find(".bricks-lodging-more-thumbnail-images a").click(function(event) {
                event.preventDefault();
                $(this).blur();
                var showText = $(this).attr('data-show-text');
                var hideText = $(this).attr('data-hide-text');
                if (container.find(".bricks-extra-thumbnails").is(":visible")) {
                    container.find(".bricks-extra-thumbnails").fadeOut('fast');
                    $(this).addClass("bricks-expand-extra-thumbnails").removeClass("bricks-collapse-extra-thumbnails").html(showText);
                } else {
                    container.find(".bricks-extra-thumbnails").fadeIn('fast');
                    $(this).addClass("bricks-collapse-extra-thumbnails").removeClass("bricks-expand-extra-thumbnails").html(hideText);
                }
                return false;
            });
        };

        return {
            init: init
        };
    };

    return {
        create: create
    };
});
Bricks.module("LodgingImages", function($) {

    var create = function() {
        var preloadedImages = false;

        var makeLargeImageHtml = function(thumbnail) {
            var html = '';
            if (thumbnail.attr('data-gallery-image-url')) {
                html += '<a href="' + thumbnail.attr('data-gallery-image-url') + '" class="bricks-gallery-image-link">';
            }
            html += '<img src="' + thumbnail.attr('data-large-image-url') + '" alt="' + thumbnail.attr('alt') + '" title="' + thumbnail.attr('title') + '" />';
            if (thumbnail.attr('data-gallery-image-url')) {
                html += '</a>';
            }
            return html;
        };

        var preloadImages = function(container) {
            preloadedImages = [];
            container.find('.bricks-lodging-image-thumbnails img').each(function() {
                var image = new Image();
                image.src = $(this).attr('data-large-image-url');
                preloadedImages.push(image);
            });
        };

        var init = function(container) {
            var largeImageContainer = container.find(".bricks-lodging-default-image");
            container.find(".bricks-lodging-image-thumbnails img").mouseover(function(event) {
                largeImageContainer.html(makeLargeImageHtml($(this)));
            });

            if (preloadedImages === false) {
                preloadImages(container);
            }

            container.find(".bricks-lodging-more-thumbnail-images a").click(function(event) {
                event.preventDefault();
                $(this).blur();
                var showText = $(this).attr('data-show-text');
                var hideText = $(this).attr('data-hide-text');
                if (container.find(".bricks-extra-thumbnails").is(":visible")) {
                    container.find(".bricks-extra-thumbnails").fadeOut('fast');
                    $(this).addClass("bricks-expand-extra-thumbnails").removeClass("bricks-collapse-extra-thumbnails").html(showText);
                } else {
                    container.find(".bricks-extra-thumbnails").fadeIn('fast');
                    $(this).addClass("bricks-collapse-extra-thumbnails").removeClass("bricks-expand-extra-thumbnails").html(hideText);
                }
                return false;
            });
        };

        return {
            init: init
        };
    };

    var setupGallery = function(container, autoRewind, options) {

        container.find('.bricks-gallery-image-link').live('click', function(event) {
            event.preventDefault();
            event.stopPropagation();
            var url = $(this).attr('href');
            if (autoRewind) {
                container.find('.bricks-lodging-gallery-images a').filter(':first').click();
            } else {
                container.find('.bricks-lodging-gallery-images a').each(function() {
                    if ($(this).attr('href') == url) {
                        $(this).click();
                    }
                });
            }
        });

        container.find('.bricks-lodging-gallery-images a').lightBox(options);
    };

    return {
        create: create,
        setupGallery: setupGallery
    };
});
Bricks.module("SearchContext", function ($) {

    var ensureArray = function (parameters, name) {
        if (typeof parameters[name] !== 'undefined') {
            if ($.isArray(parameters[name])) {
                return parameters[name];
            } else {
                return [parameters[name]];
            }
        }
        return [];
    };

    var tokenize = function (querystring) {
        var tokens = {};
        if (!querystring) return tokens;
        var parts = querystring.split(/&/);
        Bricks.forEach(parts, function (part) {
            var separatorIndex = part.indexOf('=');
            if (separatorIndex > -1) {
                tokens[part.substring(0, separatorIndex)] = part.substring(separatorIndex + 1);
            } else {
                tokens[part] = null;
            }
        });
        return tokens;
    };

    var valuesToQueryString = function (values) {
        var parts = [];
        var withQuestionMark = arguments[1] || false;
        for (var name in values) {
            if (values.hasOwnProperty(name)) {
                parts.push(name + '=' + encodeURIComponent(values[name]));
            }
        }
        if (withQuestionMark) {
            return '?' + parts.join('&');
        }
        return parts.join('&');
    };

    var valuesFromQueryString = function (querystring) {
        if (querystring.indexOf('?') === 0) querystring = querystring.substring(1);
        var tokens = tokenize(querystring);
        var parameters = {};
        var facilityId, value, greaterThanEqual;
        var numbers;
        var room;
        for (var name in tokens) {
            if (tokens.hasOwnProperty(name)) {
                try {
                    if (name === 'dat') {
                        parameters[name] = Bricks.Dates.fromQueryStringDate(decodeURIComponent(tokens[name]));
                    }
                    if (Bricks.some(['dur', 'adu', 'chi', 'inf', 'pet', 'lty', 'lod', 'lut', 'bty', 'rms', 'loc', 'min', 'max', 'pge', 'pgs', 'rnd', 'rng', 'submin', 'submax'], function (n) { return n === name; })) {
                        parameters[name] = parseInt(tokens[name], 10);
                    }
                    if (Bricks.some(['sts', 'subloc', 'substs'], function (n) { return n === name; })) {
                        numbers = [];
                        Bricks.forEach(tokens[name].split(/,/), function (part, i) {
                            if (/^[1-9][0-9]*$/.test(part)) {
                                numbers.push(parseInt(part, 10));
                            }
                        });
                        parameters[name] = numbers;
                    }
                    if (name === 'rmx') {
                        parameters[name] = [];
                        Bricks.forEach(decodeURIComponent(tokens[name]).split(/,/), function (part) {
                            var subParts = Bricks.map(part.split(/;/), function (p) { return Bricks.toInt(p); });
                            if (subParts.length === 6) {
                                room = {
                                    lodgingUnitTypeId: subParts[0],
                                    boardTypeId: subParts[1],
                                    adults: subParts[2],
                                    children: subParts[3],
                                    infants: subParts[4],
                                    pets: subParts[5]
                                };
                                parameters[name].push(room);
                            }
                        });
                        if (parameters['rms'] && parameters['rms'] < parameters['rmx'].length) {
                            parameters['rms'] = parameters['rmx'].length;
                        }
                    }
                    if (Bricks.some(['ord', 'cur', 'tag', 'stn'], function (n) { return n === name; })) {
                        parameters[name] = tokens[name];
                    }
                    if (name.indexOf('fac') === 0) {
                        facilityId = parseInt(name.replace(/^fac/, ""), 10);
                        value = tokens[name];
                        greaterThanEqual = false;
                        if (typeof parameters["fac"] === 'undefined') {
                            parameters["fac"] = [];
                        }
                        if (/^[0-9]+[pP]$/.test(value)) {
                            value = value.substring(0, value.length - 1);
                            greaterThanEqual = true;
                        }
                        parameters["fac"].push({ facilityId: facilityId, value: value, greaterThanEqual: greaterThanEqual });
                    }
                    if (name.indexOf('subfac') === 0) {
                        facilityId = parseInt(name.replace(/^subfac/, ""), 10);
                        value = tokens[name];
                        greaterThanEqual = false;
                        if (typeof parameters["subfac"] === 'undefined') {
                            parameters['subfac'] = [];
                        }
                        if (/^[0-9]+[pP]$/.test(value)) {
                            value = value.substring(0, value.length - 1);
                            greaterThanEqual = true;
                        }
                        parameters['subfac'].push({ facilityId: facilityId, value: value, greaterThanEqual: greaterThanEqual });
                    }
                } catch (ex) {
                    // Pass
                }
            }
        }
        return parameters;
    };

    var create = function (parameters) {
        return new SearchContext(parameters);
    };

    var createFromQueryString = function () {
        var querystring = arguments[0] || window.location.search;
        return new SearchContext(valuesFromQueryString(querystring));
    };

    var createFromForm = function (container) {
        var parameters = {};
        parameters["dat"] = getFormMonthYear(container.find('.bricks-select-monthyear'));
        if (getFormInteger(container.find('.bricks-select-duration')) !== null) {
            parameters["dur"] = getFormInteger(container.find('.bricks-select-duration'));
        }
        if (getFormInteger(container.find('.bricks-select-adults')) !== null) {
            parameters["adu"] = getFormInteger(container.find('.bricks-select-adults'));
        }
        if (getFormInteger(container.find('.bricks-select-children')) !== null) {
            parameters["chi"] = getFormInteger(container.find('.bricks-select-children'));
        }
        if (getFormInteger(container.find('.bricks-select-infants')) !== null) {
            parameters["inf"] = getFormInteger(container.find('.bricks-select-infants'));
        }
        if (getFormInteger(container.find('.bricks-select-pets')) !== null) {
            parameters["pet"] = getFormInteger(container.find('.bricks-select-pets'));
        }
        return new SearchContext(parameters);
    };

    var getFormInteger = function (elem) {
        var value = elem.val();
        if ($.trim(value) === "") return null;
        try {
            return parseInt(value, 10);
        } catch (ex) {
            return null;
        }
    };

    var getFormMonthYear = function (elem) {
        var month = parseInt(elem.val().substr(0, 2).replace(/^0/, ''), 10);
        var year = parseInt(elem.val().substr(3), 10);
        return new Date(year, month, 1);
    };

    function SearchContext(parameters) {
        var that = this;

        this.languageId = (typeof parameters['lan'] !== 'undefined') ? parameters['lan'] : null;
        this.arrivalDate = Bricks.Dates.fromJsonDate(parameters['dat']) || null;
        this.duration = (typeof parameters['dur'] !== 'undefined') ? parameters['dur'] : null;
        this.adults = (typeof parameters['adu'] !== 'undefined') ? parameters['adu'] : null;
        this.children = (typeof parameters['chi'] !== 'undefined') ? parameters['chi'] : null;
        this.infants = (typeof parameters['inf'] !== 'undefined') ? parameters['inf'] : null;
        this.pets = (typeof parameters['pet'] !== 'undefined') ? parameters['pet'] : null;
        this.locationId = (typeof parameters['loc'] !== 'undefined') ? parameters['loc'] : null;
        this.lodgingTypeId = (typeof parameters['lty'] !== 'undefined') ? parameters['lty'] : null;
        this.lodgingId = (typeof parameters['lod'] !== 'undefined') ? parameters['lod'] : null;
        this.lodgingUnitTypeId = (typeof parameters['lut'] !== 'undefined') ? parameters['lut'] : null;
        this.boardTypeId = (typeof parameters['bty'] !== 'undefined') ? parameters['bty'] : null;
        this.currencyCode = (typeof parameters['cur'] !== 'undefined') ? parameters['cur'] : null;
        this.minPrice = (typeof parameters['min'] !== 'undefined') ? parameters['min'] : null;
        this.maxPrice = (typeof parameters['max'] !== 'undefined') ? parameters['max'] : null;
        this.stars = ensureArray(parameters, 'sts');
        this.facilities = ensureArray(parameters, 'fac');
        this.rooms = (typeof parameters['rms'] !== 'undefined') ? parameters['rms'] : null;
        this.roomMatrix = ensureArray(parameters, 'rmx');
        if (this.rooms && this.rooms < this.roomMatrix.length) {
            this.rooms = this.roomMatrix.length;
        }
        this.orderBy = (typeof parameters['ord'] !== 'undefined') ? parameters['ord'] : null;
        this.page = (typeof parameters['pge'] !== 'undefined') ? parameters['pge'] : null;
        this.pageSize = (typeof parameters['pgs'] !== 'undefined') ? parameters['pgs'] : null;
        this.randomSeed = (typeof parameters['rnd'] !== 'undefined') ? parameters['rnd'] : null;
        this.tag = (typeof parameters['tag'] !== 'undefined') ? parameters['tag'] : null;
        this.searchRangeInDays = (typeof parameters['rng'] !== 'undefined') ? parameters['rng'] : null;
        this.streetName = (typeof parameters['stn'] !== 'undefined') ? parameters['stn'] : null;

        this.sub = {
            locationIds: ensureArray(parameters, 'subloc'),
            stars: ensureArray(parameters, 'substs'),
            facilities: ensureArray(parameters, 'subfac'),
            minPrice: (typeof parameters['submin'] !== 'undefined') ? parameters['submin'] : null,
            maxPrice: (typeof parameters['submax'] !== 'undefined') ? parameters['submax'] : null
        };

        this.departureDate = function () {
            if (that.arrivalDate && that.duration) {
                return Bricks.Dates.addDays(that.arrivalDate, that.duration);
            }
            return null;
        };

        this.facilityValueDate = function () {
            return (that.arrivalDate || new Date());
        };

        this.values = function () {
            var values = {};
            if (that.languageId !== null) values['lan'] = that.languageId;
            if (that.arrivalDate !== null) values['dat'] = Bricks.Dates.toQueryStringDate(that.arrivalDate);
            if (that.duration !== null) values['dur'] = that.duration;
            if (that.adults !== null) values['adu'] = that.adults;
            if (that.children !== null) values['chi'] = that.children;
            if (that.infants !== null) values['inf'] = that.infants;
            if (that.pets !== null) values['pet'] = that.pets;
            if (that.locationId !== null) values['loc'] = that.locationId;
            if (that.lodgingTypeId !== null) values['lty'] = that.lodgingTypeId;
            if (that.lodgingId !== null) values['lod'] = that.lodgingId;
            if (that.lodgingUnitTypeId !== null) values['lut'] = that.lodgingUnitTypeId;
            if (that.boardTypeId !== null) values['bty'] = that.boardTypeId;
            if (that.currencyCode !== null) values['cur'] = that.currencyCode;
            if (that.stars.length) values['sts'] = that.stars.join(",");
            if (that.rooms !== null) values['rms'] = that.rooms;
            if (that.roomMatrix.length) {
                var rmx = [];
                Bricks.forEach(that.roomMatrix, function (room) {
                    rmx.push(room.lodgingUnitTypeId + ";" + room.boardTypeId + ";" + room.adults + ";" + room.children + ";" + room.infants + ";" + room.pets);
                });
                values['rmx'] = rmx.join(",")
            }
            if (that.orderBy !== null) values['ord'] = that.orderBy;
            if (that.page !== null) values['pge'] = that.page;
            if (that.pageSize !== null) values['pgs'] = that.pageSize;
            if (that.randomSeed !== null) values['rnd'] = that.randomSeed;
            if (that.tag !== null) values['tag'] = that.tag;
            if (that.searchRangeInDays !== null) values['rng'] = that.searchRangeInDays;
            if (that.streetName !== null) values['stn'] = that.streetName;

            Bricks.forEach(that.facilities, function (facilityValue) {
                if (facilityValue.value === true) {
                    values["fac" + facilityValue.facilityId.toString()] = 1;
                } else if (facilityValue.value === false) {
                    values["fac" + facilityValue.facilityId.toString()] = 0;
                } else {
                    if (facilityValue.greaterThanEqual) {
                        values["fac" + facilityValue.facilityId.toString()] = facilityValue.value + "p";
                    } else {
                        values["fac" + facilityValue.facilityId.toString()] = facilityValue.value;
                    }
                }
            });
            if (that.minPrice !== null) values['min'] = that.minPrice;
            if (that.maxPrice !== null) values['max'] = that.maxPrice;
            if (that.sub.locationIds.length) values['subloc'] = that.sub.locationIds.join(',');
            if (that.sub.stars.length) values['substs'] = that.sub.stars.join(',');
            Bricks.forEach(that.sub.facilities, function (facilityValue) {
                if (facilityValue.value === true) {
                    values['subfac' + facilityValue.facilityId.toString()] = 1;
                } else if (facilityValue.value === false) {
                    values['subfac' + facilityValue.facilityId.toString()] = 0;
                } else {
                    if (facilityValue.greaterThanEqual) {
                        values['subfac' + facilityValue.facilityId.toString()] = facilityValue.value + "p";
                    } else {
                        values['subfac' + facilityValue.facilityId.toString()] = facilityValue.value;
                    }
                }
            });
            if (that.sub.minPrice !== null) values['submin'] = that.sub.minPrice;
            if (that.sub.maxPrice !== null) values['submax'] = that.sub.maxPrice;
            return values;
        };

        this.toQueryString = function () {
            var withQuestionMark = arguments.length == 1 ? arguments[0] : false;
            return valuesToQueryString(that.values(), withQuestionMark);
        };

        this.copy = function () {
            var newSearchContext = new SearchContext(parameters);
            newSearchContext.languageId = that.languageId;
            newSearchContext.arrivalDate = that.arrivalDate;
            newSearchContext.duration = that.duration;
            newSearchContext.adults = that.adults;
            newSearchContext.children = that.children;
            newSearchContext.infants = that.infants;
            newSearchContext.pets = that.pets;
            newSearchContext.locationIds = that.locationIds;
            newSearchContext.lodgingId = that.lodgingId;
            newSearchContext.lodgingTypeId = that.lodgingTypeId;
            newSearchContext.lodgingUnitTypeId = that.lodgingUnitTypeId;
            newSearchContext.boardTypeId = that.boardTypeId;
            newSearchContext.currencyCode = that.currencyCode;
            newSearchContext.stars = [];
            newSearchContext.stars.concat(that.stars);
            newSearchContext.rooms = that.rooms;
            newSearchContext.roomMatrix = [];
            newSearchContext.roomMatrix.concat(that.roomMatrix);
            newSearchContext.orderBy = that.orderBy;
            newSearchContext.page = that.page;
            newSearchContext.pageSize = that.pageSize;
            newSearchContext.randomSeed = that.randomSeed;
            newSearchContext.tag = that.tag;
            newSearchContext.searchRangeInDays = that.searchRangeInDays;
            newSearchContext.streetName = that.streetName;
            newSearchContext.facilities = [];
            newSearchContext.facilities.concat(that.facilities);
            newSearchContext.minPrice = that.minPrice;
            newSearchContext.maxPrice = that.maxPrice;
            newSearchContext.sub.locationIds = [];
            newSearchContext.sub.locationIds.concat(that.sub.locationIds);
            newSearchContext.sub.stars = [];
            newSearchContext.sub.stars.concat(that.sub.stars);
            newSearchContext.sub.facilities = [];
            newSearchContext.sub.facilities.concat(that.sub.facilities);
            newSearchContext.sub.minPrice = that.sub.minPrice;
            newSearchContext.sub.maxPrice = that.sub.maxPrice;
            return newSearchContext;
        };

        this.applyBookingOption = function (bookingOption) {
            that.arrivalDate = bookingOption.arrivalDate;
            that.duration = bookingOption.duration;
            that.adults = bookingOption.adults;
            that.children = bookingOption.children;
            that.boardTypeId = bookingOption.boardTypeId;
            that.lodgingUnitTypeId = bookingOption.lodgingUnitTypeId;
        };

        this.isEqualTo = function (other) {
            var i, l, otherIndex;
            if (!other) return false;
            if (that.arrivalDate && !other.arrivalDate) return false;
            if (!that.arrivalDate && other.arrivalDate) return false;
            if (that.arrivalDate && other.arrivalDate && that.arrivalDate.valueOf() !== other.arrivalDate.valueOf()) return false;
            if (that.duration !== other.duration) return false;
            if (that.locationId !== other.locationId) return false;
            if (that.lodgingId !== other.lodgingId) return false;
            if (that.lodgingTypeId !== other.lodgingTypeId) return false;
            if (that.lodgingUnitTypeId !== other.lodgingUnitTypeId) return false;
            if (that.boardTypeId !== other.boardTypeId) return false;
            if (that.adults !== other.adults) return false;
            if (that.children !== other.children) return false;
            if (that.infants !== other.infants) return false;
            if (that.pets !== other.pets) return false;
            if (that.rooms !== other.rooms) return false;
            if (that.roomMatrix.length === other.roomMatrix.length) {
                for (i = 0, l = that.roomMatrix.length; i < l; i++) {
                    if (that.roomMatrix[i].lodgingUnitTypeId !== other.roomMatrix[i].lodgingUnitTypeId) return false;
                    if (that.roomMatrix[i].boardTypeId !== other.roomMatrix[i].boardTypeId) return false;
                    if (that.roomMatrix[i].adults !== other.roomMatrix[i].adults) return false;
                    if (that.roomMatrix[i].children !== other.roomMatrix[i].children) return false;
                    if (that.roomMatrix[i].infants !== other.roomMatrix[i].infants) return false;
                    if (that.roomMatrix[i].pets !== other.roomMatrix[i].pets) return false;
                }
            } else {
                return false;
            }
            if (that.minPrice !== other.minPrice) return false;
            if (that.maxPrice !== other.maxPrice) return false;
            if (that.searchRangeInDays !== other.searchRangeInDays) return false;
            if (that.tag !== other.tag) return false;
            if (that.stars.length === other.stars.length) {
                for (i = 0, l = that.stars.length; i < l; i++) {
                    otherIndex = Bricks.find(other.stars, function (star) { return star === that.stars[i]; });
                    if (otherIndex > -1) return false;
                }
            } else {
                return false;
            }
            if (that.facilities.length === other.facilities.length) {
                for (i = 0, l = that.facilities.length; i < l; i++) {
                    otherIndex = Bricks.find(other.facilities, function (facility) { return facility.facilityId == that.facilities[i].facilityId; });
                    if (otherIndex > -1) {
                        if (that.facilities[i].value !== other.facilities[otherIndex].value) return false;
                        if (that.facilities[i].greaterThanEqual !== other.facilities[otherIndex].greaterThanEqual) return false;
                    } else {
                        return false;
                    }
                }
            }
            if (that.languageId !== other.languageId) return false;
            if (that.currencyCode !== other.currencyCode) return false;
            if (that.randomSeed !== other.randomSeed) return false;
            if (that.sub.minPrice !== other.sub.minPrice) return false;
            if (that.sub.maxPrice !== other.sub.maxPrice) return false;
            if (that.sub.locationIds.length === other.sub.locationIds.length) {
                for (i = 0, l = that.sub.locationIds.length; i < l; i++) {
                    if (!Bricks.some(other.sub.locationIds, function (locationId) { return that.sub.locationIds[i] === locationId; })) {
                        return false;
                    }
                }
            } else {
                return false;
            }
            if (that.sub.stars.length === other.sub.stars.length) {
                for (i = 0, l = that.sub.stars.length; i < l; i++) {
                    if (!Bricks.some(other.sub.stars, function (star) { return that.sub.stars[i] === star; })) {
                        return false;
                    }
                }
            } else {
                return false;
            }
            if (that.sub.facilities.length === other.sub.facilities.length) {
                for (i = 0, l = that.sub.facilities.length; i < l; i++) {
                    otherIndex = Bricks.find(other.sub.facilities, function (facility) { return facility.facilityId == that.sub.facilities[i].facilityId; });
                    if (otherIndex > -1) {
                        if (that.sub.facilities[i].value !== other.sub.facilities[otherIndex].value) return false;
                        if (that.sub.facilities[i].greaterThanEqual !== other.sub.facilities[otherIndex].greaterThanEqual) return false;
                    } else {
                        return false;
                    }
                }
            } else {
                return false;
            }

            return true;
        };
    }

    return {
        create: create,
        createFromQueryString: createFromQueryString,
        createFromForm: createFromForm,
        /* Private API methods for testing */
        tokenize: tokenize,
        valuesFromQueryString: valuesFromQueryString,
        valuesToQueryString: valuesToQueryString
    };
});

Bricks.module("DefaultText", function($) {

    var cleanText = function(text) {
        return text.replace(/[\t\r\n]/g, " ");
    };

    var defaultText = function(elem) {
        var text = elem.attr('data-default-text');
        if (text) {
            text = cleanText(text);
        }
        return text;
    };

    var val = function(elem) {
        if (elem.val() === defaultText(elem)) {
            return '';
        }
        return elem.val();
    };

    return {
        cleanText: cleanText,
        defaultText: defaultText,
        val: val
    };
});

(function($) {

    $.fn.defaultText = function() {

        return this.each(function() {
            var $this = $(this);
            var defaultText = Bricks.DefaultText.defaultText($this);

            $this.focus(function() {
                $(this).removeClass('search-input-empty');
                if ($(this).val() === defaultText) {
                    $(this).val('');
                }
            }).blur(function() {
                if ($(this).val() === '' || $(this).val() === defaultText) {
                    $(this).addClass('search-input-empty').val(defaultText);
                }
            });

            if ($(this).val() === '' || $(this).val() === defaultText) {
                $(this).val(defaultText);
                $(this).addClass('search-input-empty');
            } else {
                $(this).removeClass('search-input-empty');
            }
        });
    };

})(jQuery);

