/*
 * Licensed to The Apereo Foundation under one or more contributor license
 * agreements. See the NOTICE file distributed with this work for
 * additional information regarding copyright ownership.
 *
 * The Apereo Foundation licenses this file to you under the Apache License,
 * Version 2.0 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at:
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
*/
package org.unitime.timetable.gwt.client.rooms;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import org.unitime.timetable.gwt.client.page.UniTimeNotifications;
import org.unitime.timetable.gwt.client.widgets.P;
import org.unitime.timetable.gwt.client.widgets.SimpleForm.HasMobileScroll;
import org.unitime.timetable.gwt.client.widgets.UniTimeConfirmationDialog;
import org.unitime.timetable.gwt.command.client.GwtRpcService;
import org.unitime.timetable.gwt.command.client.GwtRpcServiceAsync;
import org.unitime.timetable.gwt.resources.GwtConstants;
import org.unitime.timetable.gwt.resources.GwtMessages;
import org.unitime.timetable.gwt.shared.RoomInterface;
import org.unitime.timetable.gwt.shared.RoomInterface.PeriodInterface;
import org.unitime.timetable.gwt.shared.RoomInterface.PeriodPreferenceModel;
import org.unitime.timetable.gwt.shared.RoomInterface.PreferenceInterface;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.MouseDownEvent;
import com.google.gwt.event.dom.client.MouseDownHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HasValue;
import com.google.gwt.user.client.ui.Hidden;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.datepicker.client.CalendarUtil;

/**
 * @author Tomas Muller
 */
public class PeriodPreferencesWidget extends Composite implements HasValue<PeriodPreferenceModel>, HasMobileScroll {
	private static GwtRpcServiceAsync RPC = GWT.create(GwtRpcService.class);
	private static final GwtConstants CONSTANTS = GWT.create(GwtConstants.class);
	private static final GwtMessages MESSAGES = GWT.create(GwtMessages.class);
	private AbsolutePanel iPanel;
	private PreferenceInterface iPreference = null;
	private P iSelectedIcon = null, iSelectedTitle = null;
	private PeriodPreferenceModel iModel;
	protected boolean iEditable = true;
	private CheckBox iHorizontal;
	private List<Cell> iCells = new ArrayList<Cell>();
	
	public PeriodPreferencesWidget(boolean editable) {
		iEditable = editable;

		iPanel = new AbsolutePanel();
		
		iHorizontal = new CheckBox(MESSAGES.periodPreferenceHorizontal());
		iHorizontal.addValueChangeHandler(new ValueChangeHandler<Boolean>() {
			@Override
			public void onValueChange(ValueChangeEvent<Boolean> event) {
				RoomCookie.getInstance().setHorizontal(iHorizontal.getValue());
				render();
			}
		});
		
		initWidget(iPanel);
	}
	
	public AbsolutePanel getPanel() { return iPanel; }
	
	public boolean isEditable() {
		return iEditable && iModel != null;
	}
	
	public void setEditable(boolean editable) {
		iEditable = editable;
	}
	
	public boolean isEditable(PreferenceInterface preference) {
		return isEditable() && preference.isEditable();
	}
	
	public boolean isEditable(int day, int slot) {
		return isEditable() && iModel.getPeriod(day, slot) != null;
	}
	
	public PeriodPreferenceModel getModel() {
		return iModel;
	}
	
	public boolean isHorizontal() {
		return iHorizontal.getValue();
	}
	
	public void setHorizontal(boolean horizontal) {
		iHorizontal.setValue(horizontal);
		RoomCookie.getInstance().setHorizontal(horizontal);
		render();
	}
	
	public void setModel(PeriodPreferenceModel model) {
		iModel = model;
		if (RoomCookie.getInstance().hasOrientation())
			iHorizontal.setValue(RoomCookie.getInstance().areRoomsHorizontal());
		else
			iHorizontal.setValue(model.isDefaultHorizontal());
		
		iPreference = iModel.getSelectedPreference();
		if (iPreference == null) iPreference = iModel.getPreferences().get(0);
		render();
	}
	
