function esBisiesto(nAno){
	var bRes = true;
	bRes = bRes && (nAno % 4 == 0);
	bRes = bRes && (nAno % 100 != 0);
	bRes = bRes || (nAno % 400 == 0);
	return bRes;
}

function finMes(nMes, nAno){
	var nRes = 0;
	switch (nMes){
		case 1: nRes = 31; break;
		case 2: nRes = 28; break;
		case 3: nRes = 31; break;
		case 4: nRes = 30; break;
		case 5: nRes = 31; break;
		case 6: nRes = 30; break;
		case 7: nRes = 31; break;
		case 8: nRes = 31; break;
		case 9: nRes = 30; break;
		case 10: nRes = 31; break;
		case 11: nRes = 30; break;
		case 12: nRes = 31; break;
	}
	return nRes + (((nMes == 2) && esBisiesto(nAno))? 1: 0);
}


function diasEntre(nDi0, nMe0, nAn0, nDi1, nMe1, nAn1) {
	var nAno;
	var nMes;
	var nDias = 0;

	for(nAno = nAn0; nAno <= nAn1; nAno++) {
		if(nAno != nAn0)
			nMe0 = 1;
		for(nMes = nMe0; (nMes < nMe1 && nAno == nAn1) || (nMes <= 12 && nAno != nAn1); nMes++)
			nDias += finMes(nMes, nAno);
	}
	nDias = nDias - nDi0 + nDi1;
	return nDias;				
}


function hideReservar()
{
	hide("btnReservar");
	insertInputValue("imp_total",'');
	insertInputValue("imp_reserva",'');
}

function noches()
{
	var entrada_dia = new getObj("SR_ARRIVAL_DAY");
	var entrada_mes = new getObj("SR_ARRIVAL_MONTH");
	var entrada_ano = new getObj("SR_ARRIVAL_YEAR");
	
	var salida_dia = new getObj("SR_DEPARTURE_DAY");
	var salida_mes = new getObj("SR_DEPARTURE_MONTH");
	var salida_ano = new getObj("SR_DEPARTURE_YEAR");
	
	var noches = new getObj("noches");
	noches.obj.value = diasEntre(parseInt(entrada_dia.obj.value),parseInt(entrada_mes.obj.value),parseInt(entrada_ano.obj.value),parseInt(salida_dia.obj.value),parseInt(salida_mes.obj.value),parseInt(salida_ano.obj.value));
}


function EHNode(name) {
    this.node           = document.getElementById(name);
}

EHNode.prototype.clear = function() {
    if(this.node) {
        while(this.node.hasChildNodes()) {
            this.node.removeChild(this.node.firstChild);
        }
    }
}

EHNode.prototype.print = function(text) {
    if(this.node) {
        var newNode = document.createTextNode(text);
        this.node.appendChild(newNode);
    }
}

EHNode.prototype.printElement = function(element) {
    if(this.node) {
        var newNode = document.createElement(element);
        this.node.appendChild(newNode);
    }
}

EHNode.prototype.println = function(text) {
    this.print(text);
    this.printElement("br");
}

//
//  Some Utilities for HTML Selects
//
function EHSelect(node) {
    this.node         = node;
}

EHSelect.prototype.getSelectedOption = function() {
    var option;
    if(this.node) {
        var options = this.node.options;
        var index   = this.node.selectedIndex;
        option      = options[index];
    }
    return option;
}


EHSelect.prototype.getSelectedValue = function() {
    var option = this.getSelectedOption();

    var value;
    if(option) {
        value   = option.value;
    }
    return value;
}

EHSelect.prototype.selectValue = function(value) {
    if(this.node) {
        var options = this.node.options;
        for(i=0; i<options.length; i++) {
            if(options[i].value == value) {
                this.node.selectedIndex   = i;
                break;
            }
        }
    }
}


function getLanguage() {
    var language;
    if(navigator) {
        language    = document.reservas.LANG.value;
        if(language) {
            language    = language.substring(0,2).toLowerCase();
        } else {
            language    = "en";
        }
    }
    return language;
}




/*
 *  Some code to glue the calendar into index.php
 */

function calendarFields(name) {
    this.weekday= document.getElementById(name+"_WEEKDAY")
    this.day	= document.getElementById(name+"_DAY")
    this.month	= document.getElementById(name+"_MONTH")
    this.year	= document.getElementById(name+"_YEAR")
}





function writeSelectedPoi() {
    var SR_CITY_ID      = document.reservas.SR_CITY_ID;
    var selectedIndex   = SR_CITY_ID.selectedIndex;
    if(selectedIndex < SR_CITY_ID.options.length) {
        var cityId          = SR_CITY_ID.options[selectedIndex].value;
        if(cityId) {
            writePOI(cityId);
        }
    }
}


