var g_url_prefix = "";

function onLoad(context) {
    if (context == 1) {
        document.getElementById("id_town_search").style.visibility = "visible";
        var textbox = document.getElementById("id_town_textbox");
        var provider = new LocationProvider(g_url_prefix + "/ajax.php", new LoadIndicator(16, 16, g_url_prefix + "/images/general/loading_small.gif"), 4, 2);
        var formatter = new LocationTextFormatter();
        var callback = function(item) {
            textbox.disabled = true;
            textbox.blur();
            setTimeout(function() { document.location.href = g_url_prefix + "/en/" + item.country_name_url + "/" + item.town_name_url + ".html"; }, 0);
        }
        var locationAutoSuggest = new AutoSuggest(textbox, provider, formatter, callback);

        var countryComboBox = document.getElementById("id_country_combobox");
        var townComboBox = document.getElementById("id_town_combobox");

        townComboBoxUpdater = new TownComboBoxUpdater(countryComboBox, townComboBox, g_url_prefix + "/ajax.php", new LoadIndicator(16, 16, g_url_prefix + "/images/general/loading_small.gif"), -40, 1); //GLOBAL
        townComboBoxUpdater.refresh();
    } else if (context == 3) {
//        if (GBrowserIsCompatible()) {
//            __php_showTownMap();
//        }
    } else if (context == 4) {
        if (GBrowserIsCompatible()) {
            __php_showAccommodationMap();
        }
    }

    if (context == 1 || context == 2 || context == 3 || context == 4) {
        datePickerArrival = new DatePicker("id_datepicker_arrival");
        datePickerArrival.setDayComboBox(document.getElementById("id_arrival_day"));
        datePickerArrival.setMonthYearComboBox(document.getElementById("id_arrival_month_year"));
        datePickerArrival.setMinDateFromMinControlValues();
        datePickerArrival.setMaxDateFromMaxControlValues();

        datePickerDeparture = new DatePicker("id_datepicker_departure");
        datePickerDeparture.setDayComboBox(document.getElementById("id_departure_day"));
        datePickerDeparture.setMonthYearComboBox(document.getElementById("id_departure_month_year"));
        datePickerDeparture.setMinDateFromMinControlValues();
        datePickerDeparture.setMaxDateFromMaxControlValues();

        datePickerArrival.nextDayDatePicker = datePickerDeparture;
    }
}

function onUnload(context) {
    if (/*context == 3 || */context == 4) {
        if (GBrowserIsCompatible()) {
            GUnload();
        }
    }
}



//
// accommodationMap
//

var accommodationMap = {
    preferences : {
        containerId         : "map",
        iconImage           : g_url_prefix + "/images/general/marker20px.png",
        iconWidth           : 20,
        iconHeight          : 20,
        iconAnchorX         : 10,
        iconAnchorY         : 10,
        infoWindowAnchorX   : 10,
        infoWindowAnchorY   : 10,
        zoomDefault         : 14
    },

    initialize : function() {
        this.markerIcon = new GIcon();
        this.markerIcon.image = this.preferences.iconImage;
        this.markerIcon.iconSize = new GSize(this.preferences.iconWidth, this.preferences.iconHeight);
        this.markerIcon.iconAnchor = new GPoint(this.preferences.iconAnchorX, this.preferences.iconAnchorY);
        this.markerIcon.infoWindowAnchor = new GPoint(this.preferences.infoWindowAnchorX, this.preferences.iconAnchorY);
        this.markerOptions = { icon : this.markerIcon };
        this.div = document.getElementById(this.preferences.containerId);
        this.zoomDefault = this.preferences.zoomDefault;
        this.map = undefined;
    },

    showMap : function(latitude, longitude) {
        if (typeof this.div != "object" || this.map) {
            throw new Error("showMap() error");
        }
        var ll = new GLatLng(latitude, longitude);
        this.map = new GMap2(this.div);
        this.map.addControl(new GSmallMapControl());
        this.map.addControl(new GMapTypeControl());
        this.map.addControl(new GScaleControl());
        this.map.addControl(new GOverviewMapControl());
        this.map.setCenter(ll, this.zoomDefault, G_NORMAL_MAP);
        this.map.addOverlay(new GMarker(ll, this.markerOptions));
    }
}



