package org.inria.bmajwatcher.client.ui.scheduler;

import java.util.Date;
import java.util.Map;
import java.util.Set;

import org.inria.bmajwatcher.client.services.SchedulingServiceAsync;
import org.inria.bmajwatcher.client.ui.styles.Resources;

import com.bradrydzewski.gwt.calendar.client.Appointment;
import com.bradrydzewski.gwt.calendar.client.AppointmentStyle;
import com.bradrydzewski.gwt.calendar.client.Calendar;
import com.bradrydzewski.gwt.calendar.client.CalendarViews;
import com.bradrydzewski.gwt.calendar.client.event.UpdateEvent;
import com.bradrydzewski.gwt.calendar.client.event.UpdateHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.logical.shared.OpenEvent;
import com.google.gwt.event.logical.shared.OpenHandler;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;
import com.google.gwt.event.logical.shared.ShowRangeEvent;
import com.google.gwt.event.logical.shared.ShowRangeHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DecoratedTabPanel;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.datepicker.client.CalendarUtil;
import com.google.gwt.user.datepicker.client.DatePicker;
import com.smartgwt.client.util.SC;

/**
 * 
 * Component that displays the scheduled tasks in a calendar.

 * @author rsabas
 *
 */
public class TaskViewer extends DialogBox {
	
	public static int MONTHLY = 0;
	public static int WEEKLY = 4;
	
	private int mode = WEEKLY;
	private boolean init = true;
	
	public TaskViewer(final String user) {
		super(false, false);
		setHTML("<b>Calendar view</b>");
		
		VerticalPanel mainPanel = new VerticalPanel();
		final VerticalPanel monthPnl = new VerticalPanel();
		final VerticalPanel weekPnl = new VerticalPanel();
		
		final Calendar cal = new Calendar();
		cal.setDate(new Date());
		cal.setSize("800px", "500px");
		cal.addOpenHandler(new OpenHandler<Appointment>() {
			
			@Override
			public void onOpen(OpenEvent<Appointment> event) {
				showApptDetail(event.getTarget());
			}
		});
		cal.addUpdateHandler(new UpdateHandler<Appointment>() {
			// Disabling drag and drop
			@Override
			public void onUpdate(UpdateEvent<Appointment> event) {
				event.setCancelled(true);
			}
		});
		
		
		DatePicker datePicker = new DatePicker();
		datePicker.setValue(new Date());
		datePicker.addStyleName(Resources.INSTANCE.mainCss().datePicker());
		datePicker.addValueChangeHandler(new ValueChangeHandler<Date>() {
			
			@Override
			public void onValueChange(ValueChangeEvent<Date> event) {
				cal.setDate(event.getValue());
				loadJobs(user, cal, mode);
			}
		});
		datePicker.addShowRangeHandler(new ShowRangeHandler<Date>() {
			
			@Override
			public void onShowRange(ShowRangeEvent<Date> event) {
				if (!init) { // To do if not first display, otherwise current date
					// will be overriden by first day of the month.
					long week = 3600 * 24 * 7 * 1000;
					Date dt = new Date(event.getStart().getTime() + week);
					CalendarUtil.setToFirstDayOfMonth(dt);
					cal.setDate(dt);
					loadJobs(user, cal, mode);
				}
				init = false;
			}
		});
		
		DecoratedTabPanel tabPanel = new DecoratedTabPanel();
		tabPanel.add(weekPnl, "4 days");
		tabPanel.add(monthPnl, "Month");
		tabPanel.addSelectionHandler(new SelectionHandler<Integer>() {
			
			@Override
			public void onSelection(SelectionEvent<Integer> event) {
				if (event.getSelectedItem() == 0) {
					mode = WEEKLY;
					monthPnl.clear();
					weekPnl.add(cal);
					loadJobs(user, cal, mode);
					cal.setView(CalendarViews.DAY, WEEKLY);
				} else {
					mode = MONTHLY;
					weekPnl.clear();
					monthPnl.add(cal);
					loadJobs(user, cal, mode);
					cal.setView(CalendarViews.MONTH);
				}
			}
		});
		tabPanel.selectTab(0);
		
		Button close = new Button("Close");
		close.addClickHandler(new ClickHandler() {
			
			@Override
			public void onClick(ClickEvent event) {
				hide();
			}
		});
		
		
		HorizontalPanel datePanel = new HorizontalPanel();
		/*
		VerticalPanel vp = new VerticalPanel();
		vp.setHorizontalAlignment(HasAlignment.ALIGN_RIGHT);
		vp.add(datePicker);
		DynamicForm form = new DynamicForm();
		StaticTextItem label = new StaticTextItem();
		label.setShowTitle(false);
		DateItem manualDate = new DateItem("manualDate", "Manual date selection");
		manualDate.setShowPickerIcon(false);
		ButtonItem btn = new ButtonItem("btnDate", "Show");
		btn.setAlign(Alignment.CENTER);
		form.setItems(manualDate, btn);
		form.setTitleOrientation(TitleOrientation.TOP);
		Canvas cvs = new Canvas();
		cvs.addChild(form);
		vp.add(cvs);*/
		
		datePanel.add(datePicker);
		datePanel.add(tabPanel);
		
		mainPanel.add(datePanel);
		mainPanel.add(close);
		mainPanel.setCellHorizontalAlignment(close, HasAlignment.ALIGN_RIGHT);
		
		add(mainPanel);
		
		addStyleName(Resources.INSTANCE.mainCss().calendar());
	}
	
