// JavaScript code for Price Calendar Funcionality
// requires: commons.js, search*.js, dates_i18n_js.xhtml
// also requires the definition of javascript var ajaxPricesCalendarURL

// TODO: i18n

// CALENDAR Code

var SELECT_ARRIVAL_DATE_STATE = 0;
var SELECT_DEPARTURE_DATE_STATE = 1;
var READY_TO_BOOK = 2;

var NO_AVAILABILITY_GROUP = '0';

var COMMAND_NEXT_WEEK = "NEXT_WEEK";
var COMMAND_PREVIOUS_WEEK = "PREVIOUS_WEEK";
var COMMAND_NEXT_MONTH = "NEXT_MONTH";
var COMMAND_PREVIOUS_MONTH = "PREVIOUS_MONTH";

// CSS CLASSES NAMES

var FROM_DATE_CLASS_NAME = 'entrada';
var TO_DATE_CLASS_NAME = 'salida';
var BOOKING_DAY_CLASS_NAME = 'entera';
var CLOSABLE_DAY_CLASS_NAME = 'hoverquitar';
var CLICABLE_CLASS_NAME = 'clicable';
var UNCLICABLE_CLASS_NAME = '';
var HOTEL_SELECTED_CLASS_NAME = 'first entera';
var HOTEL_UNSELECTED_CLASS_NAME = 'first';
var HOTEL_NO_CLICABLE_CLASS_NAME = 'first noclicable';
var CALENDAR_BAR_CLASS_NAME = 'mayor selec';