//
// AutoSuggest
//

function AutoSuggest(textbox, provider, formatter, callback) {
    this.textbox = textbox;
    this.provider = provider;
    this.formatter = formatter;
    this.callback = callback;
    this.text = this.textbox.value;
    this.dropDown = null;
    this.timeoutId = null;
    this.items = null;
    this.selectedNode = null;
    this.selectedIndex = 0;
    this.delay = 250;
    Utilities.addEvent(this.textbox, "keydown", Utilities.createEventHandlerMethod(this, "onKeyDown"));
    Utilities.addEvent(this.textbox, "keyup", Utilities.createEventHandlerMethod(this, "onKeyUp"));
    Utilities.addEvent(this.textbox, "blur", Utilities.createEventHandlerMethod(this, "hideDropDown"));
    this.createDropDown();
}

AutoSuggest.prototype.onKeyDown = function(event) {
    if (this.dropDown.style.visibility != "visible") {
        return;
    }    
    switch (Utilities.getKeyCode(event)) {
        case 38: //up arrow
            this.selectSuggestion(false);
            this.updateTextbox(this.selectedNode);
            break;
        case 40: //down arrow
            this.selectSuggestion(true);
            this.updateTextbox(this.selectedNode);
            break;
        case 27: //esc
            this.hideDropDown();
            this.textbox.value = "";
            break;
        case 13: //enter
            this.updateTextbox(this.selectedNode);
            this.hideDropDown();
            this.executeCallback();
            break;
    }
}

AutoSuggest.prototype.onKeyUp = function(event) {
    var keyCode = Utilities.getEvent(event).keyCode;
    this.text = this.textbox.value;

    if (this.timeoutId) {
        clearTimeout(this.timeoutId);
    }

    if (keyCode == 8 || //backspace
        keyCode == 46 || //del
        keyCode == 32 || //space
        (keyCode >= 48 && keyCode <= 111) ||
        keyCode > 123) {
        var _this = this;
        this.timeoutId = setTimeout(function() {_this.provider.doSuggestions(_this)}, this.delay);
    }
}

AutoSuggest.prototype.selectSuggestion = function(o) {
    if (typeof o == "boolean") {
        if (!this.selectedNode) {
            return;
        }
        if (o && ((this.selectedIndex + 1) < this.items.length)) {
            this.selectedNode.className = "suggestion-normal";
            this.selectedNode = this.selectedNode.nextSibling;
            this.selectedNode.className = "suggestion-selected";
            this.selectedIndex++;
        } else if (!o && ((this.selectedIndex - 1) >= 0)) {
            this.selectedNode.className = "suggestion-normal";
            this.selectedNode = this.selectedNode.previousSibling;
            this.selectedNode.className = "suggestion-selected";
            this.selectedIndex--;
       }
    } else if (typeof o == "object") {
        if (o == this.selectedNode) {
            return;
        }
        var divs = this.dropDown.childNodes;        
        for (var i = 0; i < divs.length; i++) {
            if (divs[i] == o) {
                if (this.selectedNode) {
                    this.selectedNode.className = "suggestion-normal";
                }
                this.selectedNode = divs[i];
                this.selectedNode.className = "suggestion-selected";
                this.selectedIndex = i;
            }
        }        
    }
}

AutoSuggest.prototype.updateTextbox = function(div) {
    this.textbox.value = div.firstChild.nodeValue;
}

AutoSuggest.prototype.executeCallback = function() {
    if (this.callback) {
        this.callback(this.items[this.selectedIndex]);
    }
}

AutoSuggest.prototype.createDropDown = function() {
    if (this.dropDown) {
        return;
    }

    this.dropDown = document.createElement("div");
    this.dropDown.className = "dropdown";
    document.body.appendChild(this.dropDown);

    var pos = Utilities.getElementPosition(this.textbox);
    this.dropDown.style.left = pos[0] + "px";
    this.dropDown.style.top = (pos[1] + this.textbox.offsetHeight - 1) + "px";
}

