var Calendar = function(dom){

	c = this;
	this.create_event_btn = $("#create_event_btn");
	this.event_create_space = $("#event_create_space");
	this.title = $("#current_title");
	this.calendar = $(dom);
	this.nextBtn = $("#next_month_btn");
	this.prevBtn = $("#prev_month_btn");
	this.todayBtn = $("#today_btn");
	this.modeBtns = $(".calendar_mode button");
	this.refreshBtn = $("#refresh_btn");
	this.dialog = new EventDialog(c);
	this.loading = $('#calendar-loading');
	this.success_event = null;
	this.agenda_space = $("#calendar_agenda");
	this.currentView = "month";
	this.navigation = $("#navigation");
	this.rangeSelection = $("#range_selection");
	var agendaView = new AgendaView(c);
	var loadeventsonviewchange = false;

	this.initialize = function(){
		var date = new Date();
		var d = date.getDate();
		var m = date.getMonth();
		var y = date.getFullYear();
		var change_event = function(_event, delta) {
			_event.end = (_event.end ? _event.end : _event.start);
			var s = $.fullCalendar.parseDate(c.calendar.find(".fc-view table tbody td:first").data("date"));
			var e = $.fullCalendar.parseDate(c.calendar.find(".fc-view table tbody td:first").data("date"));
			$.ajax({
				url: "/panel/calendar_new/back_end/events/"+_event.id+'.json',
				data: {event:{id:_event.id,start:_event.start,end: _event.end,_s:Math.round(+s / 1000), _e:Math.round(+e / 1000)}},
				type: 'put' ,
				datatype: 'JSON',
				error: function(jqXHR, textStatus, errorThrown) {},
			    success: function(data) {
			      console.log('event was success updated');
			    }
			});
		}
		var success_event = function(data,allDay,type){
			c.event_create_space.html(data).show();
			var dtpick = $('.datetimepick');
			var pickers = new Array();
			var checked = ($("#all_day_check").is(":checked") ? true : false);
			var checked_function = function(c){
				if(c){
					for(i in pickers){
						var input = pickers[i].find("input");
						input.val(input.val().split(" ")[0]);
					}
				}else{
					for(i in pickers){
						var d = new Date();
						var input = pickers[i].find("input");
						if(input.val())
							input.val(input.val() + " " + d.getHours() + ":" + d.getMinutes());
					}
				}
			} 
			var repeat_function = function(){
				if(c.event_create_space.find("#event_period").val() == c.event_create_space.find("#event_period option:eq(0)").val()){
					c.event_create_space.find("#event_frequency").attr("disabled","disabled");
				}else{
					c.event_create_space.find("#event_frequency").removeAttr("disabled");
				}
			}
			dtpick.each(function() {
				var $data = $(this).data();
				var options = {
			    		format: $data.dateFormat,
        				pickTime: $data.picktime,
        				language: $data.language,
        				place: "top"
        			}
			    pickers.push(
			    	$(this).datetimepicker(options)
			    );
			});
			$("a.btn-close").one("click",function(){
				c.event_create_space.html("").hide();
				return false;
			});
			$("#all_day_check").click(function(){
				if($(this).is(":checked")){
					checked = true;
				}else{
					checked = false;
				}
				checked_function(checked);
			});
			$("#recurring_checkbox").click(function(){
				if($(this).is(":checked"))
					$("#recurring_panel").show();
				else
					$("#recurring_panel").hide();

			})
			$('form[data-remote]').bind("ajax:success",function(evt, data, status){
				c.event_create_space.html("").hide();
				if(type == "new")
					c.renderEvent(data);
				if(type == "edit")
					c.calendar.fullCalendar("refetchEvents");
			});
			c.event_create_space.find("#event_period").change(function(){
				repeat_function();
			})
			for(i in pickers){
				pickers[i].on("changeDate",function(e){
					if(checked){
						var input = $(this).find("input");
						input.val(input.val().split(" ")[0]);
					}
				})
			}
			repeat_function();
			if(allDay)
				checked_function(checked);
		}
		c.success_event = success_event;
		var dview = (c.currentView == "agenda" ? "month" : c.currentView);
		c.calendar.fullCalendar({
			editable: true,
			selectable: true,
			events: "/panel/calendar_new/back_end/events/",
			eventResize: change_event,
			eventDrop: change_event ,
			header: false,
			default: dview,
			height: $("body").height() - 141,
			loading: function(bool) {
				if (bool) c.loading.css("left",($(window).width()/2 - 60) + "px").show();
				else c.loading.hide();
			},
			windowResize : function(view){
				view.setHeight($("body").height() - 141);
				c.calendar.fullCalendar("refetchEvents");
			},
			viewDisplay: function(view) {
        		c.title.html(view.title);
    		},
    		eventClick: function(calEvent, e, view) {
    			c.dialog.dismiss();
    			c.dialog.inflate(calEvent);
    			c.dialog.show({"x":e.originalEvent.clientX,"y":e.originalEvent.clientY});
    		},
    		select : function(startDate, endDate, allDay, jsEvent, view){
    			var start = new Date(startDate),
					end = new Date(endDate),
					startString = start.getFullYear() + "/"+ (start.getMonth() + 1 > 9 ? start.getMonth() + 1 : "0" + (start.getMonth() + 1)) + "/" + (start.getDate() > 9 ? start.getDate() : "0" + start.getDate()),
					endString = end.getFullYear() + "/" + (end.getMonth() + 1 > 9 ? end.getMonth() + 1 : "0" + (end.getMonth() + 1)) + "/" + (end.getDate() > 9 ? end.getDate() : "0" + end.getDate());

					if(!allDay){
						startString += " " + (start.getHours() > 9 ? start.getHours() : "0" + start.getHours()) + ":" + (start.getMinutes() > 9 ? start.getMinutes() : "0" + start.getMinutes()); 
						endString += " " + (end.getHours() > 9 ? end.getHours() : "0" + end.getHours()) + ":" + (end.getMinutes() > 9 ? end.getMinutes() : "0" + end.getMinutes()); 
					}else{
						startString += " " + start.getHours() + ":" + start.getMinutes(); 
						endString += " " + end.getMinutes() + ":" + end.getMinutes(); 
					}
				
    			$.ajax({
    				type : "get",
    				url : c.create_event_btn.attr("href"),
    				data : {"startDate":startString,"endDate":endString,"allDay":allDay},
    				success : function(data){
    					success_event(data,allDay,"new");
    				}
    			})
    		}
		});
		c.create_event_btn.click(function(){
			if(!c.isFormVisible()){
				
				$.ajax({
					type : "get",
					url : $(this).attr("href"),
					success : function(data){
						success_event(data,false,"new");
					}
				})
			}
			return false;
		});
		c.nextBtn.click(function(){
			c.dialog.dismiss();
			c.calendar.fullCalendar('next');
		});
		c.prevBtn.click(function(){
			c.dialog.dismiss();
			c.calendar.fullCalendar('prev');
		});
		c.todayBtn.click(function(){
			c.dialog.dismiss();
			c.calendar.fullCalendar('today');
		});
		c.modeBtns.click(function(){
			c.dialog.dismiss();
			toggleViews($(this).data("mode"));
		});
		c.refreshBtn.click(function(){
			c.dialog.dismiss();
			if(c.currentView == "agenda")
				agendaView.refresh();
			else
				c.calendar.fullCalendar("refetchEvents");
		});

		var toggleViews = function(view){
			c.modeBtns.removeClass("active");
			c.modeBtns.each(function(){
				if ($(this).data("mode") == view)
					$(this).addClass("active");
			})
			if(view != "agenda"){
				if(c.currentView == "agenda"){
					$("#sec1").addClass("span3").removeClass("span7");
					$("#sec2").show();
					$("#sec3").addClass("span4").removeClass("span5");
					agendaView.hide();
				}
				c.calendar.fullCalendar('changeView',view);
			}else{
				$("#sec1").addClass("span7").removeClass("span3");
				$("#sec2").hide();
				$("#sec3").addClass("span5").removeClass("span4");
				agendaView.inflate();
			}
			c.currentView = view;
			if(loadeventsonviewchange){
				c.calendar.fullCalendar("refetchEvents");
				loadeventsonviewchange = false;
			}
		}
		if(c.currentView == "agenda"){toggleViews("agenda");loadeventsonviewchange = true;}
		 $(document).on("DOMMouseScroll mousewheel", function(e){
		 	if(c.calendar.fullCalendar("getView").name == "month"){
		 		if(!c.isFormVisible()){
			 		c.dialog.dismiss();
				 	if(/Firefox/i.test(navigator.userAgent)){
				 		if(e.originalEvent.detail == 1){
				    		c.calendar.fullCalendar('next');
				    	}else if(e.originalEvent.detail == -1){
				    		c.calendar.fullCalendar('prev');
				    	}
				 	}else{
				 		if(e.originalEvent.wheelDelta /120 > 0)
				 			c.calendar.fullCalendar('prev');
				 		else
				 			c.calendar.fullCalendar('next');
				 	}
				 }
		 	}
		 });

	}

	this.isFormVisible = function(){
		return (c.event_create_space.html() == "" ? false : true);
	}

	this.renderEvent = function(eventStick){
		if(eventStick.recurring == true)
			c.calendar.fullCalendar("refetchEvents");
		else
			c.calendar.fullCalendar("renderEvent",eventStick);
	}

	this.updateEvent = function(eventStick){
		c.calendar.fullCalendar("updateEvent",eventStick);
	}

	this.deleteEvent = function(delete_url,_id){
		$.ajax({
			type : "delete",
			url : delete_url,
			success : function(){
				c.calendar.fullCalendar("removeEvents",[_id]);
				c.dialog.dismiss();
			}
		})
	}

	this.editEvent = function(edit_url,allDay){
		console.log(edit_url);
		$.ajax({
			type : "get",
			url : edit_url,
			success : function(data){
				c.success_event(data,allDay,"edit");
				c.dialog.dismiss();
			}
		})
	}

	$(document).ready(function() {
		c.initialize();
	});
}

