/*
 *******************************************************************************
 * Copyright (C) 1996-2000, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 *
 * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/demo/holiday/Attic/HolidayCalendarDemo.java,v $ 
 * $Date: 2001/10/30 02:42:49 $ 
 * $Revision: 1.7 $
 *
 *****************************************************************************************
 */

package com.ibm.demo.holiday;

import com.ibm.demo.*;
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
//import java.util.*;
import java.net.*;
import java.io.*;

//import java.text.SimpleDateFormat;
import com.ibm.text.SimpleDateFormat;
import java.text.DateFormatSymbols;
//import java.util.SimpleTimeZone;
import com.ibm.util.SimpleTimeZone;
import java.util.Locale;
import java.util.Vector;
import java.util.Date;

import com.ibm.util.*;

/**
 * CalendarDemo demonstrates how Calendar works.
 */
public class HolidayCalendarDemo extends DemoApplet 
{
    /**
     * The main function which defines the behavior of the CalendarDemo
     * applet when an applet is started.
     */
    public static void main(String argv[]) {

        new HolidayCalendarDemo().showDemo();
    }

    /* This creates a CalendarFrame for the demo applet. */
    public Frame createDemoFrame(DemoApplet applet) {
        return new CalendarFrame(applet);
    }

	/**
	* A Frame is a top-level window with a title. The default layout for a frame
	* is BorderLayout.  The CalendarFrame class defines the window layout of
	* CalendarDemo.
	*/
	private static class CalendarFrame extends Frame implements ActionListener,
                                                                ItemListener
	{
    	private static final String creditString = "";

    	private static final boolean DEBUG = false;

    	private Locale curLocale = Locale.US;

    	private DemoApplet applet;

    	private static final Locale[] calendars = {
        	//new Locale("de","AT"),
        	Locale.CANADA,
        	Locale.CANADA_FRENCH,
        	Locale.FRANCE,
        	Locale.GERMANY,
        	new Locale("iw","IL"),
        	new Locale("el","GR"),
        	//new Locale("es","MX"),
        	Locale.UK,
        	Locale.US,
    	};
    	private static final Locale[] displays = {
        	Locale.CANADA,
        	Locale.UK,
        	Locale.US,
        	Locale.FRANCE,
        	Locale.CANADA_FRENCH,
        	//new Locale("de","AT"),
        	Locale.GERMAN,
        	new Locale("el","GR"),
        	//new Locale("iw","IL"),
        	new Locale("es","MX"),
    	};

    	/**
    	* Constructs a new CalendarFrame that is initially invisible.
    	*/
    	public CalendarFrame(DemoApplet applet)
    	{
        	super("Calendar Demo");
        	this.applet = applet;
        	init();
        	start();
        	enableEvents(WindowEvent.WINDOW_CLOSING);
    	}

    	/**
    	* Initializes the applet. You never need to call this directly, it
    	* is called automatically by the system once the applet is created.
    	*/
    	public void init()
    	{
        	// Get G7 locales only for demo purpose. To get all the locales
        	// supported, switch to calling Calendar.getAvailableLocales().
        	// commented
        	locales = displays;

        	buildGUI();
    	}

    	//------------------------------------------------------------
    	// package private
    	//------------------------------------------------------------
    	void addWithFont(Container container, Component foo, Font font) {
        	if (font != null)
            	foo.setFont(font);
        	container.add(foo);
    	}

    	/**
    	* Called to start the applet. You never need to call this method
    	* directly, it is called when the applet's document is visited.
    	*/
    	public void start()
    	{
        	// do nothing
    	}

    	private Choice          localeMenu;
    	private Choice          displayMenu;
    	private Locale[]        locales;

    	private Label           monthLabel;
    	private Button          prevYear;
    	private Button          prevMonth;
    	private Button          gotoToday;
    	private Button          nextMonth;
    	private Button          nextYear;
    	private CalendarPanel   calendarPanel;

    	private static final Locale kFirstLocale = Locale.US;

    	private static void add(Container container, Component component,
                            	GridBagLayout g, GridBagConstraints c)
    	{
        	g.setConstraints(component, c);
        	container.add(component);
    	}

    	public void buildGUI()
    	{
        	setBackground(DemoUtility.bgColor);
        	setLayout(new BorderLayout(10,10));

        	// Label for the demo's title
        	Label titleLabel = new Label("Calendar Demo", Label.CENTER);
        	titleLabel.setFont(DemoUtility.titleFont);

        	// Label for the current month name
        	monthLabel = new Label("", Label.LEFT);
        	monthLabel.setFont(new Font(DemoUtility.titleFont.getName(),
                                    	DemoUtility.titleFont.getStyle(),
                                    	(DemoUtility.titleFont.getSize() * 3)/2));

        	// Make the locale popup menus
        	localeMenu= new Choice();
        	localeMenu.addItemListener(this);
        	int selectMe = 0;
        	
        	for (int i = 0; i < calendars.length; i++) {
            	if (i > 0 &&
                    	calendars[i].getCountry().equals(calendars[i-1].getCountry()) ||
                	i < calendars.length - 1 &&
                    	calendars[i].getCountry().equals(calendars[i+1].getCountry()))
            	{
                	localeMenu.addItem(calendars[i].getDisplayCountry() + " (" +
                                	calendars[i].getDisplayLanguage() + ")");
            	} else {
                	localeMenu.addItem( calendars[i].getDisplayCountry() );
            	}
            	
            	if (calendars[i].equals(kFirstLocale)) {
                	selectMe = i;
            	}
        	}
        	
        	localeMenu.setBackground(DemoUtility.choiceColor);
        	localeMenu.select(selectMe);

        	displayMenu = new Choice();
        	displayMenu.addItemListener(this);
        	
        	selectMe = 0;
        	for (int i = 0; i < locales.length; i++) {
            	if (i > 0 &&
                    	locales[i].getLanguage().equals(locales[i-1].getLanguage()) ||
                	i < locales.length - 1 &&
                    	locales[i].getLanguage().equals(locales[i+1].getLanguage()))
            	{
                	displayMenu.addItem( locales[i].getDisplayName() );
            	} else {
                	displayMenu.addItem( locales[i].getDisplayLanguage());
            	}
            	
            	if (locales[i].equals(kFirstLocale)) {
            	    selectMe = i;
            	}
        	}
        	
        	displayMenu.setBackground(DemoUtility.choiceColor);
        	displayMenu.select(selectMe);

        	// Make all the next/previous/today buttons
        	prevYear = new Button("<<");
        	prevYear.addActionListener(this);
        	prevMonth = new Button("<");
        	prevMonth.addActionListener(this);
        	gotoToday = new Button("Today");
        	gotoToday.addActionListener(this);
        	nextMonth = new Button(">");
        	nextMonth.addActionListener(this);
        	nextYear = new Button(">>");
        	nextYear.addActionListener(this);

        	// The month name and the control buttons are bunched together
        	Panel monthPanel = new Panel();
        	{
            	GridBagLayout g = new GridBagLayout();
            	GridBagConstraints c = new GridBagConstraints();
            	monthPanel.setLayout(g);

            	c.weightx = 1;
            	c.weighty = 1;

            	c.gridwidth = 1;
            	c.fill = GridBagConstraints.HORIZONTAL;
            	c.gridwidth = GridBagConstraints.REMAINDER;
            	add(monthPanel, monthLabel, g, c);

            	c.gridwidth = 1;
            	add(monthPanel, prevYear, g, c);
            	add(monthPanel, prevMonth, g, c);
            	add(monthPanel, gotoToday, g, c);
            	add(monthPanel, nextMonth, g, c);
            	c.gridwidth = GridBagConstraints.REMAINDER;
            	add(monthPanel, nextYear, g, c);
        	}

        	// Stick the menu and buttons in a little "control panel"
        	Panel menuPanel = new Panel();
        	{
            	GridBagLayout g = new GridBagLayout();
            	GridBagConstraints c = new GridBagConstraints();
            	menuPanel.setLayout(g);

            	c.weightx = 1;
            	c.weighty = 1;

            	c.fill = GridBagConstraints.HORIZONTAL;

            	c.gridwidth = GridBagConstraints.RELATIVE;
            	Label l1 = new Label("Holidays");
            	l1.setFont(DemoUtility.labelFont);
            	add(menuPanel, l1, g, c);

            	c.gridwidth = GridBagConstraints.REMAINDER;
            	add(menuPanel, localeMenu, g, c);

            	c.gridwidth = GridBagConstraints.RELATIVE;
            	Label l2 = new Label("Display:");
            	l2.setFont(DemoUtility.labelFont);
            	add(menuPanel, l2, g, c);

            	c.gridwidth = GridBagConstraints.REMAINDER;
            	add(menuPanel, displayMenu, g, c);
        	}

        	// The title, buttons, etc. go in a panel at the top of the window
        	Panel topPanel = new Panel();
        	{
            	topPanel.setLayout(new BorderLayout());

            	//topPanel.add("North", titleLabel);
            	topPanel.add("Center", monthPanel);
            	topPanel.add("East", menuPanel);
        	}
        	add("North", topPanel);

        	// The copyright notice goes at the bottom of the window
        	Label copyright = new Label(DemoUtility.copyright1, Label.LEFT);
        	copyright.setFont(DemoUtility.creditFont);
        	add("South", copyright);

        	// Now create the big calendar panel and stick it in the middle
        	calendarPanel = new CalendarPanel( kFirstLocale );
        	add("Center", calendarPanel);

        	updateMonthName();
    	}

    	private void updateMonthName()
    	{
        	SimpleDateFormat f = new SimpleDateFormat("MMMM yyyyy",
                                                    	calendarPanel.getDisplayLocale());
        	f.setCalendar(calendarPanel.getCalendar());
        	f.setTimeZone(new SimpleTimeZone(0, "UTC"));        // JDK 1.1.2 workaround
        	monthLabel.setText( f.format( calendarPanel.firstOfMonth() ));
    	}
    	
    	/**
    	* Handles the event. Returns true if the event is handled and should not
    	* be passed to the parent of this component. The default event handler
    	* calls some helper methods to make life easier on the programmer.
    	*/
    	public void actionPerformed(ActionEvent e)
    	{
    	    Object obj = e.getSource();
    	    
    	    // *** Button events are handled here.
        	if (obj instanceof Button) {
            	if (obj == nextMonth) {
                	calendarPanel.add(Calendar.MONTH, +1);
            	}
            	else
            	if (obj == prevMonth) {
                	calendarPanel.add(Calendar.MONTH, -1);
            	}
            	else
            	if (obj == prevYear) {
                	calendarPanel.add(Calendar.YEAR, -1);
            	}
            	else
            	if (obj == nextYear) {
                	calendarPanel.add(Calendar.YEAR, +1);
            	}
            	else
            	if (obj == gotoToday) {
                	calendarPanel.set( new Date() );
            	}
            	updateMonthName();
        	}
    	}
    	
    	public void itemStateChanged(ItemEvent e)
        {
            Object obj = e.getSource();
            if (obj == localeMenu) {
            	calendarPanel.setCalendarLocale(calendars[localeMenu.getSelectedIndex()]);
            	updateMonthName();
        	}
        	else 
        	    if (obj == displayMenu) {
            	    calendarPanel.setDisplayLocale(locales[displayMenu.getSelectedIndex()]);
            	    updateMonthName();
            	}
        }
        
        /**
    	* Print out the error message while debugging this program.
    	*/
    	public void errorText(String s)
    	{
        	if (DEBUG)
        	{
            	System.out.println(s);
        	}
    	}
    	
    	protected void processWindowEvent(WindowEvent e)
        {
            System.out.println("event " + e);
            if (e.getID() == WindowEvent.WINDOW_CLOSING) {
            	this.hide();
            	this.dispose();

            	if (applet != null) {
            	    applet.demoClosed();
            	} else {
                    System.exit(0);
            	}
        	}
        }
	}