AutoSuggest.prototype.showDropDown = function(items) {
    if (!items || items.length == 0) {
        this.hideDropDown();
        return;
    }

    var div = null;
    var _this = this;

    var onMouseOver = function(event) {
        var selectedDiv = Utilities.getEventTarget(event)
        _this.selectSuggestion(selectedDiv);
    }

    var onMouseDown = function(event) {
        var selectedDiv = Utilities.getEventTarget(event);
        _this.selectSuggestion(selectedDiv);
        _this.updateTextbox(selectedDiv);
        _this.hideDropDown();
        _this.executeCallback();
    }

    this.dropDown.innerHTML = "";
    this.items = items;

    for (var i = 0; i < items.length; i++) {
        div = document.createElement("div");
        div.className = "suggestion-normal";
        div.appendChild(document.createTextNode(this.formatter.format(items[i])));
        this.dropDown.appendChild(div);
        div.onmouseover = onMouseOver;
        div.onmousedown = onMouseDown;
    }

    this.selectSuggestion(this.dropDown.firstChild);
    this.dropDown.style.height = div.offsetHeight * items.length;
    this.dropDown.style.visibility = "visible";
    this.dropDown.style.zIndex = 100;
}

AutoSuggest.prototype.hideDropDown = function() {
    this.dropDown.style.visibility = "hidden";
    this.dropDown.style.zIndex = -100;
    this.selectedNode = null;
}



//
// LocationProvider
//

LocationProvider = function(url, indicator, offsetX, offsetY) {
    this.url = url;
    this.indicator = indicator;
    this.offsetX = offsetX;
    this.offsetY = offsetY;
    this.request = Ajax.createRequest();
    this.minLength = 2;
}

LocationProvider.prototype.doSuggestions = function(control) {
    if (this.request.readyState != 0) {
        this.request.abort();
        this.indicator.hide();
    }
    if (control && control.text.length < this.minLength) {
        control.hideDropDown();
        return;
    }

    this.indicator.showNextToElement(control.textbox, this.offsetX, this.offsetY);

    var _this = this;
    var url = this.url + "?t=1&s=" + encodeURIComponent(control.text);

    this.request.open("GET", url, true);
    this.request.setRequestHeader("Cache-Control", "no-cache");
    this.request.onreadystatechange = function() {
        if (_this.request.readyState == 4 && _this.request.status == 200) {
            var items = _this.request.responseText.length > 0 ? eval("(" + _this.request.responseText + ")") : "";
            control.showDropDown(items);
            _this.indicator.hide();
        }
    }

    this.request.send(null);
}



//
// LocationTextFormatter
//

LocationTextFormatter = function() {
}

LocationTextFormatter.prototype.format = function(item) {
    return item.town_name + " (" + item.country_name + ")";
}



//
// Ajax
//

function Ajax() {
}

Ajax.createRequest = function() {
    if (typeof XMLHttpRequest != "undefined") {
        return new XMLHttpRequest();
    } else if (typeof ActiveXObject != "undefined") {
        var versions = ["Msxml2.XMLHTTP.7.0", "Msxml2.XMLHTTP.6.0", "Msxml2.XMLHTTP.5.0", "Msxml2.XMLHTTP.4.0", "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP", "Microsoft.XMLHTTP"];
        for (var i = 0; i < versions.length; i++) {
            try {
                var request = new ActiveXObject(versions[i]);
                return request;
            } catch (e) {
            }
        }
    }
    throw new Error("Unable to create request object");
}



//
// Calendar
//

function Calendar(id, date) {
    this.id = id;
    this.date = date;
    this.nowDate = new Date();
    this.minDate = null;
    this.maxDate = null;
    this.dayNames = ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"];
    this.monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "Novermber", "December"];
    this.dayCells = new Array(42);
    this.onSelected = null;
    this.showToday = true;

    for (var i = 0; i < this.dayCells.length; i++) {
        this.dayCells[i] = {"disabled": false, "number": 0};
    }

    this.tableHeader = null;
    this.tableCalendar = null;
    this.divWindow = null;
}