//
// Implementation of the Target Action Paradigm, so that we
// can bind an action AND a target to te evven handlers
//
//  Please note: this uses the NeXTStep target/action pattern
//  However it names the target "delegate" to avoid confusion with
//  the event.target
//
//  The datastructure:
//  sourceObject._delegates[action].ta.{delegate,action}
//
// additionally this implementation allows for multiple receivers per event
//
function TADelegate(receiver, action, delegate, delegateAction) {
    if( receiver._delegates == null || ! receiver._delegates) {
        receiver._delegates  = new Object();
    }
    if(! receiver._delegates[action]) {
        // allow for multiple delegates per action
        receiver._delegates[action] = new Array();
    }
    var ta          = new Object();     // holder for target/action
    ta.delegate     = delegate;         // the target
    ta.action       = delegateAction;   // the action
    var actionArray = receiver._delegates[action];
    actionArray[actionArray.length] = ta;   // IE 5 does not support push()
    receiver["on"+action]       = TAForward;    // call forward on event
}

function TAForward(event) {
    var target;
    if(! event) {
        event   = window.event; // IE
    }
    if(event.target) {
        target  = event.target;     // W3C, NS
    } else {
        target  = event.srcElement;  // IE
        event.target    = target;   // make compatible
    }
    if(target) {
        var delegates   = target._delegates;         // get the delegates
        var tas         = delegates[event.type];    // get target/action tuples for this event
        for(i in tas) {
            // dispatch target actions
            var ta  = tas[i];
            var delegate    = ta.delegate;
            var action      = ta.action;
            delegate[action](event);                    // call the action on the target
        }
    }
}


//
// The AutoCompletor binds together a SELECT and a Text Field
// (edx, 2005-09-27)
//

function AutoCompletor(selectField, textField) {
    // constants
    this.KEY_UP     = 38;
    this.KEY_DOWN   = 40;
    this.name       = "AutoCompletor";
    
    // instance variables:
    this.selectField    = selectField;
    this.textField      = textField;
        
    // wire the events:
    TADelegate(this.textField,  "keydown",this, "keyDownHandler");
    TADelegate(this.textField,  "keyup",  this, "keyUpHandler");
    TADelegate(this.textField,  "blur",   this, "setTextFieldToSelected");
    TADelegate(this.selectField, "change",this, "setTextFieldToSelected");
}


AutoCompletor.prototype.autocomplete = function(field) {
    var search      = field.value.toLowerCase();
    var foundNames  = new Array();
    if(search.length > 0) {
        var options	= this.selectField.options;
        for (i=0; i<options.length; i++) {
            var name        = options[i].text;
            var lowerName   = name.toLowerCase();
            if(lowerName.indexOf(search) == 0) {
                if(foundNames.length == 0) {
                    // first finding
                    this.selectField.selectedIndex    = i;
                }
                foundNames.push(name);
            }
        }
    }
}

AutoCompletor.prototype.setTextFieldToSelected = function() {
    var option         = this.selectField.options[this.selectField.selectedIndex];
    var name           = option.text;
    this.textField.value = name;    
    this.changed();
}


AutoCompletor.prototype.keyDownHandler = function(event) {
    var key;
    if(event.keyCode) {
        key = event.keyCode;    // IE, modern
    } else {
        key = event.which;      // legacy
    }
    if(this.keyDownConsumed) {
        return; // avoid repeated keydown bug in some browsers
    } else {
        this.keyDownConsumed   = 1;
    }
    if(key == this.KEY_UP) {
        if(this.selectField.selectedIndex > 0) {
            this.selectField.selectedIndex--;
        } else {
            this.selectField.selectedIndex    = this.selectField.length-1;
        }
        this.setTextFieldToSelected();
    } else if(key == this.KEY_DOWN) {
        if(this.selectField.selectedIndex < this.selectField.length-1) {
            this.selectField.selectedIndex++;
        } else {
            this.selectField.selectedIndex    = 0;
        }
        this.setTextFieldToSelected();
    }
}



AutoCompletor.prototype.keyUpHandler = function(event) {
    this.autocomplete(this.textField);
    this.keyDownConsumed=0;
}


AutoCompletor.prototype.changed = function() {
    if(this.onchange) {
        var event           = new Object();
        event.type      = "change";
        event.target    = this;
        this.onchange(event);
    }
}