function PriceCalendar() {
	this.state = SELECT_ARRIVAL_DATE_STATE;
	this.from = null;
	this.to = null;
	// methods
	this.select = function select (id) {
		var cellSelected = getCellFromId(id);
		if (this.state == SELECT_ARRIVAL_DATE_STATE) { // from date selection
			if (!cellSelected.isAvailable()) return;
			this.state = SELECT_DEPARTURE_DATE_STATE;
			this.from = cellSelected;
			this.to = null;
			this.updateCellsAppearance();
		} else if (this.state == SELECT_DEPARTURE_DATE_STATE) {  // to date selection
			if(cellSelected.hotel != this.from.hotel) return;
			this.state = READY_TO_BOOK;
			this.to = cellSelected;
			this.updateCellsAppearance();
		} else {
			// do nothing
		}
		this.showState();
		activeCalendarBar();
	}
	
	this.setAllCellsSelectability = function setAllCellsSelectability() {
		var disable = true; 
		if (this.state == SELECT_ARRIVAL_DATE_STATE) disable = false;
		var td_elements = get('calendar_table').getElementsByTagName("td");
		if (td_elements == null || td_elements.length == 0) return;
		var newClassName;
		// todo: ignore actual line if exists!
		for (var i = 0; i < td_elements.length; i++) {
			var td = td_elements[i];
			if (td.id == null || td.id == '') // ignore both data or odd aditional cells 
				continue;
			if (td.id.search('calendar_hotel')!=-1) { // first column: hotel name
				newClassName = (disable)?HOTEL_NO_CLICABLE_CLASS_NAME:HOTEL_UNSELECTED_CLASS_NAME;				
			}
			else { // day cell
				newClassName = (!disable && getCellFromId(fixId(td.id)).isAvailable())?CLICABLE_CLASS_NAME:UNCLICABLE_CLASS_NAME;
			}
			td.className = newClassName;
		}
	}
	
	this.unselect = function unselect (id) {		
		if (this.from.id == id) { // from date unselection
			this.state = SELECT_ARRIVAL_DATE_STATE;
			this.updateCellsAppearance();
			this.checkPreviousSelection(true);
			this.to = null;
			this.from = null;
		} else if (this.to.id == id) {  // to date unselection
			this.state = SELECT_DEPARTURE_DATE_STATE;
			this.updateCellsAppearance();
			this.to = null;
		} else {
			// do nothing
		}
		this.showState();
		activeCalendarBar();
	}
	this.checkRangeEndOfAvailability = function checkRangeEndOfAvailability () {
		var fromCell = this.from;
		if (fromCell == null) return;
		if (fromCell.endOfAvailabilityDate != null) return;
		
		// get every cell in the calendar for the hotel
		var cellInputs = fromCell.getLineInputs();
		for (var i = 0; i < cellInputs.length; i++) {
			var cellInput = cellInputs[i];
			var cell = createCellFromInput(cellInput.value);
			if (cell.date.getTime() > fromCell.date.getTime() && !cell.isAvailable()) {
				fromCell.endOfAvailabilityDate = cell.date;
				return;
			}
		}
	}
	this.updateCellsAppearance = function updateCellsAppearance () {
		this.setAllCellsSelectability();
		this.checkRangeEndOfAvailability();
		var fromCell = this.from;
		if (fromCell == null) return;
		var cellInputs = fromCell.getLineInputs();
		for (var i = 0; i < cellInputs.length; i++) {
			var cell = createCellFromInput(cellInputs[i].value);
			this.updateCell(cell);
		}
	}
	
	this.updateCell = function updateCell (cell) {
		var newClassName;
		if (this.state == SELECT_ARRIVAL_DATE_STATE) { // all cells are normal
			cell.markAsNormal();
		}
		if (this.state == SELECT_DEPARTURE_DATE_STATE) { // show selectable cells [from cell already selected]
			var newClassName;
			if (this.from.id == cell.id) { // from cell
				cell.markAsSelected(FROM_DATE_CLASS_NAME);
			} else if (this.from.isCellInRange(cell)) { // selectable cells
				cell.markAsSelectable(FROM_DATE_CLASS_NAME);   
			} else { // others are unselectable cells
				cell.markAsUnselectable();
			}
		}
		if (this.state == READY_TO_BOOK) { // show selectable cells [from cell already selected]
			if (this.from.id == cell.id) { // from cell
				cell.markAsSelected(FROM_DATE_CLASS_NAME);
			} else if (this.to.id == cell.id) { // to cell
				cell.markAsSelected(TO_DATE_CLASS_NAME);
			} else if (this.from.date.getTime() < cell.date.getTime() && cell.date.getTime() < this.to.date.getTime()) {
				cell.markAsBookingDay();
			} else {
				cell.markAsNormal();
			}
		}
	}

	// TODO: unused functions by now. Update this.state with this.isState() and check everything is ok [or not]
	this.inState = function inState (stateToCompare) {
		return (this.getState() == stateToCompare);
	}
	
	this.getState = function getState () {
		if (this.from == null) return SELECT_ARRIVAL_DATE_STATE;
		else if (this.to == null) return SELECT_DEPARTURE_DATE_STATE;
		else return READY_TO_BOOK;	
	}

	this.showState = function showState () {
		// from
		var infoDateFrom = get('infoDateFrom');
		var dateFromControl = get('dateFromControl');
		var dateFrom = get(SEARCH_FORM_DATE_FROM_ELEMENT_NAME);
		// to
		var infoDateTo = get('infoDateTo');
		var dateToControl = get('dateToControl');
		var dateTo = get(SEARCH_FORM_DATE_TO_ELEMENT_NAME);
		// other info
		var selectedHotel = get(SEARCH_FORM_HOTEL_ELEMENT_NAME);
		var infoNights = get('infoNights');
		var infoBook = get('infoButton');

		// highlight right instruction
		for (var i = SELECT_ARRIVAL_DATE_STATE; i <= READY_TO_BOOK; i++ ) {
			get('info_state_'+i).className = 'modificar';
		}
		get('info_state_'+this.state).className = 'activo';
		
		var calendarInstance = this;
		if (this.from != null) {
			infoDateFrom.innerHTML = formatDate(this.from.date);
			dateFrom.value = formatDate(this.from.date);			
			dateFromControl.style.display = "inline";
			dateFromControl.onclick = function() { calendar.unselect(calendarInstance.from.id); };
			selectedHotel.value = this.from.hotel;
			this.from.highligthHotelTitle(HOTEL_SELECTED_CLASS_NAME);
		} else { 
			infoDateFrom.innerHTML = UNSELECTED_TXT;
			dateFrom.value = '';
			dateFromControl.style.display = "none";
			dateFromControl.onclick = function() { };
			selectedHotel.value = '';
		} 
		if (this.to != null) { 
			infoDateTo.innerHTML = formatDate(this.to.date);
			dateTo.value = formatDate(this.to.date);
			dateToControl.style.display = "inline";
			dateToControl.onclick = function() { calendar.unselect(calendarInstance.to.id); };
			if (infoNights != null) {
				var nnights = getNumberOfNights(this.from.date, this.to.date);
				infoNights.value = nnights + ' ' + ((nnights == 1)?NIGHT_TEXT:NIGHTS_TEXT);
				infoNights.style.display = 'block';			
			}
		} else { 
			infoDateTo.innerHTML = UNSELECTED_TXT;
			dateTo.value = '';
			dateToControl.style.display = "none";
			dateToControl.onclick = function() { };
			if (infoNights != null) {
				infoNights.value = '';
				infoNights.style.display = 'none';			
			}
		}
		if (this.state == READY_TO_BOOK) { 
			infoBook.disabled = false;
		} else {
			infoBook.disabled = true;
		}
	}
	
	this.checkPreviousSelection = function checkPreviousSelection(unMark) {
		// mark previous selection (if needed)
		var fromCell = this.from;
		if (fromCell == null) return;
		var previousDateSelected = fromCell.getPreviousDateSelectedElement();
		
		if (unMark) {
			previousDateSelected.innerHTML = '';
			fromCell.highligthHotelTitle(HOTEL_UNSELECTED_CLASS_NAME);
		} else {
			fromCell.highligthHotelTitle(HOTEL_SELECTED_CLASS_NAME);
			if (fromCell.weekFirstDay != getCalendarFirstDay()) {
				var link = '<a style="color:#880C12" href="javascript:;" onclick="calendar.move(ajaxPricesCalendarURL, \'\' , \''+ formatDate(fromCell.date) +'\')">';
				link += formatDate(fromCell.date) + '</a>';
				previousDateSelected.innerHTML = link;
			}
		}	
	}
	this.move = function move(reloadCalendarURL, command, selectedDate) {
		var now = new Date();
		reloadCalendarURL += '?command=' + command;
		if (selectedDate != null) reloadCalendarURL += '&selectedDate=' + selectedDate;
		else reloadCalendarURL += '&date=' + getCalendarLastDay();
		reloadCalendarURL += '&tmst=' + now.getTime();
		var priceCalendar = get('priceCalendar');
		priceCalendar.display = "none";				
		sendXMLRequest(reloadCalendarURL, updateCalendar);
	}
	this.reserve = function reserve() { 
		// call to search.js apropiatteReserveMethod with required data
		reserveWithSelectedDates(this.from.hotel);
	}
	
}