	public void insert(final RootPanel panel, Long eventAvailability) {
		String[] ids = panel.getElement().getInnerHTML().trim().split(":");
		Long locationId = Long.valueOf(ids[0]);
		Long examTypeId = Long.valueOf(ids[1]);
		RPC.execute(RoomInterface.PeriodPreferenceRequest.load(locationId, examTypeId), new AsyncCallback<PeriodPreferenceModel>() {
			@Override
			public void onFailure(Throwable caught) {
				UniTimeNotifications.error(MESSAGES.failedToLoadPeriodPreferences(caught.getMessage()));
			}

			@Override
			public void onSuccess(PeriodPreferenceModel result) {
				panel.getElement().setInnerText(null);
				setModel(result);
				panel.add(PeriodPreferencesWidget.this);
				panel.setVisible(true);
			}
		});
	}
	
	public static String slot2short(int slot) {
		int h = slot / 12;
        int m = 5 * (slot % 12);
        if (CONSTANTS.useAmPm())
        	return (h > 12 ? h - 12 : h) + ":" + (m < 10 ? "0" : "") + m + (h == 24 ? "a" : h >= 12 ? "p" : "a");
        else
			return h + ":" + (m < 10 ? "0" : "") + m;
	}
	
	private class Cell extends P {
		private int iDay, iSlot;
		private Date iDate;
		private PeriodInterface iPeriod;
		
		Cell(int day, int slot, Date date, PeriodInterface period) {
			super("cell", "item", isEditable() && period != null ? "clickable" : null, period == null ? "disabled" : null, period != null && iModel.isAssigned(period) ? "highlight" : null);
			iDay = day;
			iSlot = slot;
			iDate = date;
			iPeriod = period;
			if (period != null) {
				PreferenceInterface preference = iModel.getPreference(day, slot);
				if (preference == null) {
					getElement().getStyle().clearBackgroundColor();
					setHTML("");
					setTitle("");
				} else {
					getElement().getStyle().setBackgroundColor(preference.getColor());
					setTitle(DateTimeFormat.getFormat(CONSTANTS.examPeriodDateFormat()).format(date) + " " + slot2short(slot) + (period == null ? "" : " - " + slot2short(slot + period.getLength())) + ": " + preference.getName());
				}
				if (isEditable())
					addMouseDownHandler(new MouseDownHandler() {
						@Override
						public void onMouseDown(MouseDownEvent event) {
							setOption(iPreference);
						}
					});				
			}
		}
		
		public PeriodInterface getPeriod() { return iPeriod; }
		
		public void setOption(PreferenceInterface preference) {
			setOption(preference, true);
		}
		
		public void setOption(PreferenceInterface preference, boolean fireChangeEvent) {
			if (!isEditable() || iPeriod == null) return;
			if (preference != null && fireChangeEvent) {
				if (preference.getCode().equals("R")) {
					if (iModel.hasPreference()) {
						PreferenceInterface p = iModel.getPreference("0");
						for (Cell cell: iCells) {
							if (cell.getPeriod() != null) {
								PreferenceInterface pref = iModel.getPreference(cell.getPeriod().getDay(), cell.getPeriod().getStartSlot());
								if (pref != null) cell.setOption(p, false);
							}
						}
					}
				} else if (!preference.getCode().equals("0")) {
					if (iModel.hasRequired()) {
						PreferenceInterface p = iModel.getDefaultPreference();
						for (Cell cell: iCells) {
							if (cell.getPeriod() != null) {
								PreferenceInterface pref = iModel.getPreference(cell.getPeriod().getDay(), cell.getPeriod().getStartSlot());
								if (pref != null) cell.setOption(p, false);
							}
						}
					}
				}
			}
			iModel.setPreference(iDay, iSlot, preference);
			if (preference == null) {
				getElement().getStyle().clearBackgroundColor();
				setHTML("");
				setTitle("");
			} else {
				getElement().getStyle().setBackgroundColor(preference.getColor());
				setTitle(DateTimeFormat.getFormat(CONSTANTS.examPeriodDateFormat()).format(iDate) + " " + slot2short(iSlot) + " - " + slot2short(iSlot + iPeriod.getLength()) + ": " + preference.getName());
			}
			if (fireChangeEvent) ValueChangeEvent.fire(PeriodPreferencesWidget.this, getValue());
		}
	}
	