	private static class CalendarPanel extends Canvas {

    	public CalendarPanel( Locale locale ) {
        	set(locale, locale, new Date());
    	}

    	public void setCalendarLocale(Locale locale) {
        	set(locale, fDisplayLocale, fCalendar.getTime());
    	}

    	public void setDisplayLocale(Locale locale) {
        	set(fCalendarLocale, locale, fCalendar.getTime());
    	}

    	public void set(Date date) {
        	set(fCalendarLocale, fDisplayLocale, date);
    	}

    	public void set(Locale loc, Locale display, Date date)
    	{
        	if (fCalendarLocale == null || !loc.equals(fCalendarLocale)) {
            	fCalendarLocale = loc;
            	fCalendar = Calendar.getInstance(fCalendarLocale);
            	fAllHolidays = Holiday.getHolidays(fCalendarLocale);
        	}
        	if (fDisplayLocale == null || !display.equals(fDisplayLocale)) {
            	fDisplayLocale = display;
            	fSymbols = new DateFormatSymbols(fDisplayLocale);
        	}

        	fStartOfMonth = date;

        	dirty = true;
        	repaint();
    	}

    	public void add(int field, int delta)
    	{
        	synchronized(fCalendar) {
            	fCalendar.setTime(fStartOfMonth);
            	fCalendar.add(field, delta);
            	fStartOfMonth = fCalendar.getTime();
        	}
        	dirty = true;
        	repaint();
    	}

