/*
 *******************************************************************************
 * Copyright (C) 1996-2007, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 */

package com.ibm.icu.dev.demo.holiday;

import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Canvas;
import java.awt.Choice;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Label;
import java.awt.Panel;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.WindowEvent;
import java.text.DateFormatSymbols;
import java.util.Date;
import java.util.Locale;
import java.util.Vector;

import com.ibm.icu.dev.demo.impl.DemoApplet;
import com.ibm.icu.dev.demo.impl.DemoTextBox;
import com.ibm.icu.dev.demo.impl.DemoUtility;
import com.ibm.icu.text.SimpleDateFormat;
import com.ibm.icu.util.Calendar;
import com.ibm.icu.util.Holiday;
import com.ibm.icu.util.SimpleTimeZone;

/**
 * CalendarDemo demonstrates how Calendar works.
 */
public class HolidayCalendarDemo extends DemoApplet 
{
    /**
     * For serialization
     */
    private static final long serialVersionUID = 4546085430817359372L;

    /**
     * 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
    {
        /**
         * For serialization
         */
        private static final long serialVersionUID = -7023296782393042761L;

        private static final boolean DEBUG = false;

        //private Locale curLocale = Locale.US; // unused

        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 {

        /**
         * For serialization
         */
        private static final long serialVersionUID = 1521099412250120821L;

        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.icu.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;
    }
}

