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

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

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Point;
import java.util.Date;
import java.util.Locale;

import com.ibm.icu.dev.demo.impl.DemoUtility;
import com.ibm.icu.text.DateFormatSymbols;
import com.ibm.icu.util.Calendar;
import com.ibm.icu.util.SimpleTimeZone;

class CalendarPanel extends Canvas {

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

    public CalendarPanel( Locale locale ) {
        setLocale(locale);
    }

    public void setLocale(Locale locale) {
        if (fDisplayLocale == null || !fDisplayLocale.equals(locale)) {
            fDisplayLocale = locale;
            dirty = true;

            for (int i = 0; i < fCalendar.length; i++) {
                if (fCalendar[i] != null) {
                    fSymbols[i] = new DateFormatSymbols(fCalendar[i],
                                                        fDisplayLocale);
                }
            }
            String lang = locale.getLanguage();
            leftToRight = !(lang.equals("iw") || lang.equals("ar"));

            repaint();
        }
    }

    public void setDate(Date date) {
        fStartOfMonth = date;
        dirty = true;
        repaint();
    }

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

    public void setColor(int index, Color c) {
        fColor[index] = c;
        repaint();
    }

    public void setCalendar(int index, Calendar c) {
        Date date = (fCalendar[index] == null) ? new Date()
                                               : fCalendar[index].getTime();

        fCalendar[index] = c;
        fCalendar[index].setTime(date);

        fSymbols[index] = new DateFormatSymbols(c, fDisplayLocale);
        dirty = true;
        repaint();
    }

    public Calendar getCalendar(int index) {
        return fCalendar[index];
    }

    public Locale getDisplayLocale() {
        return fDisplayLocale;
    }

    public Date firstOfMonth() {
        return fStartOfMonth;
    }

    private Date startOfMonth(Date dateInMonth)
    {
        synchronized(fCalendar) {
            fCalendar[0].setTime(dateInMonth);

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

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

            return fCalendar[0].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[0].setTimeZone(new SimpleTimeZone(0, "UTC"));

        Calendar c = (Calendar)fCalendar[0].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);
        int firstWeek = c.get(Calendar.WEEK_OF_MONTH);

        // 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();
        if(endOfMonth==null){
         //do nothing
        }
        endOfMonth = null;
        int lastWeek = c.get(Calendar.WEEK_OF_MONTH);
        
        // Calculate the number of full or partial weeks in this month.
        numWeeks = lastWeek - firstWeek + 1;

        dirty = false;
    }

    static final int XINSET = 4;
    static final int YINSET = 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 = this.getSize();

        g.setColor(Color.lightGray);
        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() + YINSET * 2;

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


            double h;
            if (leftToRight) {
                h = d.width*(i + 0.5) / daysInWeek;
            } else {
                h = d.width*(daysInWeek - i - 0.5) / daysInWeek;
            }
            h -= fm.stringWidth(dayName) / 2;

            g.drawString(dayName, (int)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

            if (leftToRight) {
                g.fillRect((int)(width), labelHeight ,
                           d.width - width, (int)cellHeight);
            } else {
                g.fillRect(0, labelHeight ,
                           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

            if (leftToRight) {
                g.fillRect(0, (int)(labelHeight + (numWeeks-1) * cellHeight),
                           width, (int)cellHeight);
            } else {
                g.fillRect(d.width - width, (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

        // Figure out the date of the first cell in the calendar display
        int cell = (1 + firstDayInMonth - firstDayOfWeek - minDay);
        if (firstDayInMonth < firstDayOfWeek) {
            cell += daysInWeek;
        }

        Calendar c = (Calendar)fCalendar[0].clone();
        c.setTime(fStartOfMonth);
        c.add(Calendar.DATE, -cell);

        StringBuffer buffer = new StringBuffer();

        for (int row = 0; row < numWeeks; row++) {
            for (int col = 0; col < daysInWeek; col++) {

                g.setFont(DemoUtility.numberFont);
                g.setColor(Color.black);
                fm = g.getFontMetrics();

                int cellx;
                if (leftToRight) {
                    cellx = (int)((col) * cellWidth);
                } else {
                    cellx = (int)((daysInWeek - col - 1) * cellWidth);
                }

                int celly = (int)(row * cellHeight + labelHeight);

                for (int i = 0; i < 2; i++) {
                    fCalendar[i].setTime(c.getTime());

                    int date = fCalendar[i].get(Calendar.DATE);
                    buffer.setLength(0);
                    buffer.append(date);
                    String dayNum = buffer.toString();

                    int x;

                    if (leftToRight) {
                        x = cellx + (int)cellWidth - XINSET - fm.stringWidth(dayNum);
                    } else {
                        x = cellx + XINSET;
                    }
                    int y = celly + + fm.getAscent() + YINSET + i * fm.getHeight();

                    if (fColor[i] != null) {
                        g.setColor(fColor[i]);
                    }
                    g.drawString(dayNum, x, y);

                    if (date == 1 || row == 0 && col == 0) {
                        g.setFont(DemoUtility.numberFont);
                        String month = fSymbols[i].getMonths()[
                                            fCalendar[i].get(Calendar.MONTH)];

                        if (leftToRight) {
                            x = cellx + XINSET;
                        } else {
                            x = cellx + (int)cellWidth - XINSET - fm.stringWidth(month);
                        }
                        g.drawString(month, x, y);
                    }
                }

                c.add(Calendar.DATE, 1);
            }
        }
    }

    // Important state variables
    private Calendar[]          fCalendar = new Calendar[4];
    private Color[]             fColor = new Color[4];

    private Locale              fDisplayLocale;
    private DateFormatSymbols[] fSymbols = new DateFormatSymbols[4];

    private Date                fStartOfMonth = new Date();     // 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 boolean   leftToRight;

    private transient boolean dirty = true;
}