function getCalendarFirstDay() {
	return get('calendar_first_day_of_the_week').value;
}

function getCalendarLastDay() {
	return get('calendar_last_day_of_the_week').value;
}

function updateCalendar(xmlObject, request) {
	var priceCalendar = get('priceCalendar');
	priceCalendar.display = "block";
	priceCalendar.innerHTML = cleanResponse(request.responseText);	
	calendar.updateCellsAppearance();
	calendar.checkPreviousSelection();
	activeCalendarBar();
}

// CELL Code
 
function Cell(hotel, date, price) {
	this.hotel = hotel;
	this.date = parseDate(date);
	this.id = hotel + '_' + date;
	this.price = price;
	this.endOfAvailabilityDate = null;
	this.weekFirstDay = getCalendarFirstDay();
	// methods
	this.isAvailable = function isAvailable() {
		return (this.price != '');
	}
	this.getCellElement = function getCellElement() {
		return get('calendar_cell_'+this.id);
	}
	this.getLineElement = function getLineElement() {
		return get('calendar_line_hotel_'+this.hotel);
	}
	this.getPreviousDateSelectedElement = function getLineElement() {
		return get('calendar_hotel_previous_date_'+this.hotel);
	}
	this.highligthHotelTitle = function highligthHotelTitle(cssClassName) {
		var hotelTitle = get('calendar_hotel_title_'+this.hotel)
		if (hotelTitle != null) hotelTitle.className = cssClassName;
	}
	this.getLineInputs = function getLineInputs() {
		return this.getLineElement().getElementsByTagName("input");
	}
	this.isCellInRange = function isCellInRange(cell) {
		if (cell.date.getTime() <= this.date.getTime()) return false;
		if (this.endOfAvailabilityDate == null) return true;
		return (cell.date.getTime() <= this.endOfAvailabilityDate.getTime())
	}
	this.markAsSelected = function markAsSelected(cssClassName) {
		var cellElement = this.getCellElement();
		cellElement.className = cssClassName;
		var cellId = this.id;
		cellElement.onclick = function() { calendar.unselect(cellId); };
		cellElement.onmouseover = function() { cellElement.className=CLOSABLE_DAY_CLASS_NAME; }; 
		cellElement.onmouseout = function() { cellElement.className=cssClassName; };
	}
	this.markAsNormal = function markAsNormal(newClassName) {
		var cellElement = this.getCellElement();
		cellElement.className = (newClassName != null)?newClassName:CLICABLE_CLASS_NAME;
		var cellId = this.id;
		cellElement.onclick = function() { calendar.select(cellId); };
		cellElement.onmouseover = function() {  }; 
		cellElement.onmouseout = function() {  };
	}
	this.markAsSelectable = function markAsSelectable() {
		this.markAsNormal(CLICABLE_CLASS_NAME);
	}
	this.markAsBookingDay = function markAsBooking() {
		this.markAsNormal(BOOKING_DAY_CLASS_NAME);
	}
	this.markAsUnselectable = function markAsUnselectable() {
		var cellElement = this.getCellElement();
		cellElement.className = UNCLICABLE_CLASS_NAME;
		cellElement.onclick = function() {  };
		cellElement.onmouseover = function() {  }; 
		cellElement.onmouseout = function() {  };
	}
}