	private class D extends P {
		private int iDay, iSlot;
		private Date iDate;
		private PeriodInterface iPeriod;
		
		private D(int day, int slot, Date date, PeriodInterface period) {
			super("cell", "day", isEditable() && period != null ? "clickable" : null, period == null ? "unavailable" : null);
			iDay = day;
			iSlot = slot;
			iDate = date;
			iPeriod = period;
			setText(DateTimeFormat.getFormat("d").format(date));
			if (period != null) {
				PreferenceInterface preference = iModel.getPreference(day, slot);
				if (preference == null) {
					getElement().getStyle().clearBackgroundColor();
					setTitle("");
				} else {
					getElement().getStyle().setBackgroundColor(preference.getColor());
					setTitle(DateTimeFormat.getFormat(CONSTANTS.examPeriodDateFormat()).format(date) + " " + slot2short(slot) + (period == null ? "" : " - " + slot2short(slot + period.getLength())) + ": " + preference.getName());
				}
				if (isEditable())
					addMouseDownHandler(new MouseDownHandler() {
						@Override
						public void onMouseDown(MouseDownEvent event) {
							setOption(iPreference);
						}
					});				
			}
		}
		
		public void setOption(PreferenceInterface preference) {
			if (!isEditable() || iPeriod == null) return;
			iModel.setPreference(iDay, iSlot, preference);
			if (preference == null) {
				getElement().getStyle().clearBackgroundColor();
				setTitle("");
			} else {
				getElement().getStyle().setBackgroundColor(preference.getColor());
				setTitle(DateTimeFormat.getFormat(CONSTANTS.examPeriodDateFormat()).format(iDate) + " " + slot2short(iSlot) + " - " + slot2short(iSlot + iPeriod.getLength()) + ": " + preference.getName());
			}
			ValueChangeEvent.fire(PeriodPreferencesWidget.this, getValue());
		}
	}
	
	@SuppressWarnings("deprecation")
	static int firstDayOfWeek(int year, int month) {
		return (6 + new Date(year - 1900, month - 1, 1).getDay()) % 7;
	}
	
	@SuppressWarnings("deprecation")
	static int daysInMonth(int year, int month) {
		return new Date(year + (month == 12 ? 1 : 0) - 1900, (month == 12 ? 1 : month + 1) - 1, 0).getDate();
	}
	
	@SuppressWarnings("deprecation")
	static int weekNumber(int year, int month) {
		Date d = new Date(year - 1900, month - 1, 1);
		while (d.getDay() != CalendarUtil.getStartingDayOfWeek()) d.setDate(d.getDate() - 1);
		int y = d.getYear();
		int week = 0;
		while (d.getYear() == y) { d.setDate(d.getDate() - 7); week += 1; }
		return week;
	}
	
	static int startingDayOfWeek() {
		return (6 + CalendarUtil.getStartingDayOfWeek()) % 7;
	}
	