function DatePopup(fieldname, minDateFactory) {
    // Constants
    this.name             = "DatePopup["+fieldname+"]";
    
    this.daynames         = new Object();
    this.daynames["de"]   = new Array("Mo", "Di", "Mi", "Do", "Fr", "Sa", "So");
    this.daynames["en"]   = new Array("Mo", "Tu", "We", "Th", "Fr", "Sa", "Su");
    this.daynames["fr"]   = new Array("Lu", "Ma", "Me", "Je", "Ve", "Sa", "Di");
    this.daynames["nl"]   = new Array("Ma", "Di", "Wo", "Do", "Vr", "Za", "Zo");
    this.daynames["es"]   = new Array("Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sábado", "Domingo");
    this.daynames["tr"]   = new Array("Pa", "Sa", "Ça", "Pe", "Cu", "Cu", "Pa");
    this.daynames["pl"]   = new Array("Po", "Wt", "Sr", "Cz", "Pt", "So", "Ni");
    this.daynames["it"]   = new Array("Lu", "Ma", "Me", "Gi", "Ve", "Sa", "Do");
    
    // instance variables
    this.fieldname  = fieldname;
    this.nodes      = this.getNodes(fieldname);
    this.minDateFactory = minDateFactory;
    
    // wire the events
    TADelegate(this.nodes.day.node,   "change", this, "changedHandler");
    TADelegate(this.nodes.month.node, "change", this, "changedHandler");
    TADelegate(this.nodes.year.node,  "change", this, "changedHandler");
    this.update();
}




// get SELECT nodes
DatePopup.prototype.getNodes    = function(name) {
    var nodes       = new Object();
    nodes.weekday   = new EHNode(name+"_WEEKDAY");
    nodes.day       = new EHSelect(document.getElementById(name+"_DAY"));
    nodes.month     = new EHSelect(document.getElementById(name+"_MONTH"));
    nodes.year      = new EHSelect(document.getElementById(name+"_YEAR"));
    return nodes;
}


// get the selected values from the selects
DatePopup.prototype.getValues = function(nodes) {
    var values      = new Object();
    values.day      = this.nodes.day.getSelectedValue();
    values.month    = this.nodes.month.getSelectedValue();
    values.year     = this.nodes.year.getSelectedValue();
    return values;
}


// convert daynumber (0=sunday) to daystring
DatePopup.prototype.getWeekdayName = function(day) {
    var index       = ((day+6) % 7);
    var language    = getLanguage();
    if(! this.daynames[language]) {
        language    = "en";
    }
    return this.daynames[language][index]; // FIXME: localize
}


// get the currently selected date
DatePopup.prototype.getDate = function() {
    var values  = this.getValues();
    this.date   = new Date(values.year, values.month-1, values.day);
    return this.date;
}

DatePopup.prototype.setDate = function(aDate) {
    this.date   = aDate;
    this.nodes.day.selectValue(this.date.getDate());
    this.nodes.month.selectValue(this.date.getMonth()+1);
    this.nodes.year.selectValue(this.date.getFullYear());
}



DatePopup.prototype.daysPerMonth = function(date) {
    var month   = date.getMonth();
    if(month != 1) {
        // not february
        var days    = new Array(31,28,31,30,31,30,31,31,30,31,30,31);
        return days[month];
    } else {
        var year    = date.getYear();
        if((year % 4 == 0 && year % 100 != 0 ) || year % 400 == 0 ) {
            return 29;
        } else {
            return 28;
        }
    }
}


DatePopup.prototype.validateDate = function(date, event) {
    var minDate = this.minDateFactory.getDate();
    //log.println(this.name+".validateDate:"+minDate.toString()+"<"+date.toString());
    var minDay      = minDate.getDay();
    var minMonth    = minDate.getMonth();
    var minYear     = minDate.getFullYear();
    while(date.valueOf() < minDate.valueOf()) {
        var day     = date.getDate();
        var month   = date.getMonth();
        var year    = date.getFullYear();
        if(event && event.target && event.target == this.nodes.month.node) {
            // changed month: keep day and month
            year++;
        } else if(event && event.target && event.target == this.nodes.day.node) {
            // changed day: keep day
            if(month < 11) {    // month: 0..11
                month++;
            } else {
                month   = 0;
                year++;
            }
        } else {
            // either changed the year or updated forced internally
            if(day < this.daysPerMonth(date)) {
                day++;
            } else if(month < 11) {    // month: 0..11
                day = 1;
                month++;
            } else {
                month   = 0;
                year++;
            }
        }
        date    = new Date(year, month, day);
    }
    return date;
}


