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

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

import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Choice;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
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.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Date;
import java.util.Locale;

import com.ibm.icu.dev.demo.impl.DemoApplet;
import com.ibm.icu.dev.demo.impl.DemoUtility;
import com.ibm.icu.text.DateFormat;
import com.ibm.icu.util.BuddhistCalendar;
import com.ibm.icu.util.Calendar;
import com.ibm.icu.util.GregorianCalendar;
import com.ibm.icu.util.HebrewCalendar;
import com.ibm.icu.util.IslamicCalendar;
import com.ibm.icu.util.JapaneseCalendar;
import com.ibm.icu.util.SimpleTimeZone;

/**
 * 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.
 */
class CalendarFrame extends Frame
{
    /**
     * For serialization
     */
    private static final long serialVersionUID = -4289697663503820619L;

    private static final boolean DEBUG = false;

    private DemoApplet applet;

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

        // When the window is closed, we want to shut down the applet or application
        addWindowListener(
            new WindowAdapter() {
                public void windowClosing(WindowEvent e) {
                    setVisible(false);
                    dispose();

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

    private Choice          displayMenu;
    private Locale[]        locales = DemoUtility.getG7Locales();

    private Calendar        calendars[]   = new Calendar[2];
    private Choice          calMenu[]     = new Choice[2];
    private ColoredLabel    monthLabel[]  = new ColoredLabel[2];
    private DateFormat      monthFormat[] = new DateFormat[2];

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

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

    /**
     * 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() {
        setBackground(DemoUtility.bgColor);
        setLayout(new BorderLayout(10,10));

        Panel topPanel = new Panel();
        GridBagLayout g = new GridBagLayout();
        topPanel.setLayout(g);
        GridBagConstraints c = new GridBagConstraints();
        c.fill = GridBagConstraints.HORIZONTAL;

        // Build the two menus for selecting which calendar is displayed,
        // plus the month/year label for each calendar
        for (int i = 0; i < 2; i++) {
            calMenu[i] = new Choice();
            for (int j = 0; j < CALENDARS.length; j++) {
                calMenu[i].addItem(CALENDARS[j].name);
            }
            calMenu[i].setBackground(DemoUtility.choiceColor);
            calMenu[i].select(i);
            calMenu[i].addItemListener(new CalMenuListener());

            // Label for the current month name
            monthLabel[i] = new ColoredLabel("", COLORS[i]);
            monthLabel[i].setFont(DemoUtility.titleFont);

            // And the default calendar to use for this slot
            calendars[i] = CALENDARS[i].calendar;

            add(topPanel, calMenu[i], g, c, 5, 0);
            add(topPanel, monthLabel[i], g, c, GridBagConstraints.REMAINDER, 1);
        }

        // Now add the next/previous year/month buttons:
        prevYear = new Button("<<");
        prevYear.addActionListener(new AddAction(Calendar.YEAR, -1));

        prevMonth = new Button("<");
        prevMonth.addActionListener(new AddAction(Calendar.MONTH, -1));

        gotoToday = new Button("Today");
        gotoToday.addActionListener( new ActionListener()
        {
            public void actionPerformed(ActionEvent e) {
                calendarPanel.setDate( new Date() );
                updateMonthName();
            }
        } );

        nextMonth = new Button(">");
        nextMonth.addActionListener(new AddAction(Calendar.MONTH, 1));

        nextYear = new Button(">>");
        nextYear.addActionListener(new AddAction(Calendar.YEAR, 1));

        c.fill = GridBagConstraints.NONE;
        add(topPanel, prevYear,  g, c, 1, 0);
        add(topPanel, prevMonth, g, c, 1, 0);
        add(topPanel, gotoToday, g, c, 1, 0);
        add(topPanel, nextMonth, g, c, 1, 0);
        add(topPanel, nextYear,  g, c, 1, 0);

        // Now add the menu for selecting the display language
        Panel displayPanel = new Panel();
        {
            displayMenu = new Choice();
            Locale defaultLocale = Locale.getDefault();
            int bestMatch = -1, thisMatch = -1;
            int 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());
                }

                thisMatch = DemoUtility.compareLocales(locales[i], defaultLocale);
                
                if (thisMatch >= bestMatch) {
                    bestMatch = thisMatch;
                    selectMe = i;
                }
            }
            
            displayMenu.setBackground(DemoUtility.choiceColor);
            displayMenu.select(selectMe);

            displayMenu.addItemListener( new ItemListener()
            {
                 public void itemStateChanged(ItemEvent e) {
                    Locale loc = locales[displayMenu.getSelectedIndex()];
                    calendarPanel.setLocale( loc );
                    monthFormat[0] = monthFormat[1] = null;
                    updateMonthName();
                    repaint();
                }
            } );

            Label l1 = new Label("Display Language:", Label.RIGHT);
            l1.setFont(DemoUtility.labelFont);

            displayPanel.setLayout(new FlowLayout());
            displayPanel.add(l1);
            displayPanel.add(displayMenu);

        }
        c.fill = GridBagConstraints.NONE;
        c.anchor = GridBagConstraints.EAST;

        add(topPanel, displayPanel, g, c, GridBagConstraints.REMAINDER, 0);

        // The title, buttons, etc. go in a panel at the top of the window
        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( locales[displayMenu.getSelectedIndex()] );
        add("Center", calendarPanel);

        for (int i = 0; i < 2; i++) {
            calendarPanel.setCalendar(i, calendars[i]);
            calendarPanel.setColor(i, COLORS[i]);
        }

        updateMonthName();
    }


    private void updateMonthName()
    {
            for (int i = 0; i < 2; i++) {
                try {
                    if (monthFormat[i] == null) {     // TODO: optimize
                        DateFormat f = DateFormat.getDateTimeInstance(
                                                calendars[i], DateFormat.MEDIUM, -1,
                                                locales[displayMenu.getSelectedIndex()]);
                        if (f instanceof com.ibm.icu.text.SimpleDateFormat) {
                            com.ibm.icu.text.SimpleDateFormat f1 = (com.ibm.icu.text.SimpleDateFormat) f;
                            f1.applyPattern("MMMM, yyyy G");
                            f1.setTimeZone(new SimpleTimeZone(0, "UTC"));
                        }
                        monthFormat[i] = f;
                    }
                } catch (ClassCastException e) {
                    //hey {lw} - there's something wrong in this routine that cuases exceptions.
                    System.out.println(e);
                }

                monthLabel[i].setText( monthFormat[i].format( calendarPanel.firstOfMonth() ));
            }
    }

    /**
     * CalMenuListener responds to events in the two popup menus that select
     * the calendar systems to be used in the display.  It figures out which
     * of the two menus the event occurred in and updates the corresponding
     * element of the calendars[] array to match the new selection.
     */
    private class CalMenuListener implements ItemListener
    {
         public void itemStateChanged(ItemEvent e)
         {
            for (int i = 0; i < calMenu.length; i++)
            {
                if (e.getItemSelectable() == calMenu[i])
                {
                    // We found the menu that the event happened in.
                    // Figure out which new calendar they selected.
                    Calendar newCal = CALENDARS[ calMenu[i].getSelectedIndex() ].calendar;

                    if (newCal != calendars[i])
                    {
                        // If any of the other menus are set to the same new calendar
                        // we're about to use for this menu, set them to the current
                        // calendar from *this* menu so we won't have two the same
                        for (int j = 0; j < calendars.length; j++) {
                            if (j != i && calendars[j] == newCal) {
                                calendars[j] = calendars[i];
                                calendarPanel.setCalendar(j, calendars[j]);
                                monthFormat[j] = null;

                                for (int k = 0; k < CALENDARS.length; k++) {
                                    if (calendars[j] == CALENDARS[k].calendar) {
                                        calMenu[j].select(k);
                                        break;
                                    }
                                }
                            }
                        }
                        // Now update this menu to use the new calendar the user selected
                        calendars[i] = newCal;
                        calendarPanel.setCalendar(i, newCal);
                        monthFormat[i] = null;

                        updateMonthName();
                    }
                    break;
                }
            }
         }
    }

    /**
     * AddAction handles the next/previous year/month buttons...
     */
    private class AddAction implements ActionListener {
        AddAction(int field, int amount) {
            this.field = field;
            this.amount = amount;
        }

        public void actionPerformed(ActionEvent e) {
            calendarPanel.add(field, amount);
            updateMonthName();
        }

        private int field, amount;
    }

    /**
     * ColoredLabel is similar to java.awt.Label, with two differences:
     *
     *  - You can set its text color
     *
     *  - It draws text using drawString rather than using a host-specific
     *    "Peer" object like AWT does.  On 1.2, using drawString gives
     *    us Bidi reordering for free.
     */
    static private class ColoredLabel extends Component {
        /**
         * For serialization
         */
        private static final long serialVersionUID = 5004484960341875722L;
        public ColoredLabel(String label) {
            text = label;
        }

        public ColoredLabel(String label, Color c) {
            text = label;
            color = c;
        }

        public void setText(String label) {
            text = label;
            repaint();
        }

        public void setFont(Font f) {
            font = f;
            repaint();
        }

        public void paint(Graphics g) {
            FontMetrics fm = g.getFontMetrics(font);

            Rectangle bounds = getBounds();

            g.setColor(color);
            g.setFont(font);
            g.drawString(text, fm.stringWidth("\u00a0"),
                         bounds.height/2 + fm.getHeight()
                         - fm.getAscent() + fm.getLeading()/2);
        }

        public Dimension getPreferredSize() {
            return getMinimumSize();
        }

        public Dimension getMinimumSize() {
            FontMetrics fm = getFontMetrics(font);

            return new Dimension( fm.stringWidth(text) + 2*fm.stringWidth("\u00a0"),
                                  fm.getHeight() + fm.getLeading()*2);
        }

        String text;
        Color color = Color.black;
        Font font = DemoUtility.labelFont;
    }

    /**
     * Print out the error message while debugging this program.
     */
    public void errorText(String s)
    {
        if (DEBUG)
        {
            System.out.println(s);
        }
    }

    class CalendarRec {
        public CalendarRec(String nameStr, Calendar cal)
        {
            name = nameStr;
            calendar = cal;
        }

        Calendar  calendar;
        String              name;
    }

    private final CalendarRec[] CALENDARS = {
        new CalendarRec("Gregorian Calendar",       new GregorianCalendar()),
        new CalendarRec("Hebrew Calendar",          new HebrewCalendar()),
        new CalendarRec("Islamic Calendar",         makeIslamic(false)),
        new CalendarRec("Islamic Civil Calendar ",  makeIslamic(true)),
        new CalendarRec("Buddhist Calendar",        new BuddhistCalendar()),
        new CalendarRec("Japanese Calendar",        new JapaneseCalendar()),
    };

    static private final Calendar makeIslamic(boolean civil) {
        IslamicCalendar cal = new IslamicCalendar();
        cal.setCivil(civil);
        return cal;
    }

    static final Color[] COLORS = { Color.blue, Color.black };
}

