//
//
// Enhanced Countdown Applet
//
// Counts down to a paricular time/date. Allows users to
// customize date, colour and messages displayed before/after remaining 
// count time, and when countdown reached.
//
// Based on an earlier Countdown applet I'd written.
//
// Written by             : David Reilly
// URL                    : http://www.javacoffeebreak.com/applets/
// Release details        : Public domain source/binary
//
// Revision History :
//
//  August   28, 1999  - Added customizable foreground/background
//  December 27, 1998  - Added customizable message parameters
//
//

import java.applet.*;
import java.awt.*;
import java.util.Date;

public class EnhancedCountdown extends Applet implements Runnable
{
	// m_Countdown is the Thread object for the applet
	private Thread   m_Countdown = null;

	// m_Date is the date to which applet will countdown
	private Date m_Date;

	// String to be displayed in next update
	private String  countString;

	// PARAMETER SUPPORT:
	private String m_CountdownDate = "January 1, 2001";

	// Strings which shall be displayed to user before and after countdown
	private String m_preCountString = "There are ";
	private String m_postCountString = "remaining until event.";
	private String m_countdownReached = " Countdown expired. Target reached! ";
	private Color  m_background = Color.white;
	private Color  m_foreground = Color.red;

	// Parameter descriptions
	private final String PARAM_CountdownDate = "CountdownDate";
	private final String PARAM_PostCountName = "PostCountString";
	private final String PARAM_PreCountName  = "PreCountString";
	private final String PARAM_CountdownReached = "CountdownReached";
	private final String PARAM_Background = "Background";
	private final String PARAM_Foreground = "Foreground";

	// EnhancedCountdown Class Constructor
	public EnhancedCountdown()
	{
		super();
	}

	// Returns applet information
	public String getAppletInfo()
	{
		return "Name: EnhancedCountdown\r\n" +
			"Author: David Reilly\r\n" +
			"Created with Microsoft Visual J++ Version 1.1";
	}

	// PARAMETER SUPPORT
	//              The getParameterInfo() method returns an array of strings describing
	// the parameters understood by this applet.
	public String[][] getParameterInfo()
	{
		String[][] info =
		{
			{ PARAM_CountdownDate   , "String", "Date to which applet will countdown" },
			{ PARAM_PreCountName    , "String", "String before remaining countdown time" },
			{ PARAM_PostCountName   , "String", "String after remaining countdown time" },
			{ PARAM_CountdownReached, "String", "String when countdown expired" },
			{ PARAM_Background, "String", "String name of colour for background" },
			{ PARAM_Foreground, "String", "String name of colour for foreground" },
		};
		return info;            
	}

	// Initialise applet
	public void init()
	{
		// The following code retrieves the value of each parameter
		// specified with the <PARAM> tag and stores it in a member
		// variable.            
		String param;

		// CountdownDate: Date to which applet will countdown
		param = getParameter(PARAM_CountdownDate);

		if (param != null)
			m_CountdownDate = param;

		// PreCountString : Name of event
		param = getParameter(PARAM_PreCountName);

		if (param != null)
			m_preCountString = param;

		// PostCountString : Name of event
		param = getParameter(PARAM_PostCountName);

		if (param != null)
			m_postCountString = param;

		// CountdownReached : Name of event
		param = getParameter(PARAM_CountdownReached);

		if (param != null)
			m_countdownReached = param;

		// Background : Background colour
		param = getParameter(PARAM_Background);

		// Check for colour
		if (param != null)
		{
			// Check for the presence of a # char
			if (param.indexOf("#") != -1)
				param = param.substring (param.indexOf("#") +1);

			int cv=Integer.parseInt(param,16);
			Color color = new Color(cv);
			
			// Check to see if colour parsed correctly
			if (color != null)
				m_background = color;
		}

		// Foreground : Foreground colour
		param = getParameter(PARAM_Foreground);

		// Check for colour
		if (param != null)
		{
			// Check for the presence of a # char
			if (param.indexOf("#") != -1)
				param = param.substring (param.indexOf("#") +1);

			int cv=Integer.parseInt(param,16);
			Color color = new Color(cv);

			// Check to see if colour parsed correctly
			if (color != null)
				m_foreground = color;
		}

        // Calculate date
		m_Date = new Date(m_CountdownDate);

		// Set background
		setBackground(m_background);

		// Set foreground
		setForeground(m_foreground);

		// Set font
		setFont ( new Font("Times New Roman", Font.PLAIN, 13) );

		// Start new thread to calculate date
		start();
	}


    // Countdown Paint Handler
	public void paint(Graphics g)
	{
		FontMetrics fm = g.getFontMetrics();

        int strWidth = fm.stringWidth(countString);

		int appletWidth = size().width;

		g.drawString(countString, (appletWidth - strWidth) / 2, 20);
	}

    // Start method to launch thread
	public void start()
    {
		// Check to see if thread still active
		if (m_Countdown == null)
		{
			// Create new thread
			m_Countdown = new Thread(this);

			// Start thread
			m_Countdown.start();
		}               
	}
        
        // Stop method to stop thread
        public void stop()
        {
                // Check to see if thread still active
                if (m_Countdown != null)
                {
                        // Stop thread
                        m_Countdown.stop();

                        // Clear thread, so garbage collection can "clean up"
                        m_Countdown = null;
                }
        }

        // Run method to recalculate the countdown string
        public void run()
        {
                for (;;)
                {
                        try
                        {
                                Date currentDate = new Date();

                                if (m_Date.after(currentDate))
                                {
                                        // Calculate difference in dates
                                        long numericalDifference =  m_Date.getTime() - currentDate.getTime();

                                        // Divide by 1000 to find number of seconds difference
                                        numericalDifference = numericalDifference / 1000;
                                        
                                        // Get seconds
                                        int seconds = (int) numericalDifference % 60;

                                        // Get minutes
                                        numericalDifference = numericalDifference / 60;
                                        int minutes = (int) numericalDifference % 60;

                                        // Get hours
                                        numericalDifference = numericalDifference / 60;
                                        int hours = (int) numericalDifference % 24;

                                        // Get days
                                        numericalDifference = numericalDifference / 24;
                                        int days = (int) numericalDifference % 365;

                                        // Get years
                                        numericalDifference = numericalDifference / 365;
                                        int years = (int) numericalDifference;

                                        // Generate count string
                                        countString = m_preCountString + " ";

										// Check to see if year will be displayed
										if (years > 1 )
											countString = countString + years + " years, ";
										else
										if (years == 1)
											countString = countString + years + " year, ";

										// Check to see if days will be displayed
										if (days > 1)
											countString = countString + days + " days, ";
										else
										if (days == 1)
											countString = countString + days + " day, ";

										// Check to see if hours will be displayed
										if (hours > 1)
											countString = countString + hours + " hours, ";
										else
										if (hours == 1)
											countString = countString + hours + " hours, ";

										// Check to see if minutes will be displayed
										if (minutes > 1)
											countString = countString + minutes + " minutes, ";
										else
										if (minutes == 1)
											countString = countString + minutes + " minutes, ";


										// Check to see if minutes will be displayed
										if (seconds > 1)
											countString = countString + seconds + " seconds ";
										else
										if (minutes == 1)
											countString = countString + seconds + " seconds ";

										// Append postCountString
										countString = countString + m_postCountString;
                                }
                                else
                                        countString = m_countdownReached;

                                // Repaint applet canvas
                                repaint();
                                
                                // Sleep for a second
                                Thread.sleep(1000);
                        }
                        catch (InterruptedException e)
                        {
                                // If we're interrupted, then stop thread
                                stop();
                        }
                }
        }
}