﻿KC.Tracker = {
	init: function (print) {
		// style calendar?
		if ($("#calculator-table").size()) {
			KC.Tracker.styleCalendar(print);
		}
		
		if (!print) {
			// bind calendar events
			$("#calculator-table table").bind("click", function (e) {
				var $el = $(e.target);
				switch ($el[0].className) {
					case "flow-image":
						KC.Tracker.showFlowSelector($el);
						break;
					case "add-note":
						KC.Tracker.showNoteEditor($el);
						break;
				}
				e.preventDefault();
			});
			
			$("#calendar-print").bind("click", function (e) {
				KC.Tracker.showPrintDialog(this.className);
				e.preventDefault();
			});
			
			$("#tracker-settings").bind("click", function (e) {
				KC.Tracker.showSettingsEditor();
				e.preventDefault();
			});
			
			$("#print-style-selector select").bind("change", function () {
				KC.Tracker.showPrintPreview(this.value);
			});
		}
		
		// truncate notes to fit in cell
		$(document).bind("ready fontresize", function () {
			$("#calculator-table td p").each(function () {
				KC.Tracker.truncateNote($(this), 60);
			});
		});
		
		// mark "calculated" dates
		$("#calculator-table div.calculated img.flow-image").each(function () {
			this.src = this.src.replace(/\.png$/, "_calculated.png");
		});
	},
	
	showPrintDialog: function (src) {
		var $pd = $("#print-dialog");
		
		if (!$pd.size()) {
			$pd = KC.Tracker.insertPrintDialog();
		}
		
		$pd
			.find("iframe")
				.attr("src", src + ".aspx")
			.end()
			.jqmShow();
	},
	
	insertPrintDialog: function () {
		var options = {modal: true},
			$pd = $('<div id="print-dialog" class="jqmWindow">' +
					'<h3>Print</h3>' +
					'<div>' +
			    	'<iframe src="" frameborder="0"></iframe>' +
			    	'</div>' +
			    	'</div>');
		    		
		// init modal note dialog
		if (!KC.isIE6) {
			options.onShow = function (hash) {
				hash.w.fadeIn("slow");
			};
			options.onHide = function (hash) {
				hash.w.fadeOut("slow", function () {
					hash.o.remove();
				});
			};
		}
		
		$pd
			.appendTo("body")
			.jqm(options);
				
		return $pd;
	},
	
	closePrintDialog: function () {
		$("#print-dialog")
			.find("iframe")
				.attr("src", "about:blank")
			.end()
			.jqmHide();
	},
	
	validatePrintForm: function (form) {
		KC.Tracker.fixInvalidDates();
		
		var $style = $("#ddlStyle");
		
		if (!$style.val()) {
			$style.parent().before('<p class="error">Please select a Print Style.</p>');
			return false;
		}
		
		$("#bSubmit").attr("disabled", "disabled").val("One moment please...")[0].blur();
		$("#btCancel").remove();
		
		form.action = form.action + "?print=" + $style.val(); // for tracking purposes
		
		if (KC.isIE6) {
			form.target = "_blank";
		} else {
			window.open("about:blank", "kotexplannerprint", "width=760,height=600,scrollbars=yes,resizable=yes,menubar=yes").focus();
		}
		
		window.setTimeout(function () {
			parent.KC.Tracker.closePrintDialog();
			return true;
		}, 250);
	},
	
	showPrintPreview: function (v) {
		var $p = $("#print-preview"),
			$i = $("img", $p);
			
		$("p.error").hide("fast", function () {
			$(this).remove();
		});
			
		if ($p.hasClass("calculator")) {
			v += "_calculator";
		}
		
		if (!$i.size()) {
			$i = $('<img/>').appendTo("#print-preview");
		}
		
		$p.fadeIn("fast");
		$i.fadeTo("fast", 0, function () {
			$i.bind("load", function () {
				$i.fadeTo("slow", 1);
				$i.unbind("load");
			}).attr("src", "images/calendar_preview_" + v + ".png");
		});
	},
	
	showFlowSelector: function ($el) {
		var date = $el.parent().attr("id").split("_")[1],
			$fs = $("#flow-selector"),
			p = KC.Util.getElemPosition($el[0]);
			
		if (!$fs.size()) {
			$fs = KC.Tracker.insertFlowSelector();
		}
		
		$fs
			.hide()
			.css({top: (p.y - 69) + "px", left: (p.x - 0) + "px"})
			.data("date", date)
			.data("trigger", $el)
			.fadeIn("fast");
	},
	
	insertFlowSelector: function () {
		var t,
			$fs = $('<div id="flow-selector">' +
					'<img title="heavy flow" class="flow-heavy" src="images/flow_heavy.png"/>' +
					'<img title="medium flow" class="flow-medium" src="images/flow_medium.png"/>' +
					'<img title="light flow" class="flow-light" src="images/flow_light.png"/>' +
					'<img title="no flow" class="flow-off" src="images/flow_off.png"/>' +
					'</div>')
			.appendTo("body")
			.bind("mouseleave", function (e) {
				$this = $(this);
				t = window.setTimeout(function () {
					$this.fadeOut("fast");
				}, 1000);
				
			})
			.bind("mouseenter", function () {
				window.clearTimeout(t);
			})
			.find("img")
				.bind("click", function () {
					KC.Tracker.setFlow($(this));
				})
			.end();
			
		return $fs;
	},
	
	setFlow: function ($el) {
		var date = $el.parent().data("date"),
			$trigger = $el.parent().data("trigger"),
			flows = {
				off: 0,
				light: 1,
				medium: 2,
				heavy: 3
			},
			flow = $el[0].className.split("-")[1];
			
		$el.parent().fadeOut("fast");
			
		$trigger.data("original", $trigger.attr("src"));
			
		if ($el.attr("src") !== $trigger.data("original")) { // only process request if status was changed
			$.ajax({
				beforeSend: function () {
					$trigger.attr("src", "images/loading_tracker.gif");
				},
				cache: false,
				data: {
					trackerDate: date,
					status: flows[flow]
				},
				error: function (XMLHttpRequest, textStatus, errorThrown) {
					$trigger.attr("src", $trigger.data("original"));
					alert("Unable to process your request. Please try again in a moment.");
				},
				success: function (data, textStatus) {
					if ($("Success", data).text() === "true") {
						// show selected status
						$trigger.attr("src", "images/flow_" + flow + ".png");
					
						// remove "calculated" dates
						$("#calculator-table div.calculated img.flow-image").each(function () {
							this.src = "images/flow_off.png";
							$(this).parent().removeClass("calculated");
						});
						
						// show "recalculate" link
						$("#recalculate").fadeIn("fast");
						
					} else {
						$trigger.attr("src", $trigger.data("original"));
						alert($("Message", data).text());
					}
				},
				type: "POST",
				url: "TrackerService.asmx/SetTrackerStatus"
			});
		}
	},
	
	showNoteEditor: function ($el) {
		var date = $el.parent().attr("id").split("_")[1],
			note = $el.siblings("p").data("note") || "",
			$ne = $("#note-editor");
			
		if (!$ne.size()) {
			$ne = KC.Tracker.insertNoteEditor();
		}
			
		$ne
			.data("date", date)
			.find("h3 span")
				.text(date)
			.end()
			.find("textarea")
				.val(note.replace(/<br\/?>/ig, "\n"))
			.end()
			.jqmShow();
	},
	
	insertNoteEditor: function () {
		var options = {modal: true},
			$ne = $('<div id="note-editor" class="jqmWindow">' +
					'<h3>Notes for <span>DATE</span></h3>' +
					'<div>' +
			    	'<p>Enter a note for this day.</p>' +
			    	'<p><textarea></textarea></p>' +
			    	'<p style="text-align: right;zoom: 1;"><button onclick="KC.Tracker.saveNote();">Save</button>&nbsp;&nbsp;&nbsp;&nbsp;' +
			    	'<button onclick="KC.Tracker.cancelNote();">Cancel</button></p>' +
			    	'</div>' +
			    	'</div>');
		    		
		// init modal note dialog
		if (!KC.isIE6) {
			options.onShow = function (hash) {
				hash.w.fadeIn("slow");
			};
			options.onHide = function (hash) {
				hash.w.fadeOut("slow", function () {
					hash.o.remove();
				});
			};
		}
		
		$ne
			.appendTo("body")
			.jqm(options)
			.find("textarea")
				.charCounter(4000);
				
		return $ne;
	},
	
	saveNote: function () {
		var $ne = $("#note-editor"),
			date = $ne.data("date"),
			$el = $("#d_" + date),
			note = $ne.find("textarea").val();
			
		note = $.trim(note).replace(/<[^>]+>/g, "").replace(/\n/g, "<br/>"); // strip HTML and convert line breaks to <br/> tags
		
		if ($el.find("p").size()) { // editing an existing note
			$el = $el.find("p");
		} else { // adding a new note
			$el = $("<p></p>").prependTo($el);
		}
		
		$.ajax({
			cache: false,
			data: {
				trackerDate: date,
				notes: note
			},
			error: function (XMLHttpRequest, textStatus, errorThrown) {
				alert("Unable to process your request. Please try again in a moment.");
			},
			success: function (data, textStatus) {
				if ($("Success", data).text() === "true") {
					$el.data("note", note);
					KC.Tracker.truncateNote($el, 60);
				} else {
					$el.remove();
					alert($("Message", data).text());
				}
			},
			type: "POST",
			url: "TrackerService.asmx/SetTrackerNote"
		});
		
		$ne.jqmHide();
	},
	
	cancelNote: function () {
		$("#note-editor").jqmHide();
	},
	
	showSettingsEditor: function () {
		var $se = $("#settings-editor");
			
		if (!$se.size()) {
			$se = KC.Tracker.insertSettingsEditor();
		}
			
		$se
			.find("iframe")
				.attr("src", "TrackerSettings.aspx")
			.end()
			.jqmShow();
	},
	
	insertSettingsEditor: function () {
		var options = {modal: true},
			$se = $('<div id="settings-editor" class="jqmWindow">' +
					'<h3>Personal Period Tracker Settings</h3>' +
					'<div>' +
			    	'<iframe src="" frameborder="0"></iframe>' +
			    	'</div>' +
			    	'</div>');
		    		
		// init modal note dialog
		if (!KC.isIE6) {
			options.onShow = function (hash) {
				hash.w.fadeIn("slow");
			};
			options.onHide = function (hash) {
				hash.w.fadeOut("slow", function () {
					hash.o.remove();
				});
			};
		}
		
		$se
			.appendTo("body")
			.jqm(options);
				
		return $se;
	},
	
	closeSettingsEditor: function (reload) {
		$("#settings-editor")
			.find("iframe")
				.attr("src", "about:blank")
			.end()
			.jqmHide();
		
		if (reload) {
			location.href = location.href;
		}
	},
	
	styleCalendar: function (print) {
		var $tr;
		$("#calculator-table table").each(function () {
			$tr = $(this).find("tr");
			if ($tr.eq(6).find("td:empty").size() === 7) {
				$tr.eq(6).remove();
			}
			if ($tr.eq(5).find("td:empty").size() === 7) {
				$tr.eq(5).remove();
			}
		});
		
		$("#calculator-table td:empty").addClass("empty").html("<div><span>--</span></div>");
		
		if (print) {
			$(".flow-image").attr({alt: "", title: ""});
		}
	},
	
	truncateNote: function ($el, height) {
		var truncated = false, el = $el[0];
		
		if (typeof $el.data("note") === "undefined") {
			$el.data("note", $el.html()); // preserve complete note on page load (with HTML tags) for editing/printing/tooltip
		}
		
		$el.text($el.data("note").replace(/<br\/?>/ig, " ")); // convert <br> tags to spaces for display on calendar
		
		window.setTimeout(function () { // delay this slightly to prevent "unresponsive script" errors in IE6/7
			while (el.offsetHeight > height) {
				$el.text($el.text().slice(0,-2));
				truncated = true;
			}
			
			if (truncated) {
				$el.text($el.text().slice(0,-3) + " …").css("cursor", "help");
				KC.Tracker.makeTooltip($el, "<strong>" + $el.parent().attr("id").split("_")[1] + "</strong><br />" + $el.data("note"));
			}
			
			$el.css("visibility", "visible");
		}, 10);
	},
	
	makeTooltip: function ($el, text) {
		var $tooltip, t;
		
		$el.hover(function (e) {
			window.clearTimeout(t);		
			t = window.setTimeout(function () {							  
				$("body").append("<p id='tooltip'>"+ text +"</p>");
				$tooltip = $("#tooltip")
					.css("top",(e.pageY - 10) + "px")
					.css("left",(e.pageX + 30) + "px")
					.css({opacity: 0, display: "block"});
				$tooltip.fadeTo("fast", 0.9, function () {
					$el.trigger("mousemove");
				});
			}, 200);
	    },
		function () {
			window.clearTimeout(t);
			if ($tooltip) {
				t = window.setTimeout(function () {
					$tooltip.remove();
					$tooltip = null;
				}, 200);
			}
	    });	
	    
		$el.mousemove(snap);
		
		function snap (e) {
			if ($tooltip) {
				$tooltip
					.css("top",(e.pageY - 10) + "px")
					.css("left",(e.pageX + 30) + "px");
				keepInViewport();
			}
		}
		
		function keepInViewport () {
			// ensure tooltip doesn't extend beyond viewport edges
			var p, s, o, top, height, left, width, tt = $tooltip[0];
			p = KC.Util.getElemPosition(tt);
			s = KC.Util.getViewportSize();
			o = KC.Util.getScrollOffset();
			
			left = p.x;
			top = p.y;
			width = tt.offsetWidth;
			height = tt.offsetHeight;
			
			if (left + width > s.x + o.x) {
				$tooltip.css({left: (left - width - 40) + "px"});
			}
			
			if (top + height > s.y + o.y) {
				$tooltip.css({top: (top - height - 5) + "px"});
			}
		}
	},
	
	insertDatePicker: function (id, fm, fd, fy, options) {
		var $this, t = null;
		
		options = options || {createButton: false};
		
		function updateSelects (selectedDate) {
			if (selectedDate) {
				selectedDate = new Date(selectedDate);
				var d = selectedDate.getDate();
				var m = selectedDate.getMonth();
				var y = selectedDate.getFullYear();
				($('#' + fd)[0]).value = d;
				($('#' + fm)[0]).value = m + 1;
				($('#' + fy)[0]).value = y;
			}
		}
		
		function checkForMouseout (event) {
			var el = event.target;
			
			while (true) {
				if (el == cal) {
					if (t) {
						window.clearTimeout(t);
					}
					return true;
				} else if (el == document) {
					t = window.setTimeout(function () {
						$this.dpClose();
						$(document).unbind(
							'mouseover.datepicker',
							checkForMouseout
						);
						return false;
					}, 1000);
					return true;
				} else {
					el = $(el).parent()[0];
				}
			}
		}
	    		
		$('<img id="' + id + '" src="' + options.icon + '" alt="" />').insertAfter($('#' + fy));
		
		// initialise the "Select date" link
		$('#' + id)
			.datePicker(options)
			.bind(
				// when the link is clicked display the date picker
				'click',
				function () {
					updateSelects($(this).dpGetSelected()[0]);
					$(this).dpDisplay();
					return false;
				}
			).bind(
				// when a date is selected update the SELECTs
				'dateSelected',
				function (e, selectedDate, $td, state) {
					updateSelects(selectedDate);
				}
			).bind(
				'dpDisplayed',
				function (event, datePickerDiv) {
					cal = datePickerDiv;
					$this = $(this);
					$(document).bind(
						'mouseover.datepicker',
						checkForMouseout
					);
				}
			).bind(
				'dpClosed',
				function (e, selected) {
					updateSelects(selected[0]);
				}
			);
		
		// listen for when the selects are changed and update the picker
		$('#' + fd + ', #' + fm + ', #' + fy)
			.bind(
				'change',
				function() {
					var d = new Date(
								$('#' + fy).val(),
								$('#' + fm).val()-1,
								$('#' + fd).val()
							);
					$('#' + id).dpSetSelected(d.asString());
				}
			);
		
		if (options.selectToday || options.initial) {
			// default the position of the selects
			var d = (options.selectToday) ? new Date() : options.initial; // options.initial should be a Date object
			($('#' + fd)[0]).value = d.getDate();
			($('#' + fm)[0]).value = d.getMonth() + 1;
			($('#' + fy)[0]).value = d.getFullYear();
			
			// and update the datePicker to reflect it...
			$('#' + fd).trigger('change');
		}
	},
	
	fixInvalidDates: function () {
		// use the datepicker built-in methods to "fix" (wraparound) any invalid dates (e.g., Feb 30th)
		$(".dp-applied").each(function () {
			var $this = $(this);
			$this.triggerHandler('click');
			$this.dpClose();
		});
	}
};