    	public com.ibm.util.Calendar getCalendar() {
        	return fCalendar;
    	}

    	public Locale getCalendarLocale() {
        	return fCalendarLocale;
    	}

    	public Locale getDisplayLocale() {
        	return fDisplayLocale;
    	}


    	public Date firstOfMonth() {
        	return fStartOfMonth;
    	}

    	private Date startOfMonth(Date dateInMonth)
    	{
        	synchronized(fCalendar) {
            	fCalendar.setTime(dateInMonth);             // TODO: synchronization

            	int era = fCalendar.get(Calendar.ERA);
            	int year = fCalendar.get(Calendar.YEAR);
            	int month = fCalendar.get(Calendar.MONTH);

            	fCalendar.clear();
            	fCalendar.set(Calendar.ERA, era);
            	fCalendar.set(Calendar.YEAR, year);
            	fCalendar.set(Calendar.MONTH, month);
            	fCalendar.set(Calendar.DATE, 1);

            	return fCalendar.getTime();
        	}
    	}

    	private void calculate()
    	{
        	//
        	// As a workaround for JDK 1.1.3 and below, where Calendars and time
        	// zones are a bit goofy, always set my calendar's time zone to UTC.
        	// You would think I would want to do this in the "set" function above,
        	// but if I do that, the program hangs when this class is loaded,
        	// perhaps due to some sort of static initialization ordering problem.
        	// So I do it here instead.
        	//
        	fCalendar.setTimeZone(new SimpleTimeZone(0, "UTC"));

        	Calendar c = (Calendar)fCalendar.clone(); // Temporary copy

        	fStartOfMonth = startOfMonth(fStartOfMonth);

        	// Stash away a few useful constants for this calendar and display
        	minDay = c.getMinimum(Calendar.DAY_OF_WEEK);
        	daysInWeek = c.getMaximum(Calendar.DAY_OF_WEEK) - minDay + 1;

        	firstDayOfWeek = Calendar.getInstance(fDisplayLocale).getFirstDayOfWeek();

        	// Stash away a Date for the start of this month

        	// Find the day of week of the first day in this month
        	c.setTime(fStartOfMonth);
        	firstDayInMonth = c.get(Calendar.DAY_OF_WEEK);

        	// Now find the # of days in the month
        	c.roll(Calendar.DATE, false);
        	daysInMonth = c.get(Calendar.DATE);

        	// Finally, find the end of the month, i.e. the start of the next one
        	c.roll(Calendar.DATE, true);
        	c.add(Calendar.MONTH, 1);
        	c.getTime();        // JDK 1.1.2 bug workaround
        	c.add(Calendar.SECOND, -1);
        	Date endOfMonth = c.getTime();

        	//
        	// Calculate the number of full or partial weeks in this month.
        	// To do this I can just reuse the code that calculates which
        	// calendar cell contains a given date.
        	//
        	numWeeks = dateToCell(daysInMonth).y - dateToCell(1).y + 1;

        	// Remember which holidays fall on which days in this month,
        	// to save the trouble of having to do it later
        	fHolidays.setSize(0);

        	for (int h = 0; h < fAllHolidays.length; h++)
        	{
            	Date d = fStartOfMonth;
            	while ( (d = fAllHolidays[h].firstBetween(d, endOfMonth) ) != null)
            	{
                	c.setTime(d);
                	fHolidays.addElement( new HolidayInfo(c.get(Calendar.DATE),
                                        	fAllHolidays[h],
                                        	fAllHolidays[h].getDisplayName(fDisplayLocale) ));

                	d.setTime( d.getTime() + 1000 );    // "d++"
            	}
        	}
        	dirty = false;
    	}

