lifestyleapps = {
	locale: 'da',
	energy_unit: 'kJ',
	weight_unit: 'kg',
	height_unit: 'cm',
	nutrition_unit: 'g',
	density: {
		protein: 17.0,
		carbohydrate: 17.0,
		fat: 37.0,
		alcohol: 29.0
	},
	energy: function(food) {
		return Math.round(food.protein * lifestyleapps.density.protein + food.carbohydrate_total * lifestyleapps.density.carbohydrate + food.fat_total * lifestyleapps.density.fat + food.alcohol * lifestyleapps.density.alcohol);
	},
	messages: {
		protein: 'Protein',
		carbohydrate: 'Kulhydrat',
		fat: 'Fedt',
		alcohol: 'Alkohol'
	}
}

jQuery.ajaxSetup({
	'beforeSend': function(xhr) {
		xhr.setRequestHeader("Accept", "text/javascript");
	}
});

function _ajax_request(url, data, callback, type, method) {
	if (jQuery.isFunction(data)) {
		callback = data;
		data = {};
	}
	return jQuery.ajax({
		type: method,
		url: url,
		data: data,
		success: callback,
		dataType: type
	});
};

jQuery.extend({
	put: function(url, data, callback, type) {
		return _ajax_request(url, data, callback, type, 'PUT');
	},
	delete_: function(url, data, callback, type) {
		return _ajax_request(url, data, callback, type, 'DELETE');
	}
});

jQuery.fn.submitWithAjax = function() {
	this.unbind('submit', false);
	this.submit(function() {
		if (this.method.toUpperCase() == "POST") {
			$.post(this.action, $(this).serialize(), null, "script");
		}
		else {
			$.get(this.action, $(this).serialize(), null, "script");
		}
		$(this).find('input[type=submit]').attr('disabled', 'disabled');
		return false;
	});
	return this;
};

//Send data via get if <acronym title="JavaScript">JS</acronym> enabled
jQuery.fn.getWithAjax = function() {
	this.unbind('click', false);
	this.click(function() {
		$.get($(this).attr("href"), $(this).serialize(), null, "script");
		return false;
	});
	return this;
};

//Send data via Post if <acronym title="JavaScript">JS</acronym> enabled
jQuery.fn.postWithAjax = function() {
  this.unbind('click', false);
  this.click(function() {
    $.post($(this).attr("href"), $(this).serialize(), null, "script");
    return false;
  })
  return this;
};

jQuery.fn.putWithAjax = function() {
  this.unbind('click', false);
  this.click(function() {
		$.post($(this).attr("href"), { _method: 'put' }, null, "script");
/*    $.put($(this).attr("href"), $(this).serialize(), null, "script");*/
    return false;
  })
  return this;
};

jQuery.fn.deleteWithAjax = function() {
  this.removeAttr('onclick');
  this.unbind('click', false);
  this.click(function() {
		$.post($(this).attr("href"), { _method: 'delete' }, null, "script");
/*    $.delete_($(this).attr("href"), $(this).serialize(), null, "script");*/
    return false;
  })
  return this;
};

// this will "ajaxify" the links
function ajaxLinks() {
	$('.ajax').submitWithAjax();
	$('a.get').getWithAjax();
	$('a.post').postWithAjax();
	$('a.put').putWithAjax();
	$('a.delete').deleteWithAjax();
}

jQuery.fn.focusFirstFormElement = function() {
	$(this).find("input[type=text]:first").focus();
	return this;
};

jQuery.fn.withHovering = function() {
	$(this).hover(
		function () {
			$(this).addClass("hovering");
		}, 
		function () {
			$(this).removeClass("hovering");
		}
	);
	return this;
};

(function() {
  var delayedObserverStack = [];
  var observed;
 
  function delayedObserverCallback(stackPos) {
    observed = delayedObserverStack[stackPos];
    if (observed.timer) clearTimeout(observed.timer);
   
    observed.timer = setTimeout(function(){
      observed.timer = null;
      observed.callback(observed.obj.val(), observed.obj);
    }, observed.delay * 1000);

    observed.oldVal = observed.obj.val();
  } 
 
  jQuery.fn.extend({
    delayedObserver:function(delay, callback){
      $this = $(this);
     
      delayedObserverStack.push({
        obj: $this, timer: null, delay: delay,
        oldVal: $this.val(), callback: callback
      });
       
      stackPos = delayedObserverStack.length-1;
     
      $this.keyup(function() {
        observed = delayedObserverStack[stackPos];
          if (observed.obj.val() == observed.obj.oldVal) return;
          else delayedObserverCallback(stackPos);
      });
      return this;
    }
  });
})();