Calendar.prototype.show = function(parent) {
    this.tableHeader = this.createHeader();
    this.tableCalendar = this.createGrid();

    this.divWindow = document.createElement("div");
    this.divWindow.id = this.id + "_window";
    this.divWindow.className = "calendar";
    this.divWindow.appendChild(this.tableHeader);
    this.divWindow.appendChild(this.tableCalendar);
    parent.appendChild(this.divWindow);
    Utilities.disableSelection(this.divWindow);

    this.refresh();
}

Calendar.prototype.createHeader = function() {
    var table = document.createElement("table");
    var tbody = document.createElement("tbody");
    var tr = document.createElement("tr");
    var td = null;

    table.id = this.id + "_header";
    table.cellSpacing = 0;
    table.cellPadding = 0;
    table.className = "calendar-header";

    td = document.createElement("td");
    td.id = this.id + "_button_left";
    td.className = "calendar-header-button-left";
    tr.appendChild(td);
    Utilities.addEvent(td, "mousedown", Utilities.createEventHandlerMethod(this, "onMouseDown"));

    td = document.createElement("td");
    td.id = this.id + "_title";
    td.className = "calendar-header-title";
    td.innerHTML = "Title";
    tr.appendChild(td);

    td = document.createElement("td");
    td.id = this.id + "_button_right";
    td.className = "calendar-header-button-right";
    tr.appendChild(td);
    Utilities.addEvent(td, "mousedown", Utilities.createEventHandlerMethod(this, "onMouseDown"));

    tbody.appendChild(tr);
    table.appendChild(tbody);

    return table;
}

Calendar.prototype.createGrid = function() {
    var table = document.createElement("table");
    var tbody = document.createElement("tbody");
    var tr = null;
    var td = null;

    table.id = this.id + "_grid";
    table.cellSpacing = 0;
    table.cellPadding = 0;
    table.className = "calendar-grid";

    var i = 0;

    for (var row = 0; row < 7; row++) {
        tr = document.createElement("tr");
        for (var col = 0; col < 7; col++) {
            td = document.createElement("td");
            if (row == 0) {
                td.className = "calendar-grid-cell-header";
                td.innerHTML = this.dayNames[col];
            } else {
                td.id = this.id + "_day_" + i++;
            }
            tr.appendChild(td);
        }
        tbody.appendChild(tr);
    }
    table.appendChild(tbody);
    Utilities.addEvent(table, "mousedown", Utilities.createEventHandlerMethod(this, "onMouseDown"));

    return table;
}

Calendar.prototype.getDaysInMonth = function(month, year) {
    return (month == 2) ? ((year % 4 == 0) ? ((year % 100 == 0 && year % 400 > 0) ? 28 : 29) : 28) : ((month - 1) % 7 % 2 ? 30 : 31);
}