	private class SingleMonth extends AbsolutePanel {
		@SuppressWarnings("deprecation")
		SingleMonth(String title, Date date, int slot) {
			date.setDate(1);
			int year = Integer.parseInt(DateTimeFormat.getFormat("yyyy").format(date));
			int month = Integer.parseInt(DateTimeFormat.getFormat("MM").format(date));
			int firstDayOfWeek = (6 + date.getDay()) % 7;
			int nrDays = daysInMonth(year, month);
			int firstWeekNumber = weekNumber(year, month);
			
			addStyleName("month");
						
			if (title != null) {
				P p = new P("title"); p.setText(title);
				add(p);
			}
			
			P box = new P("box");
			add(box);

			P header = new P("row");
			box.add(header);
			P corner = new P("cell", "corner");
			header.add(corner);
			
			for (int i = 0; i < 7; i++) {
				P h = new P("cell", "dow");
				h.setText(CONSTANTS.days()[(i + startingDayOfWeek()) % 7]);
				header.add(h);
			}

			int weekNumber = firstWeekNumber;
			P line = new P("row");
			box.add(line);
			P week = new P("cell", "week");
			week.setText(String.valueOf(weekNumber ++));
			line.add(week);
			
			int idx = 0;
			int blanks = (firstDayOfWeek + 7 - startingDayOfWeek()) % 7;
			for (int i = 0; i < blanks; i++) {
				line.add(new P("cell", (i + 1 == blanks ? "last-blank": "blank")));
				idx++;
			}
			
			for (int i = 1; i <= nrDays; i++) {
				if (i > 1 && idx % 7 == 0) {
					if (idx == 7 && month == 1 && weekNumber > 50) weekNumber = 1;
					line = new P("row");
					box.add(line);
					week = new P("cell", "week");
					week.setText(String.valueOf(weekNumber ++));
					line.add(week);
				}
				int day = CalendarUtil.getDaysBetween(iModel.getFirstDate(), date);
				PeriodInterface period = iModel.getPeriod(day, slot);
				D d = new D(day, slot, date, period);
				line.add(d);
				idx++;
				date = CalendarUtil.copyDate(date);
				CalendarUtil.addDaysToDate(date, 1);
			}
		}
	}
	
	static Date getDate(Date firstDate, int offset) {
		Date d = new Date(firstDate.getTime());
		if (offset != 0) CalendarUtil.addDaysToDate(d, offset);
		return d;
	}