jQuery.fn.expandMeal = function() {
	$(this).click(function() {
		token = $("#new_serving input[name='authenticity_token']").attr("value");
		date = $("#new_serving input[name='date']").attr("value");
		$.get($(this).attr("href"), 'authenticity_token='+token+'&date='+date, null, "script");
//		$.getJSON($(this).attr("href") + ".json", function(data) {
//			token = $("#new_serving input[name='authenticity_token']").attr("value");
//			$.each(data, function(i, item) {
//				$.post('/servings', 'authenticity_token='+token+'&serving[food_id]='+item.meal_item.food_id+'&serving[size]=' + item.meal_item.size, null, "script");
//			});
//		});
		return false;
	});
};

jQuery.fn.collectServings = function() {
	selected_servings = $("#servings tr.serving img.selected").parent().parent();
	selected_servings.each(function() {
		$("#consumed-for-selector form").append("<input type='hidden' name='serving_ids[]' value='" + 1 + "'>");
	});
	
	return this;
};

/*$.blockUI.defaults.growlCSS = {
	width:    '50%',
	top:      '2.5em', 
	left:     '25%', 
	right:    '25%', 
	border:   '.1em solid #bc9',
	padding:  '.1em',
	opacity:  '0.85',
	cursor:    null,
	color:    '#000',
	backgroundColor: '#ddeebb',
	'-webkit-border-radius': '.5em',
	'-moz-border-radius':    '.5em'
};
*/
$(document).ready(function() {
	
	//"<script type='text/javascript'>$.growlUI('', '#{h(flash[identifier])}');</script>" unless flash[identifier].blank?
	$("#flash-notice").animate({opacity: 1.0}, 10).slideDown("fast").animate({opacity: 1.0}, 5000).slideUp("fast");
	
/*	$("#flash-notice").hide();
	
	if ($("#flash-notice").text() != "") {
		$.growlUI('', $("#flash-notice").text());
	}
*/
	// All non-GET requests will add the authenticity token
	// if not already present in the data packet
 $(document).ajaxSend(function(event, request, settings) {
		if (typeof(window._auth_token) == "undefined") return;
		// <acronym title="Internet Explorer 6">IE6</acronym> fix for http://dev.jquery.com/ticket/3155
		if (settings.type == 'GET' || settings.type == 'get') return;

		settings.data = settings.data || "";
		settings.data += (settings.data ? "&" : "") + window._auth_token_name + "=" + encodeURIComponent(window._auth_token);
	});

	ajaxLinks();
	
/*	$('*[hint]').inputHint();*/
	
	setupFoodAutoCompleteField();

	$(".close").click(function() {
		$(this).parent().parent().fadeOut('normal');
/*		$.get(this.href, null, null, "script");*/
		$.post('/hints/1.js', { '_method': 'delete' }, null, "script");
		return false;
		});
		
	// pure porna
	$("input, select, textarea").focus(function() { $(this).next("p.hint").addClass('active'); });
	$("input, select, textarea").blur(function() { $(this).next("p.hint").removeClass('active'); });
	$("input[type=radio]").focus(function() { $(this).closest("fieldset").find("p.hint").addClass('active'); });
	$("input[type=radio]").blur(function() { $(this).closest("fieldset").find("p.hint").removeClass('active'); });

	$("#new_session").focusFirstFormElement();
	$("#reset_password").focusFirstFormElement();
	$("#new_password").focusFirstFormElement();
	$("#new_user").focusFirstFormElement();
	$("#new_serving").focusFirstFormElement().submitWithAjax();
	$("#new_measurement").focusFirstFormElement();

	$("#enable-instant-messaging .submit").click(function() {
		$.post('/instant_messagings.js', { '_method': 'post', 'jid': $("#user_jid").attr("value") }, null, "script");
	});
	
//	$("#new_task #task_name").delayedObserver(0.8,
//		function(value, object) {
//			$.get('/tasks/parse.js', { task_name: value }, null, 'script');
//		}
//	);
	
	$(".task-complete form").submitWithAjax();
	$(".task-delete form").submitWithAjax();
	$(".task-archive form").submitWithAjax();
	$(".task-defer form").submitWithAjax();
	
	$(".serving-manage .edit").click(function() { $.get(this.href, null, null, "script"); return false; });
	$("#consumed-for-selector form").collectServings();
	$("#intake-frequent li a.expand").expandMeal();
	$("#picker").change(function() { 
		var subdomain = this.options[this.selectedIndex].value;
		$.get('/users/servicepicker', 'subdomain=' + subdomain, function() { document.location = '/' + subdomain; }, "script");
		return false;
	});
	
	$("img.avatar").attr("onerror", "null;this.src='/images/head-bg.png'").attr("onLoad", "this.style.backgroundImage='none';");
	$("form .energy-component").keyup(function() { calculateEnergy(); });
	
	$("#calculate-daily-energy").mouseover(function() { $("#user_base_weight, #user_height, #user_gender_true, #user_gender_false, #user_birthdate_1i").addClass("focus"); }).click(function() {
		gender = $("#user_gender_true").attr('checked') ? 'male' : 'female';
		weight = $("#user_base_weight").attr('value');
		height = $("#user_height").attr('value');
		age = (1900 + new Date().getYear()) - $("#user_birthdate_1i").attr('value');
		$("#user_daily_energy").attr('value', calculateDailyEnergy(gender, weight, height, age));
		$("#user_daily_energy").effect("highlight", {}, 1000);
		});
	$("#calculate-daily-energy").mouseout(function() { 
		$("#user_base_weight, #user_height, #user_gender_true, #user_gender_false, #user_birthdate_1i").removeClass("focus");
		});
	
	// url: /weight/bmi
	$("#bmi-calculator input").keyup(function() { calculateBodyMassIndex(); });
	$("#bmi-calculator select").change(function() { calculateBodyMassIndex(); });
	$("#bmi-calculator").focusFirstFormElement();
	
	$("#new_user #user_email").blur(function() { 
		if (this.value && this.value.indexOf('@') > 0) {
			$("#user_image").attr("onLoad", "$('#new_user .avatar-lookup').fadeIn('slow');");
			$("#user_image").attr("src", "http://www.gravatar.com/avatar/" + MD5(this.value) + "?s=96&d=wavatar&app=lifestyleapps");
		}
	});
	
	$("#user_profile_path").keyup(function() {
		$("#user_profile_path_preview").text(this.value);
		});

	$("#quick-login").click(function() {
		$(this).parent().hide();
		$("#quick-login-box").show().find("input[type=text]:first").focus();
		return false;
	});
	
	$("#workout_sport_id").change(function() {
		if (this.options[this.selectedIndex].text == 'Other') {
			$("#workout_description").show();
		}
		else {
			$("#workout_description").hide();
		}
	});
	
	$("#open-datepicker").click(function() {
		$("#inline-datepicker").toggle();
		return false;
	});
	
	$("#inline-datepicker").datepicker({
		firstDay: 1,
		changeFirstDay: false,
		changeMonth: true,
		changeYear: true,
		dateFormat: 'yy-mm-dd',
/*		showOtherMonths: true,*/
		onSelect: function(date) {
			location.href = "?date=" + date;
		}
	});
	
	$("#servings tr.serving").withHovering();
	
	// triggered when servings table should update e.g. to recalculate summed energy
	$("#servings").bind("update", function() {
		consumed_for_groups = ["breakfast", "breakfast-snack", "lunch", "lunch-snack", "dinner", "dinner-snack", "any"];
		columns = ["energy", "protein", "carbohydrate_total", "fat_total", "alcohol"];
		
		// calculate totals for each serving collection
		$("#servings tr.serving-collection").each(function() {
			var servingCollection = this;

			$(columns).each(function(columnIdx, column) {
				columnSum = 0.0;
				
				$(servingCollection).nextAll("." + $(servingCollection).attr("id") + ".serving-collection-item").each(function() {
					columnSum += parseFloat($(this).find("td." + column).attr("value"));
				});
				
				$(servingCollection).find("td." + column).html(Math.round(columnSum));
			});
		});

		// calculate totals for each group
		$(consumed_for_groups).each(function(idx, group) {
			$(columns).each(function(columnIdx, column) {
				columnSum = 0.0;
				$("tbody#servings-" + group + " .serving td." + column).each(function() {
					columnSum += parseFloat($(this).attr("value"));
				});

				$("tbody#servings-" + group + " tr th." + column).html(Math.round(columnSum));
			});
		});
		
		// calculate totals for entire day
		$(columns).each(function(columnIdx, column) {
			columnSum = 0.0;
			$(consumed_for_groups).each(function(idx, group) {
				columnSum += parseFloat($("tbody#servings-" + group + " tr th." + column).html());
			});
			
			$("tfoot tr td." + column).html(Math.round(columnSum));
		});		

		intakeEnergyComposition($("#servings tr.serving"));
	});
	
//	$(".sortable").tablesorter();//{headers: {0: {sorter: false}}});
});