	private void showApptDetail(Appointment appt) {
		final DialogBox db = new DialogBox();
		VerticalPanel vp = new VerticalPanel();
		db.setModal(false);
		db.addStyleName(Resources.INSTANCE.mainCss().apptDetail());
		db.setHTML("<b>" + appt.getTitle() + "</b>");
//		String[] split = appt.getDescription().split(",");
		if (appt.getLocation() != null) {
			if (appt.getTitle().equals("Session logs")) {
				HTML html = new HTML(appt.getLocation());
				vp.add(new Label("Sessions on " + DateTimeFormat.getFormat("yyyy/MM/dd").format(appt.getStart())));
				vp.add(html);
			} else {
				String[] split = appt.getLocation().split(",");
				String htmlString = "<ul>";
				for (String bank : split)
					htmlString += "<li>" + bank + "</li>";
				htmlString += "</ul>";
				HTML html = new HTML(htmlString);
				vp.add(html);
			}
		} else {
			vp.add(new Label("No bank"));
		}
		Anchor close = new Anchor("Close");
		close.addClickHandler(new ClickHandler() {
			
			@Override
			public void onClick(ClickEvent event) {
				db.hide();
			}
		});
		vp.add(close);
		
		db.setWidget(vp);
		db.center();
	}

	private void loadJobs(String user, final Calendar cal, int range) {
		cal.clearAppointments();
		
		SchedulingServiceAsync.INSTANCE.getJobsDates(user, cal.getDate(), range, new AsyncCallback<Map<Date,String>>() {
			
			@Override
			public void onSuccess(Map<Date, String> result) {
				Set<Date> keys = result.keySet();
				cal.suspendLayout();
				for (Date d : keys) {
					Appointment appt = new Appointment();
					appt.setStyle(AppointmentStyle.STEELE_BLUE);
					appt.setStart(d);
					appt.setEnd(new Date(d.getTime() + (1 * 60 * 60 * 1000)));
					String content = result.get(d);
					String[] split = content.split("_:_");
					if (split[0].equals("Session logs"))
						appt.setAllDay(true);
						
					appt.setTitle(split[0]);
					if (split.length > 1)
						appt.setLocation(split[1]);
					
					cal.addAppointment(appt);
				}
				cal.resumeLayout();
			}
			
			@Override
			public void onFailure(Throwable caught) {
				SC.warn("Failure !");
			}
		});
	}
}
