var Helper = ( function() {
	var instance = null;
	var activeBids = null;
	var url = null;
	var totalMatches = 0;

	function fixSerialized(pForm){
		return pForm.replace(/data%5BMapBounds%5D%5B0%5D%5Blatitude.*?data%5BGeoreference/g,"");
	} 
	
	function PrivateConstructor() {
		this.hasChangedForm = function(form){
			var result = false;
       		var options = {
  	              beforeSubmit: function(){},
  	              success:      function(response, status){
  	            	if(status == 'success'){
  	            		result = response;
  	            	}
  	              },
  	              url:   '/itineraries/checkchanges',
  	              type:  'post',
  	              mode:  'abort',
  	              port:  'checkchanges',
  	              cache: false,
  	              async: false, 	              
  	              dataType: 'json'
  	         };
  	         $(form).ajaxSubmit(options);
  	         return result;
		};
		this.setActiveBids = function(pActive){
			activeBids = pActive;
		};
		this.hasActiveBids = function(){
			return activeBids;
		};
		this.setTotalMatches = function(pTotal){
			totalMatches = pTotal;
		};
		this.getTotalMatches = function(){
			return totalMatches;
		};
	}

	return new function() {
		this.getInstance = function() {
			if (instance == null) {
				instance = new PrivateConstructor();
				instance.constructor = null;
			}
			return instance;
		}
	};
})();

var helper = Helper.getInstance();

/**
 * Verfies that dates in checkin and checkout fields are consistent, and calculates number 
 * of nigths between those values.
 * @param boolean checkInChanged If checkin was changed or not (checkout was modified) 
 * @return
 */
function checkDates(checkInChanged,nochange){
	try {
		var DAY = 86400000;
		var checkin = newDateFromDatePicker("#CheckIn");
		var checkout = newDateFromDatePicker("#CheckOut");
		var intime = (checkin != null ? checkin.getTime() : null);
		var	outtime = (checkout != null ? checkout.getTime() : null);
		if(!intime && !outtime) {
			$("#nigthsNumber").text("");
			return;
		}
		if(intime && !outtime || (checkInChanged && intime >= outtime)) {
			outtime = intime + DAY;
			checkout = new Date(outtime);
			$("#CheckOutPicker").datepicker( 'setDate' , checkout );
		} else if(outtime && !intime || (!checkInChanged && intime >= outtime)){
			intime = outtime - DAY;
			checkin = new Date(intime);
			$("#CheckInPicker").datepicker( 'setDate' , checkin );
		}
		if($("#nigthsNumber").length > 0){
			var nights = Math.round((outtime - intime)/DAY);
			$("#nigthsNumber").text(nights);
			updateBudgetPerNight();
			checkRemainingTimeToCheckIn();
		}
		if(typeof nochange == 'undefined'){
			$('#CheckIn').trigger('change');
			$('#CheckOut').trigger('change');
		}
	} catch (e) {
		if(window.console)
			console.log(e);
	}
};

function newDateFromDatePicker(selector,time){
	var date = ($(selector).val()).split('-');
	if(date.length > 1){
		if(typeof time == 'undefined'){
			return new Date(date[0],date[1]-1,date[2]);
		} else {
			return new Date(date[0],date[1]-1,date[2],time[0],time[1],time[2]);
		}
	} 
	return null;
};

/**
 * Calculates the datetime for bidding expiration based on value of hours selected by user.
 * @return
 */
function checkBiddingExpiration(){
	updateExpDate();
	checkRemainingTimeToCheckIn();
};

/**
 * Checks if the number of hours remaining from now to the 20th hour of the check-in date at the 
 * coordinates of the geo-reference is higher than the value selected to allow the bidding open.
 * In order to do this, searchs for the geo-reference timezone using Geonames web service through JSON 
 * when it's defined latitude and longitude.
 * The response from Geonames includes: 
 * rawOffset: the amount of time in hours to add to UTC to get standard time in this time zone.
 * gmtOffset: offset to GMT at 1. January
 * dstOffset: offset to GMT at 1. July
 * 
 * @return
 */
function checkRemainingTimeToCheckIn(){
	var lat = $('#latitude_0').val();
	var lng = $('#longitude_0').val();
	if(typeof lat != 'undefined' && typeof lng != 'undefined' && lat != '' && lng != '' && $("#Search").val() != ''){
		url = '/areas/timezone/'+lat+'/'+lng; 
		$.getJSON(
			url,
			function(data)
			{
				if(!data)
					return true;

				var placeOffset = data.offset;
				var placeDate = new Date(serverDate.getTime() + placeOffset*3600000);
				var checkin = newDateFromDatePicker("#CheckIn",[20,0,0]);
				var remaining = 72;
				if(checkin){
					remaining = (checkin.getTime() - placeDate.getTime())/3600000;	
				}
				updateExpOptions(remaining,'remove');
			}
		);
	} else {
		updateExpOptions();
	}
	return true;
}

function updateExpOptions(boundary,type){
	var optSelected = $("#biddingExpiration").selectedValues();
	if(typeof boundary == 'undefined'){
		boundary = 72;
	}
	$("#biddingExpiration").removeOption(/./);
	var lastValidIndex = 1;
    for(var i = 1;i <= 72;i++){
        if((i <= 24 || i%12==0)){
        	if(i <= boundary) {
        		$("#biddingExpiration").addOption(i,i);
        	} else {
        		break;
        	}
        	lastValidIndex = i;
        }
    }
	if($("#biddingExpiration").containsOption(optSelected[0])) {
		$("#biddingExpiration").selectOptions(optSelected[0]);
	} else { 
		$("#biddingExpiration").selectOptions(lastValidIndex);
	}
	updateExpDate();
};

function updateExpDate(){
	var formatted = generateFromServerDate($("#biddingExpiration").val());
	$("#expirationDateCon").text(formatted);
	formatted = formatted.replace(/\*| GMT/g,"");
	$("#expirationDate").val(formatted);
};

function updateBudgetPerNight(keyPressed){
	var nights = $("#nigthsNumber").text();
	var budget = $("#ItineraryBudget").val();
	
	if(nights != '' && budget != '' && (!keyPressed || isKeyCodeValid(keyPressed))){
		var budgetPerNight = parseFloat(budget)/parseInt(nights)
		$("#budgetNightVal").text((Math.round(budgetPerNight)));
		$("#budgetNight").show();
		return;
	}
	$("#budgetNight").hide();
};

function isKeyCodeValid(keyCode){
	return keyCode == 46 || keyCode == 8  || keyCode == 9 || (keyCode >= 35 && keyCode <= 40) || (keyCode >= 48 && keyCode <= 57) || (keyCode >= 96 && keyCode <= 105);
}

$(document).ready(function() {
	$("#CheckInPicker,#CheckOutPicker").change(function(){
		checkDates(this.id == "CheckInPicker");
	});
	$("#biddingExpiration").change(function(){
		checkBiddingExpiration();
	});
	$("#ItineraryBudget")
	.keyup(function(event) {
		updateBudgetPerNight(event.keyCode);
	})
	.change(function() {
		updateBudgetPerNight();
	});
	
    $('.lodgingName').each(function(){
    	$(this).tooltip({
            delay: 0, 
            showURL: false, 
            bodyHandler: function() {
                return lodgingDescriptions[this.id];
            }
        });
    });
	checkDates(false,true);
});