define([
    'Global',
    'Calendars',
    'PatientContext',
    'User',
	'CalendarData',
    'DesiredDate',
    'AppointmentRequest',
	'ApptRequestDetails',
	'MessagePopupView',
    'ErrorDesiredDatePopup',
	'Text!../html/templates/calendar.html',
    'Text!../html/templates/messages.html',
    'Text!../html/templates/clinic-legend-one.html',
    'Text!../html/templates/month-legend.html',
    'jquery.refresher'
],
    function (Global, Calendars, PatientContext, User, CalendarData, DesiredDate, AppointmentRequest, 
                ApptRequestDetails, MessagePopupView, errorDesiredDatePopup,
			  template, MessageTemplate, ClinicLegendTemplate, MonthLegendTemplate) {
        'use strict';

        var CalendarView = Backbone.View.extend({

                className: "calendar-section",

            initialize: function () {
	            var that = this;

				this.calendarData = CalendarData.instance();
				this.$container = getMainContent();
                this.today = this.calendarData.getToday();
                this.date = setTimeToZero(new Date());
                this.yearFromDate = this.calendarData.getYearFromDate();
                this.messageTemplate = _.template(MessageTemplate);
                this.clinicLegendTemplate = _.template(ClinicLegendTemplate);
                this.monthLegendTemplate = _.template(MonthLegendTemplate);
	            this.template = _.template(template);
				this.patientAppts = [];
	            this.calendarRowMinutes = 15;
	            this.apptLength = 15;

	            this.listenTo(this.calendarData, "refreshCalendar", function () {
		            that.render();
	            }).listenTo(this.calendarData, "invalidClinic", function (data) {
		            new MessagePopupView({
						alertMessage: "There was an error accessing the following clinic: " + data.clinicName + "\n",
						serverMessage: data.invalidCallResponse
		            }).render();
	            });
            },

            render: function (forceRender) {
	            var desiredDate = DesiredDate.instance().get('desiredDate'),
					$container = this.$container;

	            if (!desiredDate) {
		            DesiredDate.clearInstance();
		            DesiredDate.instance({
			            desiredDate: this.populateDesiredDate()
		            });
	            }

				this.getCalendarData();

	            if (this.isVisible() || forceRender) {
	                if (this.valid) {
		                this.showCalendar();
                        this.showRefresh();
	                } else {
		                this.$el
			                .empty()
			                .append(this.messageTemplate({
				                theme: 'e',
				                header: false,
				                message: 'Please select a Service/Specialty and Clinic to view availability.'
			                }));

	                    $container
		                    .empty()
		                    .append(this.$el);

						$container.trigger('create');
                        this.$el.find("#refresh-button").trigger("create");
	                }
	            }

				return this;
            },

            events: {
                'change #toggle-nom': 'updateNomenclature',
	            'keydown .fc-event:not(.transparent)': 'handleSlotTab',
	            'keydown .fc-button-agendaDay': 'handleDayButtonTab'
            },

	        handleSlotTab: function (e) {
		        var $target = $(e.currentTarget),
			        viewName = this.calendarData.getCalendarView();

		        if (viewName === "agendaDay" && e.which === 9) {
			        e.preventDefault();

			        if (e.shiftKey) {
				        var $prev = $target.prevAll('.fc-view-agendaDay .fc-event:not(.transparent)').eq(0);

				        if ($prev.length) {
					        $prev.focus();
				        } else {
					        $('.fc-button-agendaDay').focus();
				        }
			        } else {
				        var $next = $target.nextAll('.fc-view-agendaDay .fc-event:not(.transparent)').eq(0);

				        if ($next.length) {
					        $next.focus();
				        } else {
                            $('footer li a:eq(0)').focus();
                        }
			        }
		        }
	        },

	        handleDayButtonTab: function (e) {
		        var viewName = this.calendarData.getCalendarView();

				if (viewName === "agendaDay" && e.which === 9 && !e.shiftKey) {
					e.preventDefault();

					$('.fc-view-agendaDay .fc-event:not(.transparent)').eq(0).focus();
				}
	        },

	        updateNomenclature: function() {
		        var nomenclature = this.calendarData.getNomenclature();

		        this.calendarData.setNomenclature(!nomenclature);

		        this.calendar.rerenderEvents();
	        },

            handleDisplayNomenclature: function(){
				var nomenclature = this.calendarData.getNomenclature(),
					$daySlots = $('.fc-view-agendaDay .fc-event:not(.patient-appt)'),
					$overbookingBtn = $('.calendar-section .ui-btn'),
                    $legends = $('.legend:not(.patient-appt)'),
                    $legendKey = $('.legend-key'),
					title = "";

                if (nomenclature) {
                    $legendKey.removeClass('hidden');
                    $legends.addClass("nomenclature");
	                $daySlots.addClass("nomenclature");
	                $overbookingBtn.addClass('nomenclature');
	                title = "CLINIC NAME (Overbooks allowed per day)";
                } else {
                    $legendKey.addClass('hidden');
                    $legends.removeClass("nomenclature");
	                $daySlots.removeClass("nomenclature");
	                $overbookingBtn.removeClass('nomenclature');
	                title = "CLINIC NAME";
                }

	            var $column = $('.fc-view-agendaDay .clinic0').eq(0),
                    overbooks = $column.length ? $column.data("overbooks") : 0;
                overbooks = "(" + overbooks + ")";

                $('.legend.clinic0').attr({"data-overbooks": overbooks, "title": title});
            },

            showRefresh: function(){
                getSubHeaderRight().refresher({
                    date: false,
                    icon:'scv-icon-refresh',
                    callback:CalendarData.instance().getClinicSlots, 
                    context:CalendarData.instance()
                });
            },

			showCalendar: function () {
				var $container = this.$container,
                    toggleNomValue = this.calendarData.getNomenclature() ? "on" : "off",
					viewName = this.calendarData.getCalendarView();

				this.$el
					.empty()
					.append(this.template({facilityName: User.get('facilityName')}));

				$container
					.empty()
					.append(this.$el);

                $('#toggle-nom').val(toggleNomValue).slider();

                this.buildCalendar();

				if (viewName === "agendaDay") {
					this.handleDisplayNomenclature();
				}

                this.delegateEvents();
			},

            buildCalendar: function () {
                var slots = this.slots,
                    minTime = this.startTime,
                    date = this.date || new Date(),
                    defaultView = this.calendarData.getCalendarView() || "month",
                    $legend = $('#legend'),
	                calendarRowMinutes = this.calendarRowMinutes,
	                that = this;

				this.numClinics = this.calendarData.getNumClinics();

                if (defaultView === "month") {
                    $legend
                        .empty()
                        .append(this.monthLegendTemplate);
                } else {
                    $legend
                        .empty()
                        .append(this.clinicLegendTemplate({clinicName: this.calendarData.getClinicName()}));
                }

                that.calendar = that.$el.find('#calendar').empty().fullCalendar({
                    header: {
                        left: 'prev,next today',
                        center: 'title',
                        right: 'month,agendaWeek,agendaDay'
                    },
                    defaultView: defaultView,
					defaultEventMinutes: 30,
                    editable: false,
                    weekMode: 'liquid',
                    allDaySlot: false,
                    slotMinutes: calendarRowMinutes,
                    timeFormat: 'H:mm',
                    axisFormat: 'H:mm',
                    minTime: minTime,
                    maxTime: '24',
                    events: slots,
                    eventRender: function (event, element, view) {
                        that.eventRender(event, element, view);
                    },
                    windowResize: function (view) {
                        $('.fc-view-month .fc-event').addClass('hidden');
                        $('.fc-day-content div').css('height', '0px');
                    },
                    dayClick: function (date) {
                        var dataDate = that.makeDataDate(date),
                            selectedDay = $('[data-date="' + dataDate + '"]');

                        if (selectedDay.hasClass('available')) {
                            that.goToDay(date);
                        }
                    },
                    viewDisplay: function (view) {
	                    var $toggleNom = $('.nom-switch .ui-slider');

	                    if (view.name === "agendaDay") {
		                    $toggleNom.removeClass('invisible');
	                    } else {
		                    $toggleNom.addClass('invisible');
                        }

						if (that.calendar) {
                            that.handleViewChange(view);
                        }
                    },
					eventClick: function (event, e) {
						if (!$(e.currentTarget).hasClass('transparent')) {
							that.handleSlotSelect(event);
						} else {
							$(e.currentTarget).blur();
						}
					},
					eventAfterAllRender: function (view) {
						var viewName = view.name;

						switch (viewName) {
							case "agendaWeek":
								that.arrangeWeekEvents(view);
								break;
							case "agendaDay":
								that.arrangeEvents(viewName);

								that.handleDisplayNomenclature();

								break;
						}

						that.arrangePatientAppts(viewName);
					}
                });

                this.calendar = this.calendar.data().fullCalendar;

                this.$previousButton = this.$el.find('.fc-button-prev');
                this.$nextButton = this.$el.find('.fc-button-next');

				this.renderPatientAppts();

                this.$previousButton.addClass("fc-state-disabled");
				this.$previousButton[0].disabled = true;

                this.calendar.gotoDate(date);
            },

            renderPatientAppts: function () {
				var patientAppts = this.patientAppts,
					that = this;

				if (this.valid && this.isVisible() && this.calendar) {
					_.each(patientAppts, function (patientAppt) {
						that.calendar.renderEvent({
								title: patientAppt.clinicName,
								allDay: false,
								start: patientAppt.start,
                                end: patientAppt.end,
								apptLength: patientAppt.apptLength,
								className: "patient-appt"},
							true
						);
					});

					this.handleViewChange(this.calendar.getView());
				}
            },

            getCalendarData: function () {
	            this.apptLength = this.calendarData.getApptLength();
				this.date = this.calendarData.getCalendarDate();
				this.patientAppts = this.calendarData.getPatientAppts();
				this.slots = this.calendarData.getAvailableSlots();
				this.startTime = this.calendarData.getStartTime();
				this.valid = this.calendarData.getValid();
            },

            showClinic: function () {
                var view = this.calendar.getView().name,
                    $legend = $('#legend'),
	                that = this;

                if (view === 'month'){
                    this.showClinicMonth();
                } else {
                    $legend
                        .empty()
                        .append(this.clinicLegendTemplate({clinicName: this.calendarData.getClinicName()}));

                    var $toggleOverbooks = $('.overbooks');

                    if (view === 'agendaWeek'){
                        this.showClinicWeek();

                        //hide overbooks allowed per day message
                        $toggleOverbooks.addClass('invisible');
                    } else {
                        that.handleDisplayNomenclature();

                        //show overbooks allowed per day message
                        $toggleOverbooks.removeClass('invisible');
                    }
                }

                if (that.patientAppts.length) {
                    $('.legend.patient-appt').removeClass('hidden');
                }
            },

            showClinicMonth: function () {
                var $slots = $('.fc-view-month .fc-event').not('.patient-appt'),
                    $patientAppts = $('.fc-view-month div .patient-appt'),
                    $days = $('.fc-view-month table tbody'),
                    $legend = $('#legend'), i, len, slot, appt,
	                that = this;

                $legend.empty().append(this.monthLegendTemplate);

                for(i = 0, len = $slots.length; i < len; i++) {
                    slot = $slots.eq(i).data().start;

                    if (slot > that.yearFromDate) { return; }

                    if (slot >= that.today) {
                        var dataDate = that.makeDataDate(slot),
                            day = $days.find('td[data-date=' + dataDate + ']'),
							dayContent = day.html(),
							hasLink = day.find('button').length;

						if (!hasLink) {
							day.addClass('available').attr('title', 'Select to view available appointments for this day')
								.html('<button data-role="none">' + dayContent + '</button>');
						}
                    }
                }

                for(i = 0, len = $patientAppts.length; i < len; i++) {
                    appt = $patientAppts.eq(i).data().start;
                    var $apptDays = $days.find('td[data-date=' + that.makeDataDate(appt) + ']');
                    $apptDays.find('.patient-appt-icon').remove();
                    $apptDays
						.addClass('patient-appt')
                        .prepend("<span title='The patient has appointments for this day.' class='patient-appt-icon'></span>");
                }

                $('.fc-view-month .fc-event').addClass('hidden');

                $('.fc-day-content div').css('height', '0px');
            },

            makeDataDate: function (date) {
                var month = addLeadingZero(date.getMonth() + 1),
                    day = addLeadingZero(date.getDate()),
                    year = date.getFullYear(),
                    dataDate = year + "-" + month + "-" + day;

                return dataDate;
            },

            showClinicWeek: function () {
                var $slots = $('.fc-view-week .fc-event'),
	                that = this;

                for(var i = 0, len = $slots.length, $slot, slot; i < len; i++ ) {
                    $slot = $slots.eq(i);
                    slot = $slot.data().start;

                    if (slot < that.today || slot > that.yearFromDate) {
                        $slot.addClass('hidden');
                    }
                }
            },

            handleNextMonth: function () {
                var calendarDate = this.calendar.getDate();

                if (calendarDate.getMonth() >= this.today.getMonth()) {
                    this.$nextButton.addClass("fc-state-disabled");
					this.$nextButton[0].disabled = true;
                } else {
                    this.$nextButton.removeClass("fc-state-disabled");
					this.$nextButton[0].disabled = false;
                }
            },

            handleNextWeek: function () {
                var calendarDate = this.calendar.getDate(),
                    startOfWeek = calendarDate.getDate() - calendarDate.getDay(),
                    endOfWeek = calendarDate.getDate() + (7 - calendarDate.getDay());

                if (calendarDate.getMonth() >= this.today.getMonth() &&
                    this.today.getDate() >= startOfWeek &&
                    this.today.getDate() < endOfWeek) {
                    this.$nextButton.addClass("fc-state-disabled");
					this.$nextButton[0].disabled = true;
                } else {
                    this.$nextButton.removeClass("fc-state-disabled");
					this.$nextButton[0].disabled = false;
                }
            },

            handleNextDay: function () {
                var calendarDate = this.calendar.getDate();

                if (calendarDate.getMonth() >= this.today.getMonth() &&
                    calendarDate.getDate() == this.today.getDate()) {
                    this.$nextButton.addClass("fc-state-disabled");
					this.$nextButton[0].disabled = true;
                } else {
                    this.$nextButton.removeClass("fc-state-disabled");
					this.$nextButton[0].disabled = false;
                }
            },

            handleViewChange: function (view) {
				this.calendarData
					.setCalendarDate(this.calendar.getDate())
					.setCalendarView(view ? view.name : "month");

                this.showClinic();
                this.restrictNext();
                this.restrictPrevious();
            },

            eventRender: function (event, $element, view) {
                var that = this,
	                eventData = $element.data(),
                    startTime = addLeadingZero(event.start.getHours())
                        + ":" + addLeadingZero(event.start.getMinutes()),
                    start = event.start,
					title = event.title,
					properties = {
						"data-startDate": formatDate(start),
						"data-status": event.bookingStatus
					},
					viewName = view.name,
					clinic = this.calendarData.getClinic(),
	                classes = "",
	                slotHidden = event.clinicId ? that.isSlotHidden(event) : false,
                    nomenclature = this.calendarData.getNomenclature();

	            switch (viewName) {
		            case "agendaDay":

                        if (!title) {
                            title = "";

                            if (!slotHidden){
                                title += "Click to book appointment. ";
                            }
                            if (nomenclature){
                                title += that.handleTitlesForSlots(event.bookingStatus);
                            }

                            properties["title"] = title;

                        }
			            if (slotHidden) {
				            if (this.calendarData.getNomenclature()) {
					            $element.addClass('transparent');
				            } else {
					            $element.remove();
				            }
			            }

			            break;
		            case "agendaWeek":
						properties["title"] = title ? title : "Click to show available appointments in day view.";
						break;
		            case "month":
			            if (slotHidden) {
							$element.remove();
			            }
			            break;
	            }

                eventData.clinicId = event.clinicId;
                eventData.startTime = startTime;
                eventData.start = start;
				eventData.apptLength = event.apptLength;
                eventData.end = event.end;
                eventData.overbooks = event.overbooks;

				$($element).attr(properties);

                if (event.clinicId) {
	                classes += clinic.get('className') + " ";
                }

	            if (event.bookingStatus === "No Availability") {
		            classes += 'superbooking ';
	            }

	            $element.addClass(classes);
            },
            handleTitlesForSlots: function(bookingCode){
                var intBookingCode = parseInt(bookingCode),
	                charCode = $.isFunction(bookingCode.charCodeAt) ? bookingCode.charCodeAt(0) : 0;

	            if (isNaN(intBookingCode)){
                    switch (bookingCode){
                        case "No Availability":
                            return bookingCode;
                            break;
                        case "X":
                            return "This slot has been cancelled";
                            break;
                        case "*":
                            return "Bookings on unavailable slot: 1";
                            break;
                        case "$":
                            return "Bookings on unavailable slot: 2";
                            break;
                        case "!":
                            return "Bookings on unavailable slot: 3";
                            break;
                        case "@":
                            return "Bookings on unavailable slot: 4";
                            break;
	                    default:
		                    if (charCode >= 65 && charCode < 88) {
			                    var numOverbookings = charCode - 64;

			                    return " Overbookings made: " + numOverbookings;
		                    }
                    }
                } else {
                    return " Remaining bookings: " + bookingCode;
                }

            },

	        isSlotHidden: function (slot) {
		        var hideSlot = false,
			        status = slot.bookingStatus + "",
                    overbooks = slot.overbooks,
			        availability = slot.availability,
			        statusAsInt = parseInt(status),
			        SDOBKey = this.calendarData.getSDOBKey(),
			        SDMOBKey = this.calendarData.getSDMOBKey(),
			        statusCode = status.charCodeAt(0);

                if (status === "X") {
                    hideSlot = true;
                } else if (!SDMOBKey) {
			        if (SDOBKey) {
				        if (overbooks === "0" && (isNaN(statusAsInt) || statusAsInt <= 0)) {
					        hideSlot = true;
				        } else if (isNaN(statusAsInt)) {
					        if (status.length > 1) {
						        hideSlot = true;
					        } else if (!(statusCode > 64 && statusCode < 88)) {
						        hideSlot = true;
					        }
				        }
			       } else {

				        if (!availability || statusAsInt < 1 || isNaN(statusAsInt)) {
				            hideSlot = true;
			            }
			       }
		        }

		        return hideSlot;
	        },

            restrictPrevious: function () {
                var calendarDate = this.calendar.getDate(),
	                that = this;

                if (calendarDate < that.today) {
                    that.calendar.gotoDate(that.today);
                }

                if ($('.fc-button-today').hasClass('fc-state-disabled')) {
                    this.$previousButton.addClass("fc-state-disabled");
					this.$previousButton[0].disabled = true;
                } else {
                    this.$previousButton.removeClass('fc-state-disabled');
					this.$previousButton[0].disabled = false;
                }
            },

            restrictNext: function () {
                var calendarDate = this.calendar.getDate();

                if (calendarDate.getFullYear() > this.today.getFullYear()) {
                    switch (this.calendar.getView().name) {
                        case 'month':
                            this.handleNextMonth();

                            break;
                        case 'agendaWeek':
                            this.handleNextWeek();

                            break;
                        case 'agendaDay' :
                            this.handleNextDay();

                            break;
                    }
                } else {
					this.$nextButton.removeClass("fc-state-disabled");
					this.$nextButton[0].disabled = false;
				}
            },

            handleSlotSelect: function (event) {
				var date = new Date(event.start),
					maxBookDate = this.maxBookDate,
                    desiredDate = DesiredDate.instance().get('desiredDate');

				if (this.calendar.getView().name === "agendaWeek") {
                    this.goToDay(event.start);
                } else if (event.className.indexOf("patient-appt") === -1) {
					var hasClinicAccess = this.calendarData.getClinic().get("hasUserAccessToClinic");

					if (!PatientContext.instance().isValid()) {
						new MessagePopupView({message: "Please select a patient before booking an appointment."}).render();
					} else if (!hasClinicAccess) {
				        new MessagePopupView({title: "Restricted Clinic", alertMessage: "Booking for this clinic is restricted.  If you need access, please contact your administrator."}).render();
					} else if (date < new Date()) {
						new MessagePopupView({message: "Cannot book an appointment in the past."}).render();
					} else if (!desiredDate){
                        new errorDesiredDatePopup(event).render();
                    } else {
						ApptRequestDetails.instance().fillData(event);

						Global.getUtilities().eventAggregator.trigger("book-appointment");
					} 
				}
            },

			goToDay: function (date) {
				this.calendar.gotoDate(date);
				this.calendar.changeView("agendaDay");
				$('.fc-view-agendaDay .fc-event:not(.transparent)').eq(0).focus();
			},

			arrangeEvents: function (viewName, date) {
				var numClinics = this.numClinics,
					that = this,
					$view = $('.fc-view-' + viewName),
					$container = $view.find('.fc-event').parent(),
					zIndex = 8,
					lastLeft = 0,
					clinicsObject = this.createClinicsObject(viewName, date),
					width = clinicsObject.width,
					$allEvents = [];

				for (var i = 0; i < numClinics; i++) {
					var clinic = clinicsObject.clinics[i],
						$events = clinic.slots,
						height = clinic.height,
						left,
						lastTop = 0;

					left = lastLeft ? (lastLeft + width) + "px" : clinicsObject.firstLeft;

					for(var j = 0; j < $events.length; j++) {
						var $event = $($events[j]),
							top,
							start = new Date($event.data('start')),
							minutes = j ? start.getMinutes() : 0,
							prevSlotTime = j ? new Date($($events[j - 1]).data('start')) : 0,
							prevTime = subtractFromDateUnformatted(0, 0, 0, 0, clinic.defaultLength, 0, 0, start);

						if (minutes) {
							if (prevSlotTime.getTime() !== prevTime.getTime()) {
								top = $event.css('top');
							} else {
								top = Math.floor(lastTop + height) + "px";
							}
						} else {
							top = $event.css('top');
						}

						$event
							.css({
								"width": width + "px",
								"height": height + "px",
								"left": left,
								"z-index": zIndex,
								"top": top
							});

						lastTop = $events.length ? parseInt(top.substring(0, top.length -2)) : lastTop;
					}

					$events
						.css({
							"width": width + "px",
							"height": height + "px",
							"left": left,
							"z-index": zIndex
						});

					$events = that.sortEventsList($events);

					$allEvents = $allEvents.concat(jQuery.makeArray($events));

					lastLeft = $events.length ? parseInt(left.substring(0, left.length -2)) : lastLeft;
				}

				if (!date) {
					$container.append($allEvents);

					return [];
				} else {
					return $allEvents;
				}
			},

			arrangeWeekEvents: function (view) {
				var viewName = view.name,
					$view = $('.fc-view-' + viewName),
					$container = $view.find('.fc-event').parent(),
					startDate = view.start,
					endDate = view.end,
					$allEvents = [];

				for (var date = startDate; date < endDate; date = addToDate(0, 1, 0, 0, 0, 0, 0, date)) {
					$allEvents = $allEvents.concat(this.arrangeEvents(viewName, date));
				}

				$container.append($allEvents);
			},

			arrangePatientAppts: function (viewName) {
				var $view = $('.fc-view-' + viewName),
					$patientAppts = $view.find('.fc-event.patient-appt'),
					width = $view.find('.fc-col0').width() - 5,
                    allConflictAppts = [],
                    $availableAppts = $view.find('.fc-event:not(.patient-appt)'),
					that = this;

				_.each($patientAppts, function(appt) {
					var $appt = $(appt),
						startDate = $appt.attr('data-startDate'),
						zIndex = 200,
						left = $view
								.find('[data-startDate="' + startDate + '"]:not(.patient-appt)')
								.eq(0)
								.css('left'),
						height = that.calculateSlotHeight(viewName, $appt.data('apptLength'));

                    $appt
                        .css({
                            "width": width + "px",
                            "height": height + "px",
                            "left": left,
                            "z-index": zIndex
                        });

                    if (viewName === "agendaDay"){
                        var startTime = new Date($appt.data('start')),
                            endTime = new Date($appt.data('end'));

                        _.each($availableAppts, function(availableAppt){
                            var $availableAppt = $(availableAppt),
                                apptStartTime = new Date($availableAppt.data('start')),
                                apptEndTime = new Date($availableAppt.data('end'));

                            if (that.compareStartDates(startTime, endTime, apptStartTime) || that.compareBetweenDates(startTime, endTime, apptStartTime, apptEndTime) || that.compareEndDates(startTime, endTime, apptEndTime)){
                                allConflictAppts = allConflictAppts.concat(availableAppt);
                            }
                        });

                    }
				});

                $(allConflictAppts).remove();
			},

            compareStartDates: function(start, end, date){

                var timeRange = false;

                if (date >= start && date < end){
                    timeRange = true;
                }

                return timeRange;

            },

            compareBetweenDates: function(start, end, apptStartTime, apptEndTime){
                var timeRange = false;

                if (apptStartTime <= start && apptEndTime >= end){
                    timeRange = true;
                }

                return timeRange;
            },

            compareEndDates: function(start, end, date){
                var timeRange = false;

                if (date > start && date <= end){
                    timeRange = true;
                }

                return timeRange;

            },

			sortEventsList: function ($events) {
				var compare = function (a, b) {
					var aDate = $(a).data().start,
						bDate = $(b).data().start;

					if (aDate < bDate) {
						return -1;
					}
					if (aDate > bDate) {
						return 1;
					}

					return 0;
				};

				return $events.sort(compare);
			},

			createClinicsObject: function (viewName, date) {
				date = date ? formatDate(date) : "";

				var clinicsObject = {},
					$view = $('.fc-view-' + viewName),
					columnWidth = $view.find('.fc-col0').width() - 5,
					dateSelector = date ? '[data-startDate="' + date + '"]' : '',
					numClinics = this.numClinics,
					numVisibleClinics = 0,
					that = this;

				clinicsObject.clinics = [];
				clinicsObject.firstLeft = "px";

				for (var i = 0; i < numClinics; i++) {
					var $clinicEvents = $view.find(dateSelector + '.clinic' + i + ':not(.patient-appt)'),
						clinicData = {
							slots: $clinicEvents
						};

					if ($clinicEvents.length > 0) {
						var apptLength = $clinicEvents.eq(0).data("apptLength");

						numVisibleClinics++;

						date = date || $clinicEvents.eq(0).attr('data-startDate');

						clinicData.defaultLength = apptLength;
						clinicData.height = that.calculateSlotHeight(viewName, clinicData.defaultLength);
					}

					clinicsObject.clinics.push(clinicData);
				}

				clinicsObject.width = numVisibleClinics ? Math.floor(columnWidth / numVisibleClinics) : 0;

				clinicsObject.firstLeft = $view.find('[data-startDate="' + date + '"]').eq(0).css('left');

				return clinicsObject;
			},

			calculateSlotHeight: function (viewName, apptLength, defaultHeight) {
				defaultHeight = defaultHeight || 40;
				apptLength = apptLength || this.apptLength;

				var $view = $('.fc-view-' + viewName),
					slotHeight = $view.find('.fc-slot1').height() || defaultHeight;

				slotHeight = slotHeight / this.calendarRowMinutes;

				return (slotHeight * apptLength);
			},

			isVisible: function() {
				return this.$container.find(this.$el).length;
			},

	        populateDesiredDate: function () {
		        var desiredDateContext = DesiredDate.instance().get('desiredDate'),
			        apptRequestDate = AppointmentRequest.instance().get('optionDate1'),
//			        waitListEntry = WaitListEntry.instance(),
//			        EWLRequestDate = waitListEntry.get('desiredDate'),
//			        RecallRequestDate = waitListEntry.get('recallDate'),
//			        NEARRequestDate = waitListEntry.get('requestDate'),
			        desiredDate = desiredDateContext || apptRequestDate || /*EWLRequestDate || RecallRequestDate || NEARRequestDate ||*/ null;

		        return desiredDate ? formatDate(desiredDate) : "";
	        }
        });

		return CalendarView;
    }
);