Calendar.prototype.refresh = function() {
    var i = 0;
    var pos = 0;
    var prevMonthDate = new Date(this.date.getFullYear(), this.date.getMonth() - 1, 1, 0, 0, 0);
    var currMonthDate = new Date(this.date.getFullYear(), this.date.getMonth(), 1, 0, 0, 0);
    var prevDays = this.getDaysInMonth(prevMonthDate.getMonth() + 1, prevMonthDate.getFullYear());
    var currDays = this.getDaysInMonth(currMonthDate.getMonth() + 1, currMonthDate.getFullYear());
    var firstDayPos = currMonthDate.getDay() == 0 ? 6 : (currMonthDate.getDay() == 1 ? 7 : currMonthDate.getDay() - 1);

    while (pos < firstDayPos) {
        this.dayCells[pos].disabled = true;
        this.dayCells[pos++].number = prevDays + pos - firstDayPos;
    }

    i = 1;
    while (i <= currDays) {
        currMonthDate.setDate(i);
        if ((this.maxDate && this.maxDate.getTime() < currMonthDate.getTime()) ||
            (this.minDate && this.minDate.getTime() > currMonthDate.getTime())) {
            this.dayCells[pos].disabled = true;
        } else {
            this.dayCells[pos].disabled = false;
        }
        this.dayCells[pos++].number = i++;
    }

    i = 1;
    while (pos < this.dayCells.length) {
        this.dayCells[pos].disabled = true;
        this.dayCells[pos++].number = i++;
    }

    for (i = 0; i < this.dayCells.length; i++) {
        var day = document.getElementById(this.id + "_day_" + i);
        day.innerHTML = this.dayCells[i].number;

        if (this.dayCells[i].disabled) {
            day.className = "calendar-grid-cell-grayed";
        } else {
            if (this.showToday &&
            this.date.getFullYear() == this.nowDate.getFullYear() &&
            this.date.getMonth() == this.nowDate.getMonth() &&
            this.dayCells[i].number == this.nowDate.getDate()) {
                day.className = "calendar-grid-cell-today"
            } else {
                day.className = "calendar-grid-cell-normal";
            }
        }
    }

    var e = document.getElementById(this.id + "_title");
    if (e) {
        e.innerHTML = this.monthNames[this.date.getMonth()] + " " + this.date.getFullYear();
    }
}

Calendar.prototype.onMouseDown = function(event) {
    var target = Utilities.getEventTarget(event);

    if (target.id.length > 0) {
        if (/^.*?_day_(\d+)$/.test(target.id)) {
            if (!this.dayCells[parseInt(RegExp.$1)].disabled) {
                this.date.setDate(parseInt(target.innerHTML));
                if (this.onSelect) {
                    this.onSelect(this);
                }
            }
        } else if (target.id == (this.id + "_button_left")) {
            this.prevMonth();
        } else if (target.id == (this.id + "_button_right")) {
            this.nextMonth();
        }
    }
}

Calendar.prototype.prevMonth = function() {
    this.date.setDate(1);
    this.date.setMonth(this.date.getMonth() - 1);
    this.refresh();
}

Calendar.prototype.nextMonth = function() {
    this.date.setDate(1);
    this.date.setMonth(this.date.getMonth() + 1);
    this.refresh();
}



//
// DatePicker (inherits Calendar)
//

DatePicker.prototype = new Calendar;

function DatePicker(id) {
    var now = new Date();

    this.base = Calendar;
    this.base(id, new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0));

    this.nextDayDatePicker = null;
    this.dayComboBox = null;
    this.monthYearComboBox = null;
    this.monthYearSeparator = "_";
    this.selectedDate = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0);
    this.iconElement = null;
    this.isVisible = false;

    this.show(document.body);
    this.divWindow.style.position = "absolute";
    this.divWindow.style.top = "-500px";
    this.divWindow.style.visibility = "hidden";
    this.onSelect = Utilities.createEventHandlerMethod(this, "onSelectHandler");

    Utilities.addEvent(document, "mousedown", Utilities.createEventHandlerMethod(this, "onBodyMouseDownHandler"));
}

DatePicker.prototype.setDayComboBox = function(element) {
    this.dayComboBox = element;
    this.setControlsMaxDays();
    this.selectedDate = this.getControlsDate();
    Utilities.addEvent(this.dayComboBox, "change", Utilities.createEventHandlerMethod(this, "onControlsChangedHandler"));
}

DatePicker.prototype.setMonthYearComboBox = function(element) {
    this.monthYearComboBox = element;
    this.setControlsMaxDays();
    this.selectedDate = this.getControlsDate();
    Utilities.addEvent(this.monthYearComboBox, "change", Utilities.createEventHandlerMethod(this, "onControlsChangedHandler"));
}

DatePicker.prototype.showUnder = function(iconElement, underElement) {
    this.iconElement = iconElement;
    var lt = Utilities.getElementPosition(underElement);
    this.divWindow.style.left = lt[0] + "px";
    this.divWindow.style.top = (lt[1] + underElement.offsetHeight + 1) + "px";
    this.divWindow.style.visibility = "visible";
    this.selectedDate = this.getControlsDate();
    this.syncDate(this.selectedDate, this.date);
    this.refresh();
    this.isVisible = true;
}

