/**
 * 
 */
package sorteria.web.his.client.schedule;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import sorteria.domain.business.Holiday;
import sorteria.domain.scheduler.AbstractAppointment;
import sorteria.domain.scheduler.CalendarHelper;
import sorteria.domain.scheduler.GeneralAppointment;
import sorteria.domain.scheduler.LocationSPLink;
import sorteria.domain.scheduler.LocationSchedule;
import sorteria.domain.scheduler.Schedule;
import sorteria.domain.scheduler.ServiceProviderSchedule;
import sorteria.domain.scheduler.VisitAppointment;
import sorteria.web.commons.client.ApplicationShell;
import sorteria.web.commons.client.schedule.ScheduleModuleCommands;
import sorteria.web.commons.client.util.Prompt;
import sorteria.web.his.client.schedule.events.AbstractAppointmentEvent;
import sorteria.web.his.client.schedule.events.AppointmentUtil;
import sorteria.web.his.client.schedule.events.BusyAppointmentEvent;
import sorteria.web.his.client.schedule.events.CalendarEventOnMouseOver;
import sorteria.web.his.client.schedule.events.GeneralAppointmentEvent;
import sorteria.web.his.client.schedule.events.OnEventHover;
import sorteria.web.his.client.service.ScheduleServiceAsync;

import com.google.gwt.core.client.RunAsyncCallback;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.smartgwt.client.types.Positioning;
import com.smartgwt.client.types.TimeDisplayFormat;
import com.smartgwt.client.types.ViewName;
import com.smartgwt.client.util.SC;
import com.smartgwt.client.widgets.calendar.Calendar;
import com.smartgwt.client.widgets.calendar.CalendarEvent;
import com.smartgwt.client.widgets.calendar.events.BackgroundClickEvent;
import com.smartgwt.client.widgets.calendar.events.BackgroundClickHandler;
import com.smartgwt.client.widgets.calendar.events.CalendarEventChangedEvent;
import com.smartgwt.client.widgets.calendar.events.CalendarEventClick;
import com.smartgwt.client.widgets.calendar.events.CalendarEventRemoveClick;
import com.smartgwt.client.widgets.calendar.events.DayBodyClickEvent;
import com.smartgwt.client.widgets.calendar.events.DayBodyClickHandler;
import com.smartgwt.client.widgets.calendar.events.DayHeaderClickEvent;
import com.smartgwt.client.widgets.calendar.events.DayHeaderClickHandler;
import com.smartgwt.client.widgets.calendar.events.EventChangedHandler;
import com.smartgwt.client.widgets.calendar.events.EventClickHandler;
import com.smartgwt.client.widgets.calendar.events.EventRemoveClickHandler;
import com.smartgwt.client.widgets.events.ClickEvent;
import com.smartgwt.client.widgets.events.ClickHandler;
import com.smartgwt.client.widgets.events.DoubleClickEvent;
import com.smartgwt.client.widgets.events.DoubleClickHandler;
import com.smartgwt.client.widgets.events.DrawEvent;
import com.smartgwt.client.widgets.events.DrawHandler;
import com.smartgwt.client.widgets.events.DropEvent;
import com.smartgwt.client.widgets.events.DropHandler;
import com.smartgwt.client.widgets.events.HoverEvent;
import com.smartgwt.client.widgets.events.HoverHandler;
import com.smartgwt.client.widgets.events.ShowContextMenuEvent;
import com.smartgwt.client.widgets.events.ShowContextMenuHandler;
import com.smartgwt.client.widgets.menu.Menu;
import com.smartgwt.client.widgets.menu.MenuItem;
import com.smartgwt.client.widgets.menu.events.MenuItemClickEvent;