var EventDialog = function(calendar,event){
	_t = this;
	var event_quick_view = null;
	var template = "";
	var _this_event = null;
	this.inflate = function(_event){
		if(!_event) throw new UserException("EventStick can't be null!");
		_this_event = _event;
		var start_time = "",
			end_time = "",
			time_string = null;

		if(_event.allDay){
			start_time = (/00:00:00/i.test(_event._start.toLocaleString()) ? $.fullCalendar.formatDate(_event._start,"ddd MMM dd, yyyy") : $.fullCalendar.formatDate(_event._start,"ddd MMM dd, yyyy hh:mm"));
			if(_event._end)
				end_time = (/00:00:00/i.test(_event._end.toLocaleString()) ? $.fullCalendar.formatDate(_event._end,"ddd MMM dd, yyyy") : $.fullCalendar.formatDate(_event._end,"ddd MMM dd, yyyy hh:mm"));
			time_string = (_event._start === _event._end || !_event._end ? start_time : start_time + " - " + end_time);
		}else{
			var reg = new RegExp(/ [0-9][0-9]:[0-9][0-9]:[0-9][0-9]/),
				stime = _event._start.toLocaleString().match(reg).toString(),
				etime = _event._end.toLocaleString().match(reg).toString();

			start_time = _event._start.toLocaleString().replace(stime,",");
			end_time = _event._end.toLocaleString().replace(etime,",");

			stime = stime.substr(0,stime.length - 3);
			etime = etime.substr(0,etime.length - 3);

			time_string = (start_time === end_time ? start_time + " " + stime + " - " + etime : start_time + " " + stime + " - " + end_time + " " +etime );
		}
		event_quick_view = $('<div class="modal" style="width: 300px; display:none; margin:0 0 0 0;"></div>');
		template = '<div class="modal-header"><button type="button" class="close event-close-btn" data-dismiss="modal" aria-hidden="true">&times;</button><h3>'+ _event.title +'</h3></div><div class="modal-body"><div class="event_summary">'+ time_string +'</div>'+ _event.note +'</div><div class="modal-footer"><a href="'+ _event.delete_url +'" class="delete btn btn-primary">Delete</a><a href="'+ _event.edit_url +'" class="edit btn btn-primary" >Edit</a></div>';
	}

	this.show = function(pos){
		if(pos){
			var pos = getPosition(pos);
			event_quick_view.css({"left":pos.x+"px","top":pos.y+"px"});
		}
		event_quick_view.html(template).appendTo("body").show();
		event_quick_view.find(".event-close-btn").one("click",function(){_t.dismiss();});
		event_quick_view.find("a.delete").one("click",function(){calendar.deleteEvent(_this_event.delete_url,_this_event._id);return false;});
		event_quick_view.find("a.edit").one("click",function(){calendar.editEvent(_this_event.edit_url,_this_event.allDay);return false;});
	}

	this.dismiss = function(){
		if(event_quick_view)
			event_quick_view.remove();
	}

	var getPosition = function(pos){
		var x = pos.x,
			y = pos.y,
			winheight = $(window).height();
		if((x + event_quick_view.width()) > $(window).width()){
			x = x - event_quick_view.width();
		}
		if((y + event_quick_view.height()) > winheight){
			y = y - event_quick_view.height();
		}
		return {"x":x,"y":y};
	}

	if(event)
		_t.inflate(event);
}