DatePicker.prototype.hide = function() {
    this.divWindow.style.visibility = "hidden";
    this.isVisible = false;
}

DatePicker.prototype.toggle = function(iconElement, underElement) {
    if (this.isVisible) {
        this.hide();
    } else {
        this.showUnder(iconElement, underElement);
    }
}

DatePicker.prototype.setMinDateToday = function() {
    this.minDate = new Date(this.nowDate.getFullYear(), this.nowDate.getMonth(), this.nowDate.getDate(), 0, 0, 0);
}

DatePicker.prototype.setMinDateTomorrow = function() {
    this.minDate = new Date(this.nowDate.getFullYear(), this.nowDate.getMonth(), this.nowDate.getDate() + 1, 0, 0, 0);
}

DatePicker.prototype.setMinDateFromCurrentControlValues = function() {
    var date = this.getControlsDate();
    this.minDate = new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0);
}

DatePicker.prototype.setMinDateFromMinControlValues = function() {
    if (this.monthYearComboBox && this.monthYearComboBox.options.length > 0) {
        var value = this.monthYearComboBox.options[0].value;
        if (value) {
            var my = value.split(this.monthYearSeparator);
            if (my && my.length == 2) {
                my[0] = parseInt(my[0]);
                my[1] = parseInt(my[1]);
                if (!isNaN(my[0]) && !isNaN(my[1])) {
                    this.minDate = new Date(my[1], my[0] - 1, 1, 0, 0, 0);
                }
            }
        }
    }
}

DatePicker.prototype.setMaxDateFromMaxControlValues = function() {
    if (this.monthYearComboBox && this.monthYearComboBox.options.length > 0) {
        var value = this.monthYearComboBox.options[this.monthYearComboBox.options.length - 1].value;
        if (value) {
            var my = value.split(this.monthYearSeparator);
            if (my && my.length == 2) {
                my[0] = parseInt(my[0]);
                my[1] = parseInt(my[1]);
                if (!isNaN(my[0]) && !isNaN(my[1])) {
                    this.maxDate = new Date(my[1], my[0] - 1, this.getDaysInMonth(my[0], my[1]), 0, 0, 0);
                }
            }
        }
    }
}

DatePicker.prototype.getControlsDate = function() {
    var date = new Date(this.selectedDate);
    var value;

    if (this.dayComboBox && this.dayComboBox.options.length > 0) {
        value = this.dayComboBox.options[this.dayComboBox.selectedIndex].value;
        if (value != null) {
            var day = parseInt(value);
            if (!isNaN(day)) {
                date.setDate(day);
            }
        }
    }

    if (this.monthYearComboBox && this.monthYearComboBox.options.length > 0) {
        value = this.monthYearComboBox.options[this.monthYearComboBox.selectedIndex].value;
        if (value != null) {
            var my = value.split(this.monthYearSeparator);
            if (my && my.length == 2) {
                my[0] = parseInt(my[0]);
                my[1] = parseInt(my[1]);
                if (!isNaN(my[0]) && !isNaN(my[1])) {
                    date.setMonth(my[0] - 1);
                    date.setFullYear(my[1]);
                }
            }
        }
    }

    return date;
}

DatePicker.prototype.setControlsDate = function(date) {
    var value, i;
    if (this.dayComboBox) {
        value = date.getDate();
        for (i = 0; i < this.dayComboBox.options.length; i++) {
            if (this.dayComboBox.options[i].value == value) {
                this.dayComboBox.selectedIndex = i;
                break;
            }
        }
    }

    if (this.monthYearComboBox) {
        value = (date.getMonth() + 1) + this.monthYearSeparator + date.getFullYear();
        for (i = 0; i < this.monthYearComboBox.options.length; i++) {
            if (this.monthYearComboBox.options[i].value == value) {
                this.monthYearComboBox.selectedIndex = i;
                break;
            }
        }
    }
}

DatePicker.prototype.syncDate = function(srcDate, dstDate) {
    dstDate.setFullYear(srcDate.getFullYear());
    dstDate.setMonth(srcDate.getMonth());
    dstDate.setDate(srcDate.getDate());
}