function calculateBodyMassIndex() {
	lbs_to_kg = 0.45359237;
	in_to_cm = 2.54;
	ft_to_cm = 30.48;
	
	weight = parseFloat($("#bmi-calculator input[name='weight']").val() || 0.0);
	height = parseFloat($("#bmi-calculator input[name='height']").val() || 0.0);
	weight_unit = $("#bmi-calculator select[name='weight_unit']").val();
	height_unit = $("#bmi-calculator select[name='height_unit']").val();
	
	if (weight_unit == 'lbs') {
		weight *= lbs_to_kg;
	}
	
	if (height_unit == 'ft') {
		height *= ft_to_cm;
	}
	else if (height_unit == 'in') {
		height *= in_to_cm;
	}
	
	bmi = (weight > 0.0 && weight < 300.0 && height > 0.0 && height < 300.0) ? weight / Math.pow(height / 100.0, 2) : 0.0;
	
	$(".bmi-categories *").removeClass('calculated');
	if (bmi > 0.0 && bmi < 150.0) {
		$("#bmi-result").html(Math.round(bmi * 10) / 10);
		
		if (bmi <= 18.5) {
			$(".bmi-categories .underweight").addClass('calculated');
		}
		else if (bmi > 18.5 && bmi <= 25.0) {
			$(".bmi-categories .normal").addClass('calculated');
		}
		else if (bmi > 25.0 && bmi <= 30.0) {
			$(".bmi-categories .overweight").addClass('calculated');
		}
		else if (bmi > 30.0) {
			$(".bmi-categories .obese").addClass('calculated');
		}
	}
	else {
		$("#bmi-result").html("&nbsp;");
	}
}