var UserException = function(message) {
   this.message = message;
   this.name = "UserException";
   this.toString = function(){
   	return this.message;
   }
}

var AgendaView = function(calendar){
	var av = this;
	var _calendar = calendar;
	var agenda_space = _calendar.agenda_space;
	var today = new Date();
	var minDifference = 6;
	var start_month = today.getMonth();
	var start_year = today.getFullYear();
	var end_month = ((start_month + minDifference) > 11 ? (start_month + minDifference) - 11 : start_month + minDifference);
	var end_year = ((start_month + minDifference) > 11 ? start_year+1 : start_year);
	var monthNames = ['January','February','March','April','May','June','July','August','September','October','November','December'];
	var month_template = '<div class="span4"><h4></h4><div class="tiny_calendar"><table class="table"><tbody><tr><th class="week_title">Sun</th><th class="week_title">Mon</th><th class="week_title">Tue</th><th class="week_title">Wed</th><th class="week_title">Thu</th><th class="week_title">Fri</th><th class="week_title">Sat</th></tr></tbody></table></div></div>';

	var event_list_template = '<div class="span8"><table class="table event_list"><thead><tr height="0"><th class="span3"></th><th class="span2"></th><th class=""></th></tr></thead><tbody><tr><td colspan="3" class="no_events">No events for this month.</td></tr></tbody></table></div>';

	var head_template = '<div><label>From</label> <select name="start_month" class="input-small"></select><select name="start_year" class="input-small"></select><label>To</label> <select name="end_month" class="input-small"></select><select name="end_year" class="input-small"></select><button id="show_events" class="btn  bt-filter">Show Events</button></div>';

	var event_template = "<tr><th></th><td class='event_time'></td><td><div class='event'></div></td></tr>";

	var cache = false;
	var show_event_clicked = false;

	this.refresh = function(){
		av.inflate(true);
	}

	this.inflate = function(forceInflation){
		loading(true);
		_calendar.calendar.hide();
		_calendar.navigation.hide();

		if(!forceInflation){
			if(cache){
				av.show();
				loading(false);
				return;
			}
		}
		
		agenda_space.empty();
		if(!show_event_clicked){
			_calendar.rangeSelection.empty();
			_calendar.rangeSelection.append(renderHead().html()).show();
			_calendar.rangeSelection.find("button#show_events").click(function(){
				show_event_clicked = true;
				start_month = parseInt($("select[name=start_month]").val());
				end_month = parseInt($("select[name=end_month]").val());
				start_year = parseInt($("select[name=start_year]").val());
				end_year = parseInt($("select[name=end_year]").val());
				av.inflate(true);
			})
		}
		show_event_clicked = false;
		eventsManager();
		var s = start_month,
			e = end_month
			y = start_year;
		e = (e > s && start_year == end_year? e : e + 11);
		if(end_year > start_year)
			e = e + ((end_year - start_year -1) * 12);
		else e--;
		for(var i = s;i <= e+1; i++){
			var m = new Month(s,y);
			s++;
			if(s > 11){
				s = 0;
				y++;
			}
			if(e == 0)
				agenda_space.text("Invalid Range of Dates.")
			else
				agenda_space.append(m.monthDom);
		}
		
		loading(false);
	}

	this.hide = function(){
		cache = true;
		_calendar.rangeSelection.hide();
		agenda_space.hide();
		_calendar.navigation.show();
		_calendar.calendar.show();
	}

	this.show = function(){
		_calendar.rangeSelection.show();
		agenda_space.show();
	}
	var copyObject = function(x){
		return x.clone();
	}
	var eventsManager = function(){
		var url = "/panel/calendar_new/back_end/events/agenda",
			sd = new Date(start_year,start_month,1),
			ed = new Date(end_year,end_month+1,0);
		$.ajax({
			type : "get",
			url : url,
			data : {"agenda_start":sd.toLocaleString(),"agenda_end":ed.toLocaleString()},
			success : function(events){
				$.each(events,function(i,e){
					var ed = eventDom(e),
						s = new Date(e.start),
						e = new Date(e.end),
						e_m = ((e.getMonth() > s.getMonth() || s.getMonth() == e.getMonth()) && s.getFullYear() == e.getFullYear() ? e.getMonth() : e.getMonth() + 12)
						s_m = s.getMonth(),
						s_y = s.getFullYear();
					if(e.getFullYear() > s.getFullYear())
						e_m = e_m + ((e.getFullYear() - s.getFullYear() -1) * 12);
					for(var i = s_m; i < e_m + 1; i++){
						var temp_ed = copyObject(ed);
						var list = agenda_space.find("div[data-month="+s_m+"][data-year="+s_y+"] table.event_list tbody");
						list.append(temp_ed);
						s_m++;
						if(s_m > 11){
							s_m = 0;
							s_y++;
						}
					}
					if(s.getDate() == e.getDate() && s.getMonth() == s.getMonth() && e.getFullYear() == e.getFullYear()){
						var td = agenda_space.find("td[data-date-node="+s.getDate()+"-"+s.getMonth()+"-"+s.getFullYear()+"]");
						td.addClass("has_event");
					}else{
						var timeDiff = Math.abs(e.getTime() - s.getTime()),
							diffDays = Math.ceil(timeDiff / (1000 * 3600 * 24)),
							c_m = s.getMonth(),
							c_d = s.getDate(),
							c_y = s.getFullYear(),
							end_of_c_month = new Date(s.getFullYear(),s.getMonth()+1,0).getDate();

						for(var i = 0; i <= diffDays; i++){
							var td = agenda_space.find("td[data-date-node="+c_d+"-"+c_m+"-"+c_y+"]");
							td.addClass("has_event");
							c_d++;
							if(c_d > end_of_c_month){
								c_d = 1;
								c_m++;
								if(c_m > 11){
									c_m = 0;
									c_y++;
								}
							}
						} 
					}
				})
				agenda_space.find("table.event_list tbody").each(function(){
					if($(this).find("tr").length > 1)
						$(this).find("td.no_events").parent().remove();
				})
			}
		})
		var eventDom = function(event){
			var e_t = $(event_template),
				s = new Date(event.start),
				e = new Date(event.end),
				dateFormat = "";
			if(s.getDate() == e.getDate() && s.getMonth() == s.getMonth() && e.getFullYear() == e.getFullYear())
				dateFormat = $.fullCalendar.formatDate(s, "ddd dd");
			else
				dateFormat = $.fullCalendar.formatDates(s, e, "ddd dd, MMM - {ddd dd, MMM}");
			e_t.find("th").text(dateFormat);
			e_t.find("td.event_time").text((event.allDay ? "All Day" : $.fullCalendar.formatDate(s, "hh:mm")));
			e_t.find("div.event").text(event.title).css("color",event.color);
			return e_t;
		}

	}

	var loading = function(bool) {
		if (bool) _calendar.loading.css("left",($(window).width()/2 - 60) + "px").show();
		else _calendar.loading.hide();
	}

	var renderHead = function(){
		var head = $(head_template);
		var start_month_select = head.find("select[name=start_month]");
		for(var i = 0; i < 12; i++){
			var option = $("<option value='"+i+"'>"+monthNames[i]+"</option>");
			if(i == start_month)
				option.attr("selected","selected");
			start_month_select.append(option);
		}
		var end_month_select = head.find("select[name=end_month]");
		for(var i = 0; i < 12; i++){
			var option = $("<option value='"+i+"'>"+monthNames[i]+"</option>");
			if(i == end_month)
				option.attr("selected","selected");
			end_month_select.append(option);
		}

		var start_year_select = head.find("select[name=start_year]");
		var y = start_year - 5;
		for(var i = 0; i < 10; i++){
			var option = $("<option value='"+y+"'>"+y+"</option>");
			if(y == start_year)
				option.attr("selected","selected");
			start_year_select.append(option);
			y++;
		}
		var end_year_select = head.find("select[name=end_year]");
		y = start_year - 5;
		for(var i = 0; i < 10; i++){
			var option = $("<option value='"+y+"'>"+y+"</option>");
			if(y == end_year)
				option.attr("selected","selected");
			end_year_select.append(option);
			y++;
		}
		return head;
	}

	var Month = function(month,year){
		_this = this;
		this.monthDom = $("<div class='row-fluid' data-year='"+year+"' data-month='"+month+"'></div>");
		var template = $(month_template);
		var list_template = $(event_list_template);
		var firstDay = new Date(year,month,1);
		var lastDay = new Date(year,month+1,0);
		
		var last_inserted_date = 1;
		
		var renderMonth = function(){
			for(var i = 0; i < 5; i++){
				var tr = null;
				if(i == 0)
					tr = makeRow("first");
				else if(i == 4){
					tr = makeRow("last");
				}else{
					tr = makeRow("middle");
				}
				template.find("table.table tbody").append(tr);
				template.find("h4").text(monthNames[firstDay.getMonth()] + " - " + firstDay.getFullYear());
			}
			_this.monthDom.append(template);
			_this.monthDom.append(list_template);
		}

		var makeRow = function(position){
			var row = $("<tr></tr>");
			switch (position){
				case "first":
					for(var i = 0;i < 7;i++){
						var td = $("<td></td>");
						if(i >= firstDay.getDay()){
							td.text(last_inserted_date);
							td.attr("data-date-node",last_inserted_date+"-"+firstDay.getMonth()+"-"+firstDay.getFullYear());
							last_inserted_date++;
						}
						row.append(td);
					}
				break;
				case "middle":
					for(var i = 0;i < 7;i++){
						var td = $("<td></td>");
						td.text(last_inserted_date);
						td.attr("data-date-node",last_inserted_date+"-"+firstDay.getMonth()+"-"+firstDay.getFullYear());
						last_inserted_date++;
						row.append(td);
					}
				break;
				case "last":
					for(var i = 0;i < 7;i++){
						var td = $("<td></td>");
						if(i <= lastDay.getDay()){
							td.text(last_inserted_date);
							td.attr("data-date-node",last_inserted_date+"-"+firstDay.getMonth()+"-"+firstDay.getFullYear());
							last_inserted_date++;
						}
						row.append(td);
					}
				break;
			}
			return row;
		}

		renderMonth();
	}

}




		

























