(function($){
	Date.prototype.getDayExt = function(Full) {
		var Exts = [[jsTranslate("Sun"), jsTranslate("Sunday")], [jsTranslate("Mon"), jsTranslate("Monday")], [jsTranslate("Tue"), jsTranslate("Tuesday")], [jsTranslate("Wed"), jsTranslate("Wednesday")], [jsTranslate("Thu"), jsTranslate("Thursday")], [jsTranslate("Fri"), jsTranslate("Friday")], [jsTranslate("Sat"), jsTranslate("Saturday")]];
		return Exts[this.getDay()][(Full) ? 1 : 0];
	}

	Date.prototype.getMonthExt = function(Full) {
		var Exts = [[jsTranslate("Jan"), jsTranslate("January")], [jsTranslate("Feb"), jsTranslate("February")], [jsTranslate("Mar"), jsTranslate("March")], [jsTranslate("Apr"), jsTranslate("April")], [jsTranslate("May"), jsTranslate("May")], [jsTranslate("Jun"), jsTranslate("June")], [jsTranslate("Jul"), jsTranslate("July")], [jsTranslate("Aug"), jsTranslate("August")], [jsTranslate("Sep"), jsTranslate("September")], [jsTranslate("Oct"), jsTranslate("October")], [jsTranslate("Nov"), jsTranslate("November")], [jsTranslate("Dec"), jsTranslate("December")]];
		return Exts[this.getMonth()][(Full) ? 1 : 0];
	}

	Date.prototype.getOrdinalSuffix = function() {
		return (this.getDate() == 1 || this.getDate() == 21 || this.getDate() == 31) ? "st" : ((this.getDate() == 2 || this.getDate() == 22) ? "nd" : ((this.getDate() == 3 || this.getDate() == 23) ? "rd" : "th"));
	}

	Date.prototype.getLongDate = function() {
		return this.getDayExt(true) + " " + this.getDate() + this.getOrdinalSuffix() + " " + this.getMonthExt(true) + " " + this.getFullYear();
	}

	Date.prototype.get12Hours = function() {
		var hour = (this.getHours() > 12) ? this.getHours() - 12 : this.getHours();
		if (hour == 0) {
			return "12 AM";
		} else if (hour == 12) {
			return "Noon";
		} else if (this.getHours() == 23) {
			return "11 PM";
		}
		return hour;
	};

	var events = [];

	var publicMethods = {
		dbLookup: function(date) {
			var startDate = new Date(date);
			startDate.setHours(0);
			startDate.setMinutes(0);
			startDate.setSeconds(0);
			var endDate = new Date(date);
			endDate.setHours(23);
			endDate.setMinutes(59);
			endDate.setSeconds(59);

			var recipientsGetLink = "";
			$(".user").each(function() {
				recipientsGetLink += "&recipients[]=" + $(this).text();
			});

			$.ajax({
				type: "GET",
				url: input_url + "index.php/mail/calendar/caldavglue?func=freebusy&json=1" + recipientsGetLink + "&start=" + Math.round(startDate.getTime() / 1000) + "&end=" + Math.round(endDate.getTime() / 1000),
				dataType: "json",
				success: function(json) {
					var il = json.length;
					for (var i = 0; i < il; i ++) {
						$(this).scheduler("addEvent", json[i].id, json[i].user, new Date(json[i].start * 1000), Math.abs(json[i].end - json[i].start) / 60, json[i].color);
					}
				}
			});
		},
		userExists: function(userName) {
			var doesExists = false;
			$(".userListBorder").children().each(function() {
				if (userName == $(this).text()) doesExists = true;
			});
			return doesExists;
		},
		addUser: function(userName) {
			$(".userListBorder").children(":last").css("border-bottom", "1px solid #d3dbe2");
			$(".userListBorder").append("<div class=\"user\">" + userName + "</div>");
			$(".eventColumn").each(function() {
				$(this).children(":last").css("border-bottom", "1px solid #d3dbe2");
			});
			$(".eventColumn").each(function() {
				$(this).append("<div class=\"eventSlot\">&nbsp;</div>");
				$(this).children(":last").data("userName", userName);
			});
		},
		deleteUser: function(userName) {
			$(".userListBorder").children(":last").css("border-bottom", "1px solid #d3dbe2");
			$(".userListBorder").children().each(function() {
				if ($(this).text() == userName) $(this).remove();
			});
			$(".eventColumn").each(function() {
				$(this).children(":last").css("border-bottom", "1px solid #d3dbe2");
			});
			$(".eventColumn").each(function() {
				$(this).children().each(function() {
					if ($(this).data("userName") == userName) $(this).remove();
				});
			});
		},
		addEvent: function(id, userName, dateStart, lengthMin, color) {
			var il = events.length;
			for (var i = 0; i < il; i ++) {
				if (events[i][0] == id) {
					$(this).scheduler("deleteEvent", id);
					break;
				}
			}

			events.push([id, userName, dateStart, lengthMin, color]);

			$(this).scheduler("renderEvent", id);
		},
		updateEvent: function(id, userName, dateStart, lengthMin, color) {
			$(this).scheduler("deleteEvent", id);
			$(this).scheduler("addEvent", id, userName, dateStart, lengthMin, color);
		},
		deleteEvent: function(id) {
			var il = events.length;
			for (var i = 0; i < il; i ++) {
				if (events[i][0] == id) {
					events.splice(i, 1);
					break;
				}
			}
			$(this).scheduler("renderEvent", id);
		},
		renderEvent: function(id) {
			var eventIndex = null;

			var il = events.length;
			for (var i = 0; i < il; i ++) {
				if (events[i][0] == id) {
					eventIndex = i;
					break;
				}
			}

			if (eventIndex === null) {
				$("#event_" + id).parent().empty();
			} else {
				var userName = events[eventIndex][1];
				var dateStart = events[eventIndex][2];
				var lengthMin = events[eventIndex][3];
				var color = events[eventIndex][4];
// Need to update Scheduler to support any hex colour!
				var color = "red";

				$(".timeSliderBox").children().each(function() {
					if ($(this).data("slotDate").getLongDate() == dateStart.getLongDate()) {
						var userIndex = 0;
						$(".user").each(function() {
							if ($(this).text() == userName) {
								return false;
							}
							userIndex ++;
						});

						var blockLength = (dateStart.getMinutes() + lengthMin) / 60;

						for (var i = 0; i < Math.ceil(blockLength); i ++) {
							$(this).children(":eq(" + (dateStart.getHours() + i) + ")").children(":last").children(":eq(" + userIndex + ")").empty();
							$(this).children(":eq(" + (dateStart.getHours() + i) + ")").children(":last").children(":eq(" + userIndex + ")").append("<div id=\"event_" + id + "\" class=\"eventBox eventBox" + color.toUpperCase() + "\">&nbsp;</div>");

							if (i == 0 && dateStart.getMinutes() > 0) {
								$(this).children(":eq(" + (dateStart.getHours() + i) + ")").children(":last").children(":eq(" + userIndex + ")").children(":first").css("position", "relative");
								$(this).children(":eq(" + (dateStart.getHours() + i) + ")").children(":last").children(":eq(" + userIndex + ")").children(":first").css("width", (46 - Math.ceil((dateStart.getMinutes() / 60) * 46)) + "px");
								$(this).children(":eq(" + (dateStart.getHours() + i) + ")").children(":last").children(":eq(" + userIndex + ")").children(":first").css("left", Math.ceil((dateStart.getMinutes() / 60) * 46) + "px");
							} else if (i == Math.ceil(blockLength) - 1 && blockLength - i < 1) {
								$(this).children(":eq(" + (dateStart.getHours() + i) + ")").children(":last").children(":eq(" + userIndex + ")").children(":first").css("width", (46 - Math.ceil((blockLength - i) * 46)) + "px");
							}
						}
					}
				});
			}
		}
	};

	$.fn.scheduler = function(method) {
		if (publicMethods[method]) {
			return publicMethods[method].apply(this, Array.prototype.slice.call(arguments, 1));
		} else if (typeof(method) === "object" || !method) {
			var slotDate = (method.selectedDate) ? method.selectedDate : new Date();
			slotDate.setHours(0, 0, 0, 0);

			$("#availabilityHeader").append("<div class=\"dayHeader\">" + slotDate.getLongDate() + "</div>");
			$(this).append("<div class=\"dayBox\"><div class=\"timeBox insideLeftShadow\"><div class=\"userListBox\"><div class=\"userList\"><div class=\"userListBorder\"></div></div></div><div class=\"timeSlider insideTopShadow\"><div class=\"timeSliderBox\"></div></div></div></div>");

			$(".timeSliderBox").append("<div class=\"time24hrSlot\" style=\"width: 1177px;\"></div>");
			$(".timeSliderBox").children(":first").data("slotDate", slotDate);

			for (var i = 0; i < 24; i ++) {
				slotDate.setHours(i);
				$(".timeSliderBox").children(":first").append("<div class=\"timeSlot\"" + ((i == 0) ? " style=\"border-left: 0px;\"" : "") + "><div class=\"eventHeader\"" + ((i == 0) ? " style=\"border-left: 1px solid white;\"" : ((i == 23) ? " style=\"border-right: 1px solid white;\"" : "")) + ">" + slotDate.get12Hours() + "</div><div class=\"eventColumn\"></div></div>");
			}

			$(".timeSliderBox").children(":first").append("<div class=\"timeShadeNight1\"></div>");
			$(".timeSliderBox").children(":first").append("<div class=\"timeShadeDay\"></div>");
			$(".timeSliderBox").children(":first").append("<div class=\"timeShadeNight2\"></div>");
			$(".timeSliderBox").children(":first").append("<div class=\"timeShadeBizHrs\"></div>");

			$(this).scheduler("dbLookup", new Date(slotDate));

			$(".timeSlider").scrollLeft(($(".timeSliderBox").width() - $(".timeSlider").width()) / 2);

			$(".timeSlider").scroll(function() {
				if (this.scrollLeft == 0) {
					this.scrollLeft = 100;
					$(".timeSliderBox").children(":first").children(":first").css("border-left", "1px solid #d3dbe2");
					$(".timeSliderBox").children(":first").children(":first").children(":first").css("border-left", "0px");

					slotDate = new Date(
						$(".timeSliderBox").children(":first").data("slotDate").getFullYear(),
						$(".timeSliderBox").children(":first").data("slotDate").getMonth(),
						$(".timeSliderBox").children(":first").data("slotDate").getDate() - 1
					);

					$(".timeSliderBox").prepend("<div class=\"time24hrSlot\" style=\"width: 1176px;\"></div>");

					$(".timeSliderBox").children(":first").data("slotDate", slotDate);

					var newHeader = $(".timeSliderBox").children(":first").data("slotDate").getLongDate();
					if (newHeader != $(".dayHeader").contents().text()) {
						$(".dayHeader").empty();
						$(".dayHeader").append(newHeader);
					}

					slotDate.setHours(23);
					for (var i = 23; i >= 0; i --) {
						slotDate.setHours(i);
 						$(".timeSliderBox").children(":first").prepend("<div class=\"timeSlot\"" + ((i == 0) ? " style=\"border-left: 0px;\"" : "") + "><div class=\"eventHeader\"" + ((i == 0) ? " style=\"border-left: 1px solid white;\"" : "") + ">" + slotDate.get12Hours() + "</div><div class=\"eventColumn\"></div></div>");

						for (var x = 0; x < $(".userListBorder").children().length; x ++) {
							$(".timeSliderBox").children(":first").children(":first").children(":last").children(":last").css("border-bottom", "1px solid #d3dbe2");
							$(".timeSliderBox").children(":first").children(":first").children(":last").append("<div class=\"eventSlot\">&nbsp;</div>");
						}
					}

					$(".timeSliderBox").children(":first").append("<div class=\"timeShadeNight1\"></div>");
					$(".timeSliderBox").children(":first").append("<div class=\"timeShadeDay\"></div>");
					$(".timeSliderBox").children(":first").append("<div class=\"timeShadeNight2\"></div>");
					$(".timeSliderBox").children(":first").append("<div class=\"timeShadeBizHrs\"></div>");

					if ($(".timeSliderBox").children().length > 4) $(".timeSliderBox").children(":last").remove();

					$(".timeSliderBox").css("width", (49 * ($(".timeSliderBox").children().length * 24) + 1) + "px");

					$(".eventColumn").bind("mousewheel", function(event, delta) {
						$(".userList").scrollTop((delta > 0) ? $(".userList").scrollTop() - 10 : $(".userList").scrollTop() + 10);
						return false;
					});

					var il = events.length;
					for (var i = 0; i < il; i ++) {
						if (events[i][2].getLongDate() == slotDate.getLongDate()) $(this).scheduler("renderEvent", events[i][0]);
					}

					$(this).scheduler("dbLookup", new Date(slotDate));
				} else if (this.scrollLeft == ($(".timeSliderBox").width() - $(".timeSlider").width())) {
					this.scrollLeft = ($(".timeSliderBox").width() - $(".timeSlider").width()) - 100;
					$(".timeSliderBox").children(":last").children(":last").prev().prev().prev().prev().children(":first").css("border-right", "0px");
					$(".timeSliderBox").children(":last").css("width", "1176px");

					slotDate = new Date(
						$(".timeSliderBox").children(":last").data("slotDate").getFullYear(),
						$(".timeSliderBox").children(":last").data("slotDate").getMonth(),
						$(".timeSliderBox").children(":last").data("slotDate").getDate() + 1
					);

					$(".timeSliderBox").append("<div class=\"time24hrSlot\" style=\"width: 1177px;\"></div>");

					$(".timeSliderBox").children(":last").data("slotDate", slotDate);

					var newHeader = $(".timeSliderBox").children(":last").data("slotDate").getLongDate();
					if (newHeader != $(".dayHeader").contents().text()) {
						$(".dayHeader").empty();
						$(".dayHeader").append(newHeader);
					}

					slotDate.setHours(0);
					for (var i = 0; i < 24; i ++) {
						slotDate.setHours(i);
 						$(".timeSliderBox").children(":last").append("<div class=\"timeSlot\"><div class=\"eventHeader\"" + ((i == 24) ? " style=\"border-right: 1px solid white;\"" : "") + ">" + slotDate.get12Hours() + "</div><div class=\"eventColumn\"></div></div>");

						for (var x = 0; x < $(".userListBorder").children().length; x ++) {
							$(".timeSliderBox").children(":last").children(":last").children(":last").children(":last").css("border-bottom", "1px solid #d3dbe2");
							$(".timeSliderBox").children(":last").children(":last").children(":last").append("<div class=\"eventSlot\">&nbsp;</div>");
						}
					}

					$(".timeSliderBox").children(":last").append("<div class=\"timeShadeNight1\"></div>");
					$(".timeSliderBox").children(":last").append("<div class=\"timeShadeDay\"></div>");
					$(".timeSliderBox").children(":last").append("<div class=\"timeShadeNight2\"></div>");
					$(".timeSliderBox").children(":last").append("<div class=\"timeShadeBizHrs\"></div>");

					if ($(".timeSliderBox").children().length > 4) $(".timeSliderBox").children(":first").remove();

					$(".timeSliderBox").css("width", (49 * ($(".timeSliderBox").children().length * 24) + 1) + "px");

					$(".eventColumn").bind("mousewheel", function(event, delta) {
						$(".userList").scrollTop((delta > 0) ? $(".userList").scrollTop() - 10 : $(".userList").scrollTop() + 10);
						return false;
					});
					var il = events.length;
					for (var i = 0; i < il; i ++) {
						if (events[i][2].getLongDate() == slotDate.getLongDate()) $(this).scheduler("renderEvent", events[i][0]);
					}

					$(this).scheduler("dbLookup", new Date(slotDate));
				} else {
					var newHeader = $(".timeSliderBox").children(":eq(" + (Math.ceil((this.scrollLeft + ($(".timeSlider").width() / 2)) / 1176) - 1) + ")").data("slotDate").getLongDate();
					if (newHeader != $(".dayHeader").contents().text()) {
						$(".dayHeader").empty();
						$(".dayHeader").append(newHeader);
					}
				}
			});

			$(".userList").scroll(function() {
				$(".eventColumn").scrollTop(this.scrollTop);
			});

			$(".eventColumn").bind("mousewheel", function(event, delta) {
				$(".userList").scrollTop((delta > 0) ? $(".userList").scrollTop() - 10 : $(".userList").scrollTop() + 10);
				return false;
			});

			return $;
		} else {
			$.error("Method " +  method + " does not exist on jQuery.scheduler");
		}
	};
})(jQuery);