DatePicker.prototype.setControlsMaxDays = function() {
    if (this.dayComboBox && this.dayComboBox.options.length > 0 && this.monthYearComboBox && this.monthYearComboBox.length > 0) {
        var value = this.monthYearComboBox.options[this.monthYearComboBox.selectedIndex].value;
        var i;

        if (value == null) {
            return;
        }

        var my = value.split(this.monthYearSeparator);

        if (!my || my.length != 2) {
            return;
        }

        my[0] = parseInt(my[0]);
        my[1] = parseInt(my[1]);

        if (isNaN(my[0]) || isNaN(my[1])) {
            return;
        }

        var daysMax = this.getDaysInMonth(my[0], my[1]);
        var daysInControl = this.dayComboBox.options.length;
        var option = null;

        if (daysInControl > daysMax) {
            if (this.dayComboBox.selectedIndex >= daysMax) {
                this.dayComboBox.selectedIndex = daysMax - 1;
            }
            for (i = 0; i < (daysInControl - daysMax); i++) {
                this.dayComboBox.options[daysMax] = null;
            }
        } else if (daysInControl < daysMax) {
            for (i = daysInControl + 1; i <= daysMax; i++) {
                option = document.createElement("option");
                option.text = i;
                option.value = i;
                this.dayComboBox.options.add(option);
            }
        }
    }
}

DatePicker.prototype.updateNextDayDatePicker = function(date) {
    if (this.nextDayDatePicker) {
        if (this.nextDayDatePicker.selectedDate <= date) {
            var dateNextDay = new Date(date);
            dateNextDay.setDate(dateNextDay.getDate() + 1);
            this.nextDayDatePicker.selectedDate = dateNextDay;
            this.nextDayDatePicker.setControlsDate(dateNextDay);
            this.nextDayDatePicker.setControlsMaxDays();
        }
    }
}

DatePicker.prototype.onSelectHandler = function(o) {
    this.syncDate(this.date, this.selectedDate);
    this.setControlsDate(this.selectedDate);
    this.setControlsMaxDays();
    this.updateNextDayDatePicker(this.selectedDate);
    this.hide();
}

DatePicker.prototype.onControlsChangedHandler = function(event) {
    this.setControlsMaxDays();
    this.selectedDate = this.getControlsDate();
    this.updateNextDayDatePicker(this.selectedDate);
}

DatePicker.prototype.onBodyMouseDownHandler = function(event) {
    if (this.isVisible) {
        var target = Utilities.getEventTarget(event);
        if (target.id != this.iconElement.id && target.id.indexOf(this.id) != 0) {
            this.hide();
        }
    }
}



//
// LoadIndicator
//

function LoadIndicator(width, height, image) {
    this.width = width;
    this.height = height;
    this.image = image;
    this.div = document.createElement("div");
    this.div.style.width = this.width + "px";
    this.div.style.height = this.height + "px";
    this.div.style.backgroundImage = "url(" + this.image + ")";
    this.div.style.backgroundRepeat = "no-repeat";
    this.div.style.visibility = "hidden";
    document.body.appendChild(this.div);
}

LoadIndicator.prototype.showNextToElement = function(element, offsetX, offsetY) {
    var pos = Utilities.getElementPosition(element);
    this.div.style.position = "absolute";
    this.div.style.left = pos[0] + element.offsetWidth + offsetX  + "px";
    this.div.style.top = pos[1] + offsetY + "px";
    this.show();
}

LoadIndicator.prototype.show = function() {
    if (!this.div) {
        return;
    }
    this.div.style.visibility = "visible";
    this.div.style.zIndex = 1000;
}

LoadIndicator.prototype.hide = function() {
    if (!this.div) {
        return;
    }
    this.div.style.visibility = "hidden";
    this.div.style.zIndex = 0;
}

LoadIndicator.prototype.destroy = function() {
    if (!this.div) {
        return;
    }
    document.body.removeChild(this.div);
    this.div = null;
}