function calculateEnergy() {
	protein = parseFloat($("form #food_protein").val() || 0.0);
	carbohydrate_total = parseFloat($("form #food_carbohydrate_total").val() || 0.0);
	fat_total = parseFloat($("form #food_fat_total").val() || 0.0);
	alcohol = parseFloat($("form #food_alcohol").val() || 0.0);
	
	energy = protein * lifestyleapps.density.protein + carbohydrate_total * lifestyleapps.density.carbohydrate + fat_total * lifestyleapps.density.fat + alcohol * lifestyleapps.density.alcohol;
	$("form #calculated-energy").attr("value", Math.round(energy * 10) / 10);
}

// weight/kg
// height/cm
// output: kj
// Using Miffin's formula http://www.ajcn.org/cgi/content/abstract/51/2/241
function calculateDailyEnergy(gender, weight, height, age) {
	return Math.round(kcalToKj(10 * weight + 6.25 * height - 5 * age + ((gender == 'male') ? 5 : -161)));
}

function kcalToKj(kcal) {
	return kcal * 4.184;
}

function intakeEnergyComposition(servings) {
	var graphImageSource = "";
	
	var total_energy = 0.0, total_protein = 0, total_carbohydrate = 0, total_fat = 0, total_alcohol = 0;
	
	servings.each(function() {
		p = parseFloat($(this).find("td.protein").attr("value"));
		c = parseFloat($(this).find("td.carbohydrate_total").attr("value"));
		f = parseFloat($(this).find("td.fat_total").attr("value"));
		a = parseFloat($(this).find("td.alcohol").attr("value"));
		if (isNaN(p) || isNaN(c) || isNaN(f) || isNaN(a)) {
			p = c = f = a = 0;
		}
		
		total_energy += (p * lifestyleapps.density.protein + c * lifestyleapps.density.carbohydrate + f * lifestyleapps.density.fat + a * lifestyleapps.density.alcohol);
		total_protein += p;
		total_carbohydrate += c;
		total_fat += f;
		total_alcohol += a;
	});
	
	total_grams = total_protein + total_carbohydrate + total_fat + total_alcohol;
	protein_percentage = (total_protein / total_grams * 100).toFixed(0);
	carbohydrate_percentage = (total_carbohydrate / total_grams * 100).toFixed(0);
	fat_percentage = (total_fat / total_grams * 100).toFixed(0);
	alcohol_percentage = (total_alcohol / total_grams * 100).toFixed(0);
	
	if (total_grams > 0) {
		graphImageSource = "http://chart.apis.google.com/chart?cht=bhs&chbh=12,2&chs=220x64&chxt=x,y,r&chxl=1:|"+lifestyleapps.messages.alcohol+"|"+lifestyleapps.messages.fat+"|"+lifestyleapps.messages.carbohydrate+"|"+lifestyleapps.messages.protein+"|2:|" + 
			alcohol_percentage + "%|" + fat_percentage + "%|" + carbohydrate_percentage + "%|" + protein_percentage + 
			"%&chxs=0,000000,1,0,_|1,999999,12,-1,_|2,999999,11,1,_&chco=1166FF|66CC11|FFCC11|FF1111&chd=t:" + protein_percentage + "," + carbohydrate_percentage + "," + fat_percentage + "," + alcohol_percentage;
	}

	if (graphImageSource != "") {
		$("body.intake .graph img").attr("src", graphImageSource);
		$("body.intake .graph img").show();
	}
	else {
		$("body.intake .graph img").hide();
	}
}