	protected void render() {
		iPanel.clear();
		iCells.clear();
	
		if (iModel.getExamType().isFinal() || !CONSTANTS.displayMidtermPeriodPreferencesAsCalendar()) {
			iPanel.setStyleName("unitime-RoomSharingWidget");
			DateTimeFormat f1 = DateTimeFormat.getFormat(CONSTANTS.examPeriodPreferenceDateFormat()[0]);
			DateTimeFormat f2 = DateTimeFormat.getFormat(CONSTANTS.examPeriodPreferenceDateFormat()[1]);
			DateTimeFormat fm = DateTimeFormat.getFormat("MMMM yyyy");
			P horizonal = new P("horizontal"); horizonal.add(iHorizontal);
			iPanel.add(horizonal);
			
			boolean splitByMonths = iModel.getDays().size() > 15;
			P container = null;
			if (splitByMonths) {
				container = new P("container");
				iPanel.add(container);
			}
			Set<String> months = new HashSet<String>();
			while (true) {
				TreeSet<Integer> days = iModel.getDays();
				String month = null;
				if (splitByMonths) {
					days = new TreeSet<Integer>();
					for (int day: iModel.getDays()) {
						Date date = getDate(iModel.getFirstDate(), day);
						String m = fm.format(date);
						if (m.equals(month)) {
							days.add(day);
						} else if (month == null && months.add(m)) {
							month = m;
							days.add(day);
						}
					}
					if (month == null) break;
				}
				
				P table = new P(splitByMonths ? "intable" : "table");
				if (splitByMonths) {
					container.add(table);
					P title = new P("title");
					title.setText(month);
					table.add(title);
				} else {
					iPanel.add(table);
				}
				P box = new P("box");
				table.add(box);
				P header = new P("row");
				box.add(header);
				P corner = new P("cell", "corner", isEditable() ? "clickable" : null);
				corner.setHTML(MESSAGES.roomSharingCorner());
				header.add(corner);
				
				final List<Cell> thisPage = new ArrayList<Cell>();
				if (isHorizontal()) {
					if (container != null)
						container.addStyleName("orientation-horizontal");
					
					final Map<Integer, List<Cell>> thisSlot = new HashMap<Integer, List<Cell>>();
					for (int slot: iModel.getSlots()) {
						P p = new P("cell", "time", isEditable() ? "clickable" : null);
						p.setHTML(MESSAGES.roomSharingTimeHeader(slot2short(slot), slot2short(slot + iModel.getLength(slot))));
						final List<Cell> t = new ArrayList<Cell>();
						thisSlot.put(slot, t);
						header.add(p);
						if (isEditable())
							p.addMouseDownHandler(new MouseDownHandler() {
								@Override
								public void onMouseDown(MouseDownEvent event) {
									for (Cell d: t)
										d.setOption(iPreference);
								}
							});
					}
					for (int day: days) {
						P line = new P("row");
						box.add(line);
						P d = new P("cell", "day", isEditable() ? "clickable" : null);
						Date date = getDate(iModel.getFirstDate(), day);
						d.setHTML(f1.format(date) + "<br>" + f2.format(date));
						line.add(d);
						final List<Cell> thisDay = new ArrayList<Cell>();
						for (int slot: iModel.getSlots()) {
							Cell p = new Cell(day, slot, date, iModel.getPeriod(day, slot));
							line.add(p);
							thisSlot.get(slot).add(p);
							thisPage.add(p);
							thisDay.add(p);
							iCells.add(p);
						}
						if (isEditable())
							d.addMouseDownHandler(new MouseDownHandler() {
								@Override
								public void onMouseDown(MouseDownEvent event) {
									for (Cell d: thisDay)
										d.setOption(iPreference);
								}
							});
					}
				} else {
					if (container != null)
						container.addStyleName("orientation-vertical");
					
					final Map<Integer, List<Cell>> thisDay = new HashMap<Integer, List<Cell>>();
					for (int day: days) {
						P p = new P("cell", "time", isEditable() ? "clickable" : null);
						Date date = getDate(iModel.getFirstDate(), day);
						p.setHTML(f1.format(date) + "<br>" + f2.format(date));
						final List<Cell> t = new ArrayList<Cell>();
						thisDay.put(day, t);
						header.add(p);
						if (isEditable())
							p.addMouseDownHandler(new MouseDownHandler() {
								@Override
								public void onMouseDown(MouseDownEvent event) {
									for (Cell d: t)
										d.setOption(iPreference);
								}
							});
					}
					
					for (int slot: iModel.getSlots()) {
						P line = new P("row");
						box.add(line);
						P d = new P("cell", "day", isEditable() ? "clickable" : null);
						d.setHTML(MESSAGES.roomSharingTimeHeader(slot2short(slot), slot2short(slot + iModel.getLength(slot))));
						line.add(d);
						final List<Cell> thisSlot = new ArrayList<Cell>();
						for (int day: days) {
							Date date = getDate(iModel.getFirstDate(), day);
							Cell p = new Cell(day, slot, date, iModel.getPeriod(day, slot));
							line.add(p);
							thisSlot.add(p);
							thisPage.add(p);
							thisDay.get(day).add(p);
							iCells.add(p);
						}
						if (isEditable())
							d.addMouseDownHandler(new MouseDownHandler() {
								@Override
								public void onMouseDown(MouseDownEvent event) {
									for (Cell d: thisSlot)
										d.setOption(iPreference);
								}
							});
					}
				}

				
				if (isEditable())
					corner.addMouseDownHandler(new MouseDownHandler() {
						@Override
						public void onMouseDown(MouseDownEvent event) {
							for (Cell d: thisPage)
								d.setOption(iPreference);
						}
					});	
				
				if (!splitByMonths) break;
			}
		} else {
			iPanel.setStyleName("unitime-DateSelector");
			DateTimeFormat format = DateTimeFormat.getFormat("MMMM yyyy");
			P table = new P(); table.getElement().getStyle().setProperty("display", "inline-table");
			iPanel.add(table);
			for (int slot: iModel.getSlots()) {
				String last = null;
				P row = new P(); row.getElement().getStyle().setProperty("display", "table-row");
				table.add(row);
				SingleMonth m = null;
				for (int day: iModel.getDays()) {
					Date d = getDate(iModel.getFirstDate(), day);
					if (format.format(d).equals(last)) continue;
					last = format.format(d);
					m = new SingleMonth(format.format(d) + " (" + slot2short(slot) + " - " + slot2short(slot + iModel.getLength(slot)) + ")", d, slot);
					m.getElement().getStyle().setProperty("display", "table-cell");
					row.add(m);
				}
			}
		}

		P legend = new P("legend");
		iPanel.add(legend);
		
		P box = new P("box");
		legend.add(box);
		
		iSelectedIcon = null; iSelectedTitle = null;
		for (final PreferenceInterface option: iModel.getPreferences()) {
			final P line = new P("row");
			
			final P icon = new P("cell", isEditable(option) ? "clickable" : null);
			if (box.getWidgetCount() == 0) icon.addStyleName("first");
			icon.getElement().getStyle().setBackgroundColor(option.getColor());
			line.add(icon);
			
			final P title = new P("title", isEditable(option) ? "editable-title" : null); title.setHTML(option.getName());
			line.add(title);
			
			if (isEditable(option) && option.equals(iPreference)) {
				icon.addStyleName("selected");
				title.addStyleName("selected-title");
				iSelectedIcon = icon;
				iSelectedTitle = title;
			}

			if (isEditable(option)) {
				MouseDownHandler md = new MouseDownHandler() {
					@Override
					public void onMouseDown(MouseDownEvent event) {
						if (iModel.isReqConfirmation()) {
							if (option.getCode().equals("R")) {
								if (iModel.hasPreference())
									UniTimeConfirmationDialog.alert(MESSAGES.warnPreferenceUseRequired());
							} else if (!option.getCode().equals("0")) {
								if (iModel.hasRequired())
									UniTimeConfirmationDialog.alert(MESSAGES.warnPreferenceUseNotRequired());
							}
						}
						iPreference = option;
						iModel.setSelectedPreference(option);
						if (iSelectedIcon != null)
							iSelectedIcon.removeStyleName("selected");
						if (iSelectedTitle != null)
							iSelectedTitle.removeStyleName("selected-title");
						icon.addStyleName("selected");
						title.addStyleName("selected-title");
						iSelectedIcon = icon;
						iSelectedTitle = title;
					}
				};
				
				icon.addMouseDownHandler(md);
				title.addMouseDownHandler(md);
			}
			
			box.add(line);
		}
	}