//
// TownComboBoxUpdater
//

function TownComboBoxUpdater(countryComboBox, townComboBox, url, indicator, offsetX, offsetY) {
    this.countryComboBox = countryComboBox;
    this.townComboBox = townComboBox;
    this.request = Ajax.createRequest();
    this.url = url;
    this.indicator = indicator;
    this.offsetX = offsetX;
    this.offsetY = offsetY;
    this.ready = false;

    Utilities.addEvent(this.countryComboBox, "change", Utilities.createEventHandlerMethod(this, "onCountryChange"));
}

TownComboBoxUpdater.prototype.onCountryChange = function() {
    this.refresh();
}

TownComboBoxUpdater.prototype.refresh = function() {
    this.suspendTownComboBox();

    if (this.request.readyState != 0) {
        this.request.abort();
    }

    var _this = this;
    var value = this.countryComboBox.options[this.countryComboBox.selectedIndex].value;
    var url = this.url + "?t=2&s=" + encodeURIComponent(value);

    this.request.open("GET", url, true);
    this.request.setRequestHeader("Cache-Control", "no-cache");
    this.request.onreadystatechange = function() {
        if (_this.request.readyState == 4) {
            if (_this.request.status == 200) {
                if (_this.request.responseText.length > 0) {
                    var items = eval("(" + _this.request.responseText + ")");
                    _this.fillTownComboBox(items);
                    _this.resumeTownComboBox();
                }
            }
        }
    }

    this.request.send(null);
}

TownComboBoxUpdater.prototype.suspendTownComboBox = function() {
    this.ready = false;
    this.townComboBox.disabled = true;
    this.indicator.showNextToElement(this.townComboBox, this.offsetX, this.offsetY);
}

TownComboBoxUpdater.prototype.resumeTownComboBox = function() {
    this.ready = true;
    this.townComboBox.disabled = false;
    this.indicator.hide();
}

TownComboBoxUpdater.prototype.fillTownComboBox = function(items) {
    if (!items || items.length == 0) {
        return;
    }

    var option;

    if (this.townComboBox.options.length > 0) {
        this.townComboBox.options.length = 0;
    }

    for (var i = 0; i < items.length; i++) {
        option = document.createElement("option");
        option.text = items[i].town_name;
        option.value = items[i].town_name_url;
        this.townComboBox.options.add(option);
    }
}



//
// Utilities
//

function Utilities()
{
}

Utilities.createEventHandlerMethod = function(o, m)
{
    return function() {
        o[m].apply(o, arguments);
    }
}

Utilities.addEvent = function(o, e, h)
{
    if (o.addEventListener) {
        o.addEventListener(e, h, false);
    } else if (o.attachEvent) {
        o.attachEvent("on" + e, h);
    }
}

Utilities.removeEvent = function(o, e, h)
{
    if (o.remoteEventListener) {
        o.removeEventListener(e, h, false);
    } else if (o.detachEvent) {
        o.detachEvent("on" + e, h);
    }
}

Utilities.stopEvent = function(e)
{
    if (e) {
        if (window.event) {
            e.cancelBubble = true;
            e.returnValue = false;
        } else {
            e.preventDefault();
            e.stopPropagation();
        }
    }
    return false;
}

Utilities.getEvent = function(e)
{
    return (window.event) ? window.event : e;
}

Utilities.getEventTarget = function(e)
{
    return (window.event) ? window.event.srcElement : e.target;
}

Utilities.getKeyCode = function(e)
{
    return (e.keyCode) ? e.keyCode : e.which ? e.which : e.charCode;
}

Utilities.getElementPosition = function(o)
{
    var l = 0, t = 0;
    if (o.offsetParent) {
        l = o.offsetLeft;
        t = o.offsetTop;
        while (o = o.offsetParent) {
            l += o.offsetLeft;
            t += o.offsetTop;
        }
    }
    return [l, t];
}

Utilities.disableSelection = function(o)
{
    o.onselectstart = function() {
        return false;
    }
    o.unselectable = "on";
    o.style.MozUserSelect = "none";
}