    	static final int INSET = 2;

    	/*
    	* Convert from the day number within a month (1-based)
    	* to the cell coordinates on the calendar (0-based)
    	*/
    	private void dateToCell(int date, Point pos)
    	{
        	int cell = (date + firstDayInMonth - firstDayOfWeek - minDay);
        	if (firstDayInMonth < firstDayOfWeek) {
            	cell += daysInWeek;
        	}

        	pos.x = cell % daysInWeek;
        	pos.y = cell / daysInWeek;
    	}
    	private Point dateToCell(int date) {
        	Point p = new Point(0,0);
        	dateToCell(date, p);
        	return p;
    	}

    	public void paint(Graphics g) {

        	if (dirty) {
            	calculate();
        	}

        	Point cellPos = new Point(0,0);     // Temporary variable
        	Dimension d = getSize();

        	g.setColor(DemoUtility.bgColor);
        	g.fillRect(0,0,d.width,d.height);

        	// Draw the day names at the top
        	g.setColor(Color.black);
        	g.setFont(DemoUtility.labelFont);
        	FontMetrics fm = g.getFontMetrics();
        	int labelHeight = fm.getHeight() + INSET * 2;

        	int v = fm.getAscent() + INSET;
        	for (int i = 0; i < daysInWeek; i++) {
            	int dayNum = (i + minDay + firstDayOfWeek - 2) % daysInWeek + 1;
            	String dayName = fSymbols.getWeekdays()[dayNum];

            	int h = (int) (d.width * (i + 0.5)) / daysInWeek;
            	h -= fm.stringWidth(dayName) / 2;

            	g.drawString(dayName, h, v);
        	}

        	double cellHeight = (d.height - labelHeight - 1) / numWeeks;
        	double cellWidth = (double)(d.width - 1) / daysInWeek;

        	// Draw a white background in the part of the calendar
        	// that displays this month.
        	// First figure out how much of the first week should be shaded.
        	{
            	g.setColor(Color.white);
            	dateToCell(1, cellPos);
            	int width = (int)(cellPos.x*cellWidth);  // Width of unshaded area

            	g.fillRect((int)(width), labelHeight ,
                    	(int)(d.width - width), (int)cellHeight);

            	// All of the intermediate weeks get shaded completely
            	g.fillRect(0, (int)(labelHeight + cellHeight),
                        	d.width, (int)(cellHeight * (numWeeks - 2)));

            	// Now figure out the last week.
            	dateToCell(daysInMonth, cellPos);
            	width = (int)((cellPos.x+1)*cellWidth);  // Width of shaded area

            	g.fillRect(0, (int)(labelHeight + (numWeeks-1) * cellHeight),
                        	width, (int)(cellHeight));

        	}
        	// Draw the X/Y grid lines
        	g.setColor(Color.black);
        	for (int i = 0; i <= numWeeks; i++) {
            	int y = (int)(labelHeight + i * cellHeight);
            	g.drawLine(0, y, d.width - 1, y);
        	}
        	for (int i = 0; i <= daysInWeek; i++) {
            	int x = (int)(i * cellWidth);
            	g.drawLine(x, labelHeight, x, d.height - 1);
        	}

        	// Now loop through all of the days in the month, figure out where
        	// they go in the grid, and draw the day # for each one
        	Font numberFont = new Font("Helvetica",Font.PLAIN,12);
        	// not used Font holidayFont = DemoUtility.creditFont;

        	Calendar c = (Calendar)fCalendar.clone();
        	c.setTime(fStartOfMonth);

        	for (int i = 1, h = 0; i <= daysInMonth; i++) {
            	g.setFont(numberFont);
            	g.setColor(Color.black);
            	fm = g.getFontMetrics();

            	dateToCell(i, cellPos);
            	int x = (int)((cellPos.x + 1) * cellWidth);
            	int y = (int)(cellPos.y * cellHeight + labelHeight);

            	StringBuffer buffer = new StringBuffer();
            	buffer.append(i);
            	String dayNum = buffer.toString();

            	x = x - INSET - fm.stringWidth(dayNum);
            	y = y + fm.getAscent() + INSET;

            	g.drawString(dayNum, x, y);

            	// See if any of the holidays land on this day....
            	HolidayInfo info = null;
            	int count = 0;

            	// Coordinates of lower-left corner of cell.
            	x = (int)((cellPos.x) * cellWidth);
            	y = (int)((cellPos.y+1) * cellHeight) + labelHeight;

            	while (h < fHolidays.size() &&
                    	(info = (HolidayInfo)fHolidays.elementAt(h)).date <= i)
            	{
                	if (info.date == i) {
                    	// Draw the holiday here.
                    	g.setFont(numberFont);
                    	g.setColor(Color.red);

                    	DemoTextBox box = new DemoTextBox(g, info.name, (int)(cellWidth - INSET));
                    	box.draw(g, x + INSET, y - INSET - box.getHeight());

                    	y -= (box.getHeight() + INSET);
                    	count++;
                	}
                	h++;
            	}
        	}
    	}

    	// Important state variables
    	private Locale              fCalendarLocale;    // Whose calendar
    	private Calendar            fCalendar;          // Calendar for calculations

    	private Locale              fDisplayLocale;     // How to display it
    	private DateFormatSymbols   fSymbols;           // Symbols for drawing

    	private Date                fStartOfMonth;      // 00:00:00 on first day of month

    	// Cached calculations to make drawing faster.
    	private transient int minDay;           // Minimum legal day #
    	private transient int daysInWeek;       // # of days in a week
    	private transient int firstDayOfWeek;   // First day to display in week
    	private transient int numWeeks;         // # full or partial weeks in month
    	private transient int daysInMonth;      // # days in this month
    	private transient int firstDayInMonth;  // Day of week of first day in month

    	private transient Holiday[] fAllHolidays;
    	private transient Vector    fHolidays = new Vector(5,5);

    	private transient boolean dirty = true;
	}

	private static class HolidayInfo {
    	public HolidayInfo(int date, Holiday holiday, String name) {
        	this.date = date;
        	this.holiday = holiday;
        	this.name = name;
    	}

    	public Holiday holiday;
    	public int date;
    	public String name;
	}
}