DatePopup.prototype.fixDaysPerMonth = function(event) {
    if(event && event.target && event.target == this.nodes.month.node) {
        // make sure that the selected days exists in this month
        var year    = this.nodes.month.getSelectedValue();
        var month   = this.nodes.month.getSelectedValue();
        var day     = this.nodes.day.getSelectedValue();
        var date    = new Date(year, month-1, 1);
        var daysPerMonth    = this.daysPerMonth(date);
        if(day > daysPerMonth) {
            this.nodes.day.selectValue(daysPerMonth);
        }
    }
}

/** values changed externally */
DatePopup.prototype.update = function(event) {
    this.fixDaysPerMonth(event);
    var date    = this.getDate();
    date        = this.validateDate(date, event);
    this.setDate(date);
    var day     = date.getDay();
    var dayName = this.getWeekdayName(day);
    this.nodes.weekday.clear();
    this.nodes.weekday.print(dayName);
	noches();
					
    if(this.onupdate) {
        var myEvent     = new Object();
        myEvent.target  = this;
        myEvent.type    = "update";
        this.onupdate(myEvent);
    }
}

/** popup changed by user interaction */
DatePopup.prototype.changedHandler = function(event) {
	hideReservar();
    this.update(event);
    // forward event:
    if(this.onchange) {
        var myEvent   = new Object();
        myEvent.target  = this;
        myEvent.type    = "change";
        this.onchange(myEvent);
    }
}


// Provide todays date
function DateFactoryToday() {
    this.adjustDay  = 0;    // start adjusting with month
}
DateFactoryToday.prototype.getDate = function() {
    var today       = new Date();
    var dayStart    = new Date(today.getFullYear(), today.getMonth(), today.getDate());
    return dayStart;
}

// provide a date one day after arrival
function DateFactoryNextDay(arrival) {
    this.arrival    = arrival;
    this.adjustDay  = 1;
}
DateFactoryNextDay.prototype.getDate = function() {
    var oneDay          = 24*60*60*1000;
    return new Date(this.arrival.getDate().valueOf() + oneDay);
}


/*
 *  Initializtion
 */
var log;


/** main initialization function */
function index_onload() {
    log    = new EHNode("log");    // generic logging output (optional)
    init_AutoCompletor();
    init_popup();
    init_calendar();
}


// this function initializes the calendar
// called onload
//
var arrival;    // the object validating the arrival popup
var departure;  // the object validating the departure popup

function init_popup() {
    // init popups and set their validator
    arrival     = new DatePopup("SR_ARRIVAL",   new DateFactoryToday());
    departure   = new DatePopup("SR_DEPARTURE", new DateFactoryNextDay(arrival));

    // wire the components:
    // whenever the arrival date changes, also adjust the departure date
    TADelegate(arrival,   "update", departure,  "update");
    arrival.update();   // make sure everything is in sync
}



function init_calendar() {
  /*  for(i=0; i<2; i++) {
        var	button          = document.getElementById("calendarButton"+i);
		
        var a               = document.createElement("a");
        var img             = document.createElement("img");
        a.href              = "#showCalendar";
        a.title             = "Show Calendar";
        a.onclick           = show_calendar;
        img.src             = "img/lleno.gif";
        img.border          = 0;
        a.appendChild(img);
        button.appendChild(a);	
    }*/
}

var calendar;   // the calendar

function show_calendar() {
    if(! calendar) {
        var arrivalFields   = new calendarFields("SR_ARRIVAL");
        var departureFields = new calendarFields("SR_DEPARTURE");
        var	container		= document.getElementById("calendarDiv");
        
        var language    = getLanguage();
        
        calendar            =  new EHCalendar(container, 2, language,
                                              arrivalFields.day, arrivalFields.month, arrivalFields.year,
                                              departureFields.day, departureFields.month,
                                              departureFields.year);
        
        // wire the components:
        // whenever a popup changes, update the calendar
        TADelegate(arrival,   "update", calendar,  "update");       // update calendar
        TADelegate(departure, "update", calendar,  "update");       // update calendar
        
        // whenever the calendar changes, update the popups
        TADelegate(calendar,  "change", arrival,   "update");   // update popups
        
        arrival.update();   // make sure everything is in sync
    }
}

function init_AutoCompletor() {
    var SR_CITY_ID      = document.getElementById("SR_CITY_ID");
    var cityNameField   = document.getElementById("cityNameField");
    if(SR_CITY_ID && cityNameField) {
        var autocompletor   = new AutoCompletor(SR_CITY_ID, cityNameField);
        autocompletor.onchange  = writeSelectedPoi;
    }
}