public class ScheduleCalendar
		extends Calendar implements 
		EventChangedHandler, EventClickHandler, DoubleClickHandler,
		BackgroundClickHandler, ClickHandler, DrawHandler, EventRemoveClickHandler, DropHandler, DayHeaderClickHandler, HoverHandler {

	protected ScheduleModule scheduleModule = null;
	protected Schedule schedule;
	protected Schedule parentSchedule;
	protected CalendarHelper calHelper;
	protected LocationSPLink locationSPLink;
	protected ViewName currentView;
	protected Menu contextMenu;
	protected MenuItem cutMenuItem;
	protected MenuItem hoverMenuItem;
	protected MenuItem pasteMenuItem;
	protected MenuItem openMenuItem;

	protected MenuItem addGeneralAppMenuItem;
	protected MenuItem addPaitentAppMenuItem;
	protected String tabNum;
	protected Date prevClick = null;
	protected Serializable prevAppId = null;
	protected HoverBannerBar bannerBar = null;

	protected ScheduleServiceAsync service = ScheduleServiceAsync.Util
			.getInstance();

	/**
	 * 
	 */

	protected ScheduleCalendar() {

		super();
	}

	public ScheduleCalendar(ScheduleModule scheduleModule, Schedule schedule) {

		super();
		this.scheduleModule = scheduleModule;
		this.schedule = schedule;
		this.currentView = scheduleModule.getCalendarView();
		loadCalendarHelper();
		loadEvents();
		initPage();
	}

	public ScheduleCalendar(ScheduleModule scheduleModule, Schedule schedule,
			LocationSPLink locationSPLink) {

		super();
		this.scheduleModule = scheduleModule;
		this.schedule = schedule;
		this.locationSPLink = locationSPLink;
		this.currentView = scheduleModule.getCalendarView();
		loadCalendarHelper();
		loadEvents();
		initPage();
	}

	public ScheduleCalendar(ScheduleModule scheduleModule, Schedule schedule,
			LocationSPLink locationSPLink, Schedule parentSchedule) {

		super();
		this.parentSchedule = parentSchedule;
		this.scheduleModule = scheduleModule;
		this.schedule = schedule;
		this.locationSPLink = locationSPLink;
		this.currentView = scheduleModule.getCalendarView();
	//	setScClassName("SCalendar");
		loadCalendarHelper();
		loadEvents();
		initPage();
	}

	@Override
	public void onClick(ClickEvent event) {

		event.cancel();
	}

	private void loadCalendarHelper() {

		service.findOperatingHoursForSchedule(
				ApplicationShell.getServiceContext(), schedule.getId(),
				scheduleModule.getLeftNavChosenDate(),
				new AsyncCallback<CalendarHelper>() {

					@Override
					public void onSuccess(CalendarHelper result) {

						calHelper = result;
					}

					@Override
					public void onFailure(Throwable caught) {

						Prompt.say("Calendar Helper Lookup " + ApplicationShell
								.getLocalizedErrorMessage(caught));
					}
				});

	}

	@Override
	public void onEventChanged(CalendarEventChangedEvent event) {

		if (event.getEvent() instanceof AbstractAppointmentEvent) {
			((AbstractAppointmentEvent) event.getEvent())
					.saveAppointment(scheduleModule);
		}
	}

	@Override
	public void onEventClick(CalendarEventClick event) {
	
		scheduleModule.setActiveSchedule(schedule);
		scheduleModule
				.setActiveCalenderAppointment(((AbstractAppointmentEvent) event
						.getEvent()).getAppointment());

		if (event.getEvent() instanceof GeneralAppointmentEvent) {
			scheduleModule
					.doCommand(ScheduleModuleCommands.CMD_EDIT_GENERAL_APPOINTMENT);
		}
		else {
			scheduleModule
					.doCommand(ScheduleModuleCommands.CMD_EDIT_PATIENT_APPOINTMENT);
		}
		event.cancel();
	}
	
	protected boolean checkDoubleClick(CalendarEventClick event){
		if (prevClick != null && prevAppId != null){
			long millis = (new Date()).getTime() - prevClick.getTime();
			System.out.println("Diff :" + millis);
			if (millis < 1000){
				if (prevAppId.equals(((AbstractAppointmentEvent) event
						.getEvent()).getAppointment().getId())){
					prevAppId = null;
					prevClick= null;
					return true;
				}
			}
		}
		prevClick = new Date();
		prevAppId = ((AbstractAppointmentEvent) event
				.getEvent()).getAppointment().getId();
		return false;
	}

	@Override
	public void onBackgroundClick(BackgroundClickEvent event) {

		event.cancel();
		scheduleModule.setActiveSchedule(schedule);
		scheduleModule.setSelectedStartTime(event.getStartDate());
		scheduleModule.setSelectedEndTime(event.getEndDate());
		scheduleModule.setAddAppointmentFromCalenderCells(true);
		//scheduleModule
		//		.doCommand(ScheduleModuleCommands.CMD_ADD_PATIENT_APPOINTMENT);

	}

	@Override
	public void onDoubleClick(DoubleClickEvent event) {
		if(!currentView.equals(ViewName.MONTH) ){
			scheduleModule
				.doCommand(ScheduleModuleCommands.CMD_ADD_PATIENT_APPOINTMENT);
		}
		
		event.cancel();
//		scheduleModule.setCalendarView(ViewName.DAY);
//		setChosenDate(scheduleModule.getSelectedStartTime());
//		scheduleModule.doCommand(ScheduleModuleCommands.CMD_CHANGE_TO_CALENDAR_VIEW);
	}

	public boolean isServiceProviderSchedule() {

		if (schedule instanceof LocationSchedule) {
			return false;
		}
		return true;
	}

	protected void pasteAndEditAppointment() {

		if (scheduleModule.getSelectedAppointmentEvent() instanceof GeneralAppointmentEvent) {
			service.findGeneralAppointmentById(scheduleModule
					.getSelectedAppointmentEvent().getAppointment().getId(),
					new AsyncCallback<GeneralAppointment>() {

						@Override
						public void onFailure(Throwable caught) {

						}

						@Override
						public void onSuccess(
								GeneralAppointment appointmentToPaste) {

							updateAppointmentonPaste(appointmentToPaste);
							scheduleModule
									.setActiveCalenderAppointment(appointmentToPaste);
							scheduleModule
									.setAfterEventPasteCallback(afterPasteEvent());
							scheduleModule
									.doCommand(ScheduleModuleCommands.CMD_PASTE_GENERAL_APPOINTMENT);

						}
					});

		}
		else {

			service.findVisitAppointmentById(scheduleModule
					.getSelectedAppointmentEvent().getAppointment().getId(),
					new AsyncCallback<VisitAppointment>() {

						@Override
						public void onFailure(Throwable caught) {

						}

						@Override
						public void onSuccess(
								VisitAppointment appointmentToPaste) {

							updateAppointmentonPaste(appointmentToPaste);
							scheduleModule
									.doCommand(ScheduleModuleCommands.CMD_EDIT_PATIENT_APPOINTMENT);
							scheduleModule.setSelectedAppointmentEvent(null);
							scheduleModule.setSourceCalendar(null);
						}
					});

		}

	}

	protected void updateAppointmentonPaste(GeneralAppointment appointmentToPaste) {

		appointmentToPaste
				.setEndDate(new Date(
						scheduleModule.getSelectedStartTime().getTime()
								+ (appointmentToPaste.getEndDate().getTime() - appointmentToPaste
										.getStartDate().getTime())));
		appointmentToPaste.setStartDate(scheduleModule.getSelectedStartTime());

		if (scheduleModule.getSourceCalendar().getSchedule().getId() != schedule
				.getId()) {

			if (appointmentToPaste.getSchedules() != null) {
				Iterator<Schedule> scheITr = appointmentToPaste.getSchedules()
						.iterator();
				boolean scheduleExists = false;
				while (scheITr.hasNext()) {

					Schedule s = scheITr.next();

					if (s.getId().equals(schedule.getId())) {
						scheduleExists = true;
					}
					if (s.getId().equals(
							scheduleModule.getSourceCalendar().getSchedule()
									.getId())
							&& scheduleModule.getSourceCalendar().getSchedule() instanceof ServiceProviderSchedule
							&& schedule instanceof ServiceProviderSchedule) {
						scheITr.remove();
					}

				}

				if (!scheduleExists) {
					appointmentToPaste.getSchedules().add(schedule);
				}
			}
		}

		scheduleModule.setActiveCalenderAppointment(appointmentToPaste);
		scheduleModule.setAfterEventPasteCallback(afterPasteEvent());

	}

	protected void updateAppointmentonPaste(VisitAppointment appointmentToPaste) {

		appointmentToPaste
				.setEndDate(new Date(
						scheduleModule.getSelectedStartTime().getTime()
								+ (appointmentToPaste.getEndDate().getTime() - appointmentToPaste
										.getStartDate().getTime())));
		appointmentToPaste.setStartDate(scheduleModule.getSelectedStartTime());

		if (scheduleModule.getSourceCalendar().getSchedule().getId() != schedule
				.getId()) {// can not past to same schedules
			if (schedule instanceof ServiceProviderSchedule) {
				if (appointmentToPaste.getSchedules() != null) {
					Iterator<Schedule> scheITr = appointmentToPaste.getSchedules()
							.iterator();

					while (scheITr.hasNext()) {
						Schedule s = scheITr.next();
						if (s instanceof ServiceProviderSchedule) {
							scheITr.remove();
						}
					}

					appointmentToPaste.getSchedules().add(schedule);
					appointmentToPaste.getVisit().setAttendingServiceProvider(
							((ServiceProviderSchedule) schedule).getServiceProvider());

				}
			}
		}

		scheduleModule.setActiveCalenderAppointment(appointmentToPaste);
		scheduleModule.setAfterEventPasteCallback(afterPasteEvent());

	}

	protected void initPage() {
		setEventSnapGap(15);
		setScClassName("SCalendar");
		addClickHandler(this);
		addBackgroundClickHandler(this);
		addEventChangedHandler(this);
		addEventClickHandler(this);
		addDoubleClickHandler(this);
		addEventRemoveClickHandler(this);
		addDayHeaderClickHandler(this);
		addDropHandler(this);
		setCanHover(true);
		setHoverAutoDestroy(true);
		setHoverDelay(1);
		setHoverWidth(300);
		//setHoverHeight(200);
		//setShowHoverComponents(true);
		
		this.addHoverHandler(new HoverHandler() {
			
			@Override
			public void onHover(HoverEvent event) {
				
				try{
					
					for(CalendarEvent eventHovered: ((Calendar)event.getSource()).getData()){
						
						if(eventHovered instanceof AbstractAppointmentEvent){
							AbstractAppointment abstractAppointment = ((AbstractAppointmentEvent) eventHovered).getAppointment();
							
							if(abstractAppointment instanceof VisitAppointment){
								HoverBannerBar bannerBar = new HoverBannerBar ((VisitAppointment)abstractAppointment);
								bannerBar.show();
							}
							
						}
						
					}
					
				}catch(ClassCastException e){
					//Prompt.error("class cast exception");
				}	
			}
		});
		
		this.addDayBodyClickHandler(new DayBodyClickHandler() {

			@Override
			public void onDayBodyClick(DayBodyClickEvent event) {
				
				if(event.isCancelled() && bannerBar.getInstance() != null){
					bannerBar.getInstance().destroy();
				}
				else{
					
					try{
						
						for(CalendarEvent eventHovered: event.getEvents()){
							
							if(eventHovered instanceof AbstractAppointmentEvent){
								AbstractAppointment abstractAppointment = ((AbstractAppointmentEvent) eventHovered).getAppointment();
								
								if(abstractAppointment instanceof VisitAppointment){
									bannerBar = new HoverBannerBar ((VisitAppointment)abstractAppointment);
									//setPrompt(bannerBar.toString());
									bannerBar.show();
								}
								
							}
							
						}
						
					}catch(ClassCastException e){
						//Prompt.error("class cast exception");
					}
					
				}
			}  	
		});
		
		addEventHoverHandler(new OnEventHover() {
			
			@Override
			public void onHover(CalendarEventOnMouseOver event) {
				SC.say("It worked");
		
			}
		});
		setDisableWeekends(false);
		setShowDateChooser(false);
		setShowDatePickerButton(false);
		setChosenDate(scheduleModule.getLeftNavChosenDate());
		setShowControlsBar(false);
		setShowWorkday(true);
		setAnimateTime(5);
		setTimeFormatter(TimeDisplayFormat.TOSHORT24HOURTIME);
		switch (scheduleModule.getCalendarView()) {
			case DAY:
				setShowDayView(true);
				setShowMonthView(false);
				setShowWeekView(false);
				break;
			case WEEK:
				setShowDayView(false);
				setShowMonthView(false);
				setShowWeekView(true);
				break;
			default:
				setShowDayView(false);
				setShowMonthView(true);
				setShowWeekView(false);
				setCanCreateEvents(false);
				break;
		}
		contextMenu = new Menu();

		cutMenuItem = new MenuItem("Cut");

		cutMenuItem
				.addClickHandler(new com.smartgwt.client.widgets.menu.events.ClickHandler() {

					@Override
					public void onClick(MenuItemClickEvent event) {

					}
				});
		
		hoverMenuItem = new MenuItem("Show Hover");
		openMenuItem = new MenuItem("Open");


		pasteMenuItem = new MenuItem("Paste");

		pasteMenuItem
				.addClickHandler(new com.smartgwt.client.widgets.menu.events.ClickHandler() {

					@Override
					public void onClick(MenuItemClickEvent event) {

						scheduleModule.setActiveSchedule(schedule);
						scheduleModule.setCutMenuItemClicked(false);
						if (scheduleModule.getSelectedAppointmentEvent() != null
								&& scheduleModule.getSourceCalendar() != null) {
							pasteAndEditAppointment();
						}
					}
				});

		addGeneralAppMenuItem = new MenuItem("Add General Appointment");

		addGeneralAppMenuItem
				.addClickHandler(new com.smartgwt.client.widgets.menu.events.ClickHandler() {

					@Override
					public void onClick(MenuItemClickEvent event) {

						scheduleModule.setActiveSchedule(schedule);
						scheduleModule
								.doCommand(ScheduleModuleCommands.CMD_ADD_GENERAL_APPOINTMENT);

					}
				});

		addPaitentAppMenuItem = new MenuItem("Add Patient Appointment");

		addPaitentAppMenuItem
				.addClickHandler(new com.smartgwt.client.widgets.menu.events.ClickHandler() {

					@Override
					public void onClick(MenuItemClickEvent event) {

						scheduleModule.setActiveSchedule(schedule);
						scheduleModule
								.doCommand(ScheduleModuleCommands.CMD_ADD_PATIENT_APPOINTMENT);

					}
				});
		contextMenu.setItems(cutMenuItem, addGeneralAppMenuItem,
				addPaitentAppMenuItem);
		if (scheduleModule.getCalendarView() != ViewName.MONTH) {
			setContextMenu(contextMenu);
			
		addShowContextMenuHandler(new ShowContextMenuHandler() {

			@Override
			public void onShowContextMenu(final ShowContextMenuEvent event) {

				event.cancel();
				boolean hoverEnable = false;
				if (scheduleModule.getCalendarView().name().equals(ViewName.MONTH)) {
					return;
				}
				// required as selected time does not gives right time when
				// clicked on context menu item
				scheduleModule.setSelectedStartTime(ScheduleCalendar.this
						.getActiveTime());
				scheduleModule.setSelectedEndTime(null);
				scheduleModule.setAddAppointmentFromCalenderCells(true);

				CalendarEvent[] calEvents = ScheduleCalendar.this.getData();
				Menu cutSubMenu = new Menu();
				Menu hoverSubMenu = new Menu();
				Menu openSubMenu = new Menu();
				boolean eventExist = false;
				for (int i = 0; i < calEvents.length; i++) {
					if (!(calEvents[i] instanceof AbstractAppointmentEvent) || (calEvents[i] instanceof BusyAppointmentEvent))
						continue;
					final AbstractAppointmentEvent calEvent = (AbstractAppointmentEvent) calEvents[i];
					if (calEvent.getStartDate().equals(
							scheduleModule.getSelectedStartTime())
							|| (calEvent.getStartDate().before(
									scheduleModule.getSelectedStartTime()) && calEvent
									.getEndDate().after(
											scheduleModule
													.getSelectedStartTime()))) {
						eventExist = true;

						MenuItem cutSubMenuItem = new MenuItem("" + calEvent.getName());
						cutSubMenuItem.setAttribute("SELECTED_APPOINTMENT_ID",
								calEvent.getAppointment().getId().toString());
						cutSubMenuItem.setAttribute("SELECTED_EVENT", calEvent);

						cutSubMenuItem
								.addClickHandler(new com.smartgwt.client.widgets.menu.events.ClickHandler() {

									@Override
									public void onClick(MenuItemClickEvent event) {

										scheduleModule.setActiveSchedule(schedule);
										scheduleModule
												.setCutMenuItemClicked(true);
										scheduleModule
												.setSelectedAppointmentEvent(calEvent);
										scheduleModule
												.setSourceCalendar(ScheduleCalendar.this);

									}
								});
						cutSubMenu.addItem(cutSubMenuItem);
						if (!(calEvent instanceof GeneralAppointmentEvent)) {
						
							MenuItem hoverSubMenuItem = new MenuItem("" + calEvent.getName());
							hoverSubMenuItem.setAttribute("SELECTED_APPOINTMENT_ID",
									calEvent.getAppointment().getId().toString());
							hoverSubMenuItem.setAttribute("SELECTED_EVENT", calEvent);
	
							hoverSubMenuItem
									.addClickHandler(new com.smartgwt.client.widgets.menu.events.ClickHandler() {
	
										@Override
										public void onClick(MenuItemClickEvent clickEvent) {
											AbstractAppointment app = calEvent.getAppointment();
											if (app instanceof VisitAppointment){
												VisitAppointment vapp = (VisitAppointment) app;
												 HoverBannerBar banner = new HoverBannerBar(vapp);
												 banner.enableCloseOnClick();
												 banner.setPosition(Positioning.ABSOLUTE);
												 banner.setLeft(event.getX());
												 banner.setTop(event.getY());
												 banner.show(); 
											}
										}
									});
							hoverSubMenu.addItem(hoverSubMenuItem);
							hoverEnable = true;
						}
						
						MenuItem openSubMenuItem = new MenuItem("" + calEvent.getName());
						openSubMenuItem.setAttribute("SELECTED_APPOINTMENT_ID",
								calEvent.getAppointment().getId().toString());
						openSubMenuItem.setAttribute("SELECTED_EVENT", calEvent);

						openSubMenuItem
								.addClickHandler(new com.smartgwt.client.widgets.menu.events.ClickHandler() {

									@Override
									public void onClick(MenuItemClickEvent event) {
										scheduleModule.setActiveSchedule(schedule);
										scheduleModule.setActiveCalenderAppointment(calEvent.getAppointment());

										if (calEvent instanceof GeneralAppointmentEvent) {
											scheduleModule
													.doCommand(ScheduleModuleCommands.CMD_EDIT_GENERAL_APPOINTMENT);
										}
										else {
											scheduleModule
													.doCommand(ScheduleModuleCommands.CMD_EDIT_PATIENT_APPOINTMENT);
										}
									}
								});
						openSubMenu.addItem(openSubMenuItem);

					}

				}
				if (scheduleModule.isCutMenuItemClicked()) {

					if (eventExist) {
						if (!hoverEnable){
							cutMenuItem.setSubmenu(cutSubMenu);
							openMenuItem.setSubmenu(openSubMenu);
							contextMenu.setItems(openMenuItem,cutMenuItem, pasteMenuItem,
									addGeneralAppMenuItem, addPaitentAppMenuItem);
						} else {
							cutMenuItem.setSubmenu(cutSubMenu);
							hoverMenuItem.setSubmenu(hoverSubMenu);
							openMenuItem.setSubmenu(openSubMenu);
							contextMenu.setItems(openMenuItem,cutMenuItem, pasteMenuItem,
									addGeneralAppMenuItem, addPaitentAppMenuItem, hoverMenuItem);
						}

					}
					else {

						contextMenu.setItems(pasteMenuItem,
								addGeneralAppMenuItem, addPaitentAppMenuItem);
					}

				}
				else {

					if (eventExist) {
						if (!hoverEnable){
							cutMenuItem.setSubmenu(cutSubMenu);
							openMenuItem.setSubmenu(openSubMenu);
							contextMenu.setItems(openMenuItem, cutMenuItem,
									addGeneralAppMenuItem, addPaitentAppMenuItem);
						} else {
							hoverMenuItem.setSubmenu(hoverSubMenu);
							cutMenuItem.setSubmenu(cutSubMenu);
							openMenuItem.setSubmenu(openSubMenu);
							contextMenu.setItems(openMenuItem, cutMenuItem,
									addGeneralAppMenuItem, addPaitentAppMenuItem, hoverMenuItem);
						}

					}
					else {

						contextMenu.setItems(addGeneralAppMenuItem,
								addPaitentAppMenuItem);
					}
				}

				// }
				// if (ScheduleCalendar.this.selectedEvent == null) {
				//

				//
				// }
				// else {

				// Menu openSubMenu = new Menu();
				// MenuItem openSubMenuItem = new MenuItem(
				// selectedEvent.getName());
				// openSubMenu.addItem(openSubMenuItem);
				// openMenuItem.setSubmenu(openSubMenu);
				// contextMenu.setItems(cutMenuItem, addGeneralAppMenuItem,
				// addPaitentAppMenuItem);
				// }

				contextMenu.setPosition(Positioning.ABSOLUTE);
				contextMenu.setLeft(event.getX());
				contextMenu.setTop(event.getY());
				contextMenu.show();

			}
		});
		}
	}

	@Override
	protected String getDayBodyHTML(Date date, CalendarEvent[] events, Calendar calendar,
			int rowNum, int colNum) {

		if (scheduleModule.getCalendarView().equals(ViewName.MONTH)) {
			int rowcount = 0;
			boolean styleHoliday = false;
			boolean styleWorkday = false;
			boolean styleWorkHoliday = false;
			boolean styleClosed = false;

			String workDay = "#c2e3ea>";
			String closed = "#fbe0d5>";
			String holidays = "#fefbac>";
			String workHoliday = "#81a8b0>";
			String returnStr = "";

			String startStr = "<table height='100%' width='100%' bgcolor=";

			// String startStr =
			// "<table height='100%' width='100%' bgcolor=#FFFF22>";
			if (calHelper != null) {

				final DateTimeFormat dateFormatter = DateTimeFormat.getFormat("yyyyMMdd");
				String strDate = dateFormatter.format(date);
				Integer dayInt = new Integer(strDate);
				if (calHelper.getHolidays() != null) {
					if (calHelper.getHolidays().containsKey(dayInt)) {
						Holiday holiday = calHelper.getHolidays().get(dayInt);
						if (holiday.isNormalWorkingDay()) {
							styleWorkHoliday = true;
						}
						else {
							styleHoliday = true;
						}
						returnStr = returnStr.concat("<tr><td>" + holiday.getName()
								+ "</td></tr>");
						rowcount++;
					}
				}
				@SuppressWarnings("deprecation")
				int dayOfWeek = date.getDay() + 1;
				dayInt = new Integer(dayOfWeek);
				if (calHelper.getOperationalHours() != null) {
					if (calHelper.getOperationalHours().containsKey(dayInt)) {
						if (calHelper.getOperationalHours().get(dayInt) == null
								|| calHelper.getOperationalHours().get(dayInt)
										.isEmpty()) {
							styleClosed = true;
							rowcount++;
							returnStr = returnStr.concat("<tr><td>Closed</td></tr>");
						}
						else {
							styleWorkday = true;
						}
					}
					else {
						rowcount++;
						returnStr = returnStr.concat("<tr><td>Closed</td></tr>");
					}
				}
			}

			// Place holder for creating summary for calendar;
			if (events != null && events.length > 0) {
				rowcount++;
				returnStr = returnStr.concat("<tr><td>" + events.length + " "
						+ MsgSchedule.LABEL_APPOINTMENT_001.getMessage())
						+ "</td></tr>";
			}
			for (int i = rowcount; i < 7; i++) {
				returnStr = returnStr
						.concat("<tr height='10' width='100%'><td>&nbsp</td></tr>");
			}
			returnStr = returnStr.concat("</table>");
			if (styleWorkHoliday) {
				startStr = startStr.concat(workHoliday);
			}
			else if (styleHoliday) {
				startStr = startStr.concat(holidays);
			}
			else if (styleClosed) {
				startStr = startStr.concat(closed);
			}
			else {
				startStr = startStr.concat(workDay);
			}
			return startStr + returnStr;

		}

		return super.getDayBodyHTML(date, events, calendar, rowNum, colNum);

		// return returnStr;
	}

	@Override
	public String getDayBodyBaseStyle() {

		if (scheduleModule.getCalendarView().equals(ViewName.MONTH)) {
			// Hook for updating the style for month view.
			return super.getDayBodyBaseStyle();
		}
		return super.getDayBodyBaseStyle();
	}

	public void reloadData(Date date) {

	}

	public void loadEvents() {

		Date currentDate = scheduleModule.getLeftNavChosenDate();
		ViewName view = scheduleModule.getCalendarView();
		setData(AppointmentUtil.generateNullEvents());

		service.findAppointmentsForSchedule(ApplicationShell.getServiceContext(),
				currentDate, view.toString(), schedule.getId(),
				scheduleModule.getStatusFilter(),
				new AsyncCallback<List<AbstractAppointment>>() {

					@Override
					public void onSuccess(List<AbstractAppointment> result) {

						if (result != null && !result.isEmpty()) {
							if (parentSchedule != null) {
								setData(AppointmentUtil.generateCalendarEvents(result, parentSchedule));
							}
							else {
								setData(AppointmentUtil.generateCalendarEvents(result));
							}			
							if (scheduleModule.getSearchAppointmentID() != null){
								for (CalendarEvent event : getData()){
									if (event instanceof AbstractAppointmentEvent) {
										AbstractAppointmentEvent aae = (AbstractAppointmentEvent) event;
										if (aae.getAppointment()!= null && aae.getAppointment().getId().equals(scheduleModule.getSearchAppointmentID())){
											selectRecord(aae);
											scheduleModule.setSearchAppointmentID(null);
										}
									}
								}
							}	
						}
						else {
							setData(AppointmentUtil.generateNullEvents());
						}
						redraw();
						ApplicationShell.getInstance().hideProgressBar();
					}

					@Override
					public void onFailure(Throwable caught) {

						Prompt.say(ApplicationShell
								.getLocalizedErrorMessage(caught));
					}
				});
	}

	public ViewName getCurrentView() {

		return currentView;
	}

	public void setCurrentView(ViewName currentView) {

		this.currentView = currentView;
	}

	public Schedule getSchedule() {

		return schedule;
	}

	public void setSchedule(Schedule schedule) {

		this.schedule = schedule;
	}

	public String getTabNum() {

		return tabNum;
	}

	public void setTabNum(String tabNum) {

		this.tabNum = tabNum;
	}

	public LocationSPLink getLocationSPLink() {

		return locationSPLink;
	}

	public CalendarHelper getCalHelper() {

		return calHelper;
	}

	public void removeCalendarEvent(AbstractAppointmentEvent eventToRemove) {

		List<CalendarEvent> calendarEvents = new ArrayList<CalendarEvent>(
				Arrays.asList(getData()));
		Iterator<CalendarEvent> iteratorEvents = calendarEvents.iterator();
		while (iteratorEvents.hasNext()) {
			AbstractAppointmentEvent calendarEvent = (AbstractAppointmentEvent) iteratorEvents
					.next();
			if (calendarEvent.getEventId() != null
					&& calendarEvent.getAppointment().getId()
							.equals(eventToRemove.getAppointment().getId()))
				iteratorEvents.remove();
		}

		CalendarEvent[] events = calendarEvents
				.toArray(new CalendarEvent[calendarEvents.size()]);
		setData(events);

	}

	public void addCalendarEvent(AbstractAppointmentEvent event) {

		List<CalendarEvent> calendarEvents = new ArrayList<CalendarEvent>(
				Arrays.asList(this.getData()));
		calendarEvents.add(event);

		CalendarEvent[] events = calendarEvents
				.toArray(new CalendarEvent[calendarEvents.size()]);
		setData(events);

	}

	protected RunAsyncCallback afterPasteEvent() {

		return new RunAsyncCallback() {

			@Override
			public void onFailure(Throwable reason) {

				String errorMessage = ApplicationShell
						.getLocalizedErrorMessage(reason);
				Prompt.error(errorMessage);
			}

			@Override
			public void onSuccess() {

				if (scheduleModule.getSelectedAppointmentEvent() != null
						&& scheduleModule.getSourceCalendar() != null) {

					// no need to add it to calender its already being refreshed
					// on save of appointment
					// scheduleModule.getSourceCalendar().removeCalendarEvent(
					// scheduleModule.getSelectedAppointmentEvent());
					// ScheduleCalendar.this.addCalendarEvent(scheduleModule
					// .getSelectedAppointmentEvent());

					scheduleModule.setSelectedAppointmentEvent(null);
					scheduleModule.setSourceCalendar(null);

				}
			}

		};

	}

	@Override
	public void onDraw(DrawEvent event) {

		System.out.println(getRowHeight());
	}

	@Override
	public void onEventRemoveClick(CalendarEventRemoveClick event) {

		event.cancel();
	}

	@Override
	public void onDrop(DropEvent event) {
		event.getSource();
	}

	@Override
	public void onDayHeaderClick(DayHeaderClickEvent event) {
		
		scheduleModule.setLeftNavChosenDate(event.getDate());
		scheduleModule.setCalendarView(ViewName.DAY);
		scheduleModule.doCommand(ScheduleModuleCommands.CMD_SET_DATE);
		scheduleModule.doCommand(ScheduleModuleCommands.CMD_REFRESH_CALENDAR_VIEW);

	}
	
	/**
     * Add a addEventHoverHandler handler.
     * <p>
     * Called whenever the close icon of an event is clicked within the day or week view. Call {@link com.smartgwt.client.widgets.calendar.events.CalendarEventRemoveClick#cancel()} from within {@link EventRemoveClickHandler#onEventRemoveClick} to cancel the removal,
     * or . <P> Implement this method to do something like, for example, showing a confirmation dialog  before
     * an event is removed.
     *
     * @param handler the eventRemoveClick handler
     * @return {@link HandlerRegistration} used to remove this handler
     */
    public HandlerRegistration addEventHoverHandler(sorteria.web.his.client.schedule.events.OnEventHover handler) {
    	if(getHandlerCount(sorteria.web.his.client.schedule.events.CalendarEventOnMouseOver.getType()) == 0) setupEventHoverEvent();
        return doAddHandler(handler, sorteria.web.his.client.schedule.events.CalendarEventOnMouseOver.getType());
    }
    
	
	private native void setupEventHoverEvent() /*-{
	    var obj = null;
	    var selfJ = this;
	    if(this.@com.smartgwt.client.widgets.BaseWidget::isCreated()()) {
	     	 obj = this.@com.smartgwt.client.widgets.BaseWidget::getJsObj()();
	         obj.addProperties({hover:$debox($entry(function(){
	                    var param = {"event" : arguments[0], "viewName" : arguments[1]};
	                 	var event = @sorteria.web.his.client.schedule.events.CalendarEventOnMouseOver::new(Lcom/google/gwt/core/client/JavaScriptObject;)(param);
	                 	selfJ.@com.smartgwt.client.widgets.BaseWidget::fireEvent(Lcom/google/gwt/event/shared/GwtEvent;)(event);
	                 	var ret = event.@com.smartgwt.client.event.Cancellable::isCancelled()();
	                 	return !ret;
	                }))
	         });
	    } else {
	        obj = this.@com.smartgwt.client.widgets.BaseWidget::getConfig()();
	        obj.hover = $debox($entry(function(){
	               var param = {"event" : arguments[0], "viewName" : arguments[1]};
	               var event = @sorteria.web.his.client.schedule.events.CalendarEventOnMouseOver::new(Lcom/google/gwt/core/client/JavaScriptObject;)(param);
	               selfJ.@com.smartgwt.client.widgets.BaseWidget::fireEvent(Lcom/google/gwt/event/shared/GwtEvent;)(event);
	               var ret = event.@com.smartgwt.client.event.Cancellable::isCancelled()();
	               return !ret;
	           }));
	    }
	}-*/;

	@Override
	public void onHover(HoverEvent event) {

		if(event.isCancelled()){
			bannerBar.getInstance().destroy();
			
		}
		else{
			
			try{
				
				for(CalendarEvent eventHovered: ((Calendar)event.getSource()).getData()){
					
					if(eventHovered instanceof AbstractAppointmentEvent){
						AbstractAppointment abstractAppointment = ((AbstractAppointmentEvent) eventHovered).getAppointment();
						
						if(abstractAppointment instanceof VisitAppointment){
							bannerBar = new HoverBannerBar ((VisitAppointment)abstractAppointment);
							setPrompt(bannerBar.toString());
							bannerBar.show();
						}
						
					}
					
				}
				
			}catch(ClassCastException e){
				//Prompt.error("class cast exception");
			}
		}
		
	}
	
      
	
}