function setupFoodAutoCompleteField() {
	$("#servings-add").live("click", function() {
		var portion_size = $("input[name=food_portion]:checked").val();
		if (portion_size) {
			$("#serving_size").val(portion_size);
		}
		return true;
	});

	$("#serving_food_name").autocomplete('/foods.json', {
		minChars: 2,
		selectFirst: false,
		max: 50,
		parse: function(data) {
			return $.map(eval(data), function(row) {
				return {
					data: row,
					value: row.food.name,
					result: row.food.name
				}
			});
		},
		formatItem: function(item) {
			if (item.food.food_type == 'food') {
				return "<div class='food_list_item'>" + item.food.name + (item.food.brand ? ' (' + item.food.brand + ')' : '') + " <span class=\"energy\">" + lifestyleapps.energy(item.food) + lifestyleapps.energy_unit + "</span><div class=\"composition\"><span class=\"protein\">" + item.food.protein + lifestyleapps.nutrition_unit + "</span><span class=\"carbohydrate_total\">" + item.food.carbohydrate_total + lifestyleapps.nutrition_unit + "</span><span class=\"fat_total\">" + item.food.fat_total + lifestyleapps.nutrition_unit + "</span></div>" + "</div>";
			}
			else {
				return "<div class='meal_list_item'>" + item.food.name + "</div>";
			}
		}
	}).result(function(e, item) {
		$('#serving_size').val(item.food.serving_size ? item.food.serving_size : 100).select().focus();
		$('#reference_id').val(item.food.id);
		
		if (item.food.food_type == 'food') {
			$('#new_serving').attr('action', '/servings');
			//$("#portions").html("<ul><li><input type=\"radio\" /> 1 skive (50g)</li><li><input type=\"radio\" /> 1 stor skive (100g)</li></ul>");
			
			$.getJSON("/portions.json?id="+item.food.id+"&type=Food", function(data) {
				if (data.length > 0) {
					var portions = "<div style=\"background-color: #ffc\"><ul class=\"portions\">";
					$.each(data, function(i, pitem) {
						dom_id = "portion_" + pitem.portion.id;
						portions += "<li><input type=\"radio\" id=\"" + dom_id + "\" name=\"food_portion\" value=\"" + pitem.portion.weight + "\" /><label for=\"" + dom_id + "\">" + pitem.portion.name + " (" + pitem.portion.weight + lifestyleapps.nutrition_unit + ")</label></li>"
					});
					portions += "</ul> Denne funktion er under udvikling. Valgte maengde vil blive benyttet istedet for indtastede.</div>";
					$("#portions").html(portions);
				}
				else {
					$("#portions").html("");
				}
			});
			
		}
		else {
			$('#new_serving').attr('action', '/serving_collections');
		}
	});
}