function getCellFromId(id) {
	return createCellFromInput(get('calendar_input_' + id).value);
} 

function fixId(completeId) {
	var fixedId = completeId.replace("calendar_input_","");
	fixedId = completeId.replace("calendar_hotel_","");
	fixedId = completeId.replace("calendar_cell_","");
	return fixedId;
}

function createCellFromInput(content) {
	var contentArray = content.split('|');
	return new Cell(contentArray[0], contentArray[1], contentArray[2]);
}
// inherent initialization [it's useful & comfortable]
var calendar = new PriceCalendar();

// functions for calendar bars
function activeCalendarBar(){
	var disable = true; 
	var td_elements = get('calendar_table').getElementsByTagName("td");
	if (td_elements == null || td_elements.length == 0) return;
	for (var i = 1; i < td_elements.length; i++) {
		var td = td_elements[i];
		var calendarBar = get('select0' + i);
		if (td.id == null || td.id == '' || (calendarBar == null)) 
			continue;
		
		calendarBar.onclick = td.onclick;
		calendarBar.onmouseover = td.onmouseover; 
		calendarBar.onmouseout = td.onmouseout;
		calendarBar.className = CALENDAR_BAR_CLASS_NAME;
		if(exitsClass(td, FROM_DATE_CLASS_NAME) || exitsClass(td, TO_DATE_CLASS_NAME)){
			addClass(calendarBar, td.className);
			addClass(calendarBar, CLICABLE_CLASS_NAME);
		}else if(td.className != UNCLICABLE_CLASS_NAME){
			addClass(calendarBar, CLICABLE_CLASS_NAME);
		}else{} //by a bug of JS :s
	}
}

function exitsClass(obj, className){
	return (obj.className.search(className) != -1);
}