	@Override
	public HandlerRegistration addValueChangeHandler(ValueChangeHandler<PeriodPreferenceModel> handler) {
		return addHandler(handler, ValueChangeEvent.getType());
	}

	@Override
	public PeriodPreferenceModel getValue() {
		return getModel();
	}

	@Override
	public void setValue(PeriodPreferenceModel value) {
		setValue(value, false);
	}

	@Override
	public void setValue(PeriodPreferenceModel value, boolean fireEvents) {
		setModel(value);
		if (fireEvents)
			ValueChangeEvent.fire(this, getValue());
	}
	
	public void insert(final RootPanel panel) {
		String pattern = null;
		if (panel.getElement().getFirstChildElement() != null) {
			pattern = Hidden.wrap(panel.getElement().getFirstChildElement()).getValue();
		} else {
			pattern = panel.getElement().getInnerText().trim();
		}
		final Long examTypeId = Long.valueOf(pattern.substring(0, pattern.indexOf(':')));;
		RPC.execute(RoomInterface.PeriodPreferenceRequest.loadForExam(null, examTypeId), new AsyncCallback<PeriodPreferenceModel>() {
			@Override
			public void onFailure(Throwable caught) {
				UniTimeNotifications.error(caught);
			}

			@Override
			public void onSuccess(final PeriodPreferenceModel model) {
				if (panel.getElement().getFirstChildElement() != null) {
					final Hidden pattern = Hidden.wrap(panel.getElement().getFirstChildElement());
					model.setPattern(pattern.getValue());
				
					addValueChangeHandler(new ValueChangeHandler<PeriodPreferenceModel>() {
						@Override
						public void onValueChange(ValueChangeEvent<PeriodPreferenceModel> event) {
							pattern.setValue(event.getValue().getPattern());
						}
					});
					iEditable = true;
				} else {
					String pattern = panel.getElement().getInnerText().trim();
					panel.getElement().setInnerText(null);
					model.setPattern(pattern);
					iEditable = false;
				}
				
				setModel(model);

				panel.add(PeriodPreferencesWidget.this);
				panel.setVisible(true);				
			}
		});
	}
}