/*
	Karl's Throw - away 2000 ad count down counter
	Revision History
	V 0.0	05 Apr 97	Intitial dabblings
	V 0.1	08 Apr		User interface layout
	v 0.2	09 Apr		First working version
	v 0.3	10 Apr		Seconds pop up
	v 0.5	27 Apr		Days pop, fix pop up positions for pcs
	v 1.0	08 May		Final realease
	
	Karl Grabe
	Cork
	grabe@angelic.com
	http://indigo.ie/~grabe
*/
import java.util.*;
import java.awt.*;
import java.applet.Applet;
import java.awt.Color;

public class ClockDown extends Applet implements Runnable
{
	Thread 		timer = null;			// Thread that runs to update time display

	// User interface items
	Panel 		ClockPanel;
	Label		DateTime;
	Label		title;
	Label		CDsecs;					// CountDown seconds
	Label		CDdays;					// CoundDown days
	Color		theColor;
	Button		TimeNow;				// Click to display current time
	Choice		SecondsPop;				// seconds pop up menu
	Choice		DaysPop;				// days pop up

	Button[]	Spiral;					// Array to hold spiral buttons
	final int	SpiralBits 	= 30;		// Number of bits (buttons in spiral + 1)
	long		OffsetMS 	=0; 		// Display time but offset by this number of milli seconds
	long 		MilleniumMS;			// Next Millenium represented in ms
	long		timeNowMS;				// Time NOW in MS
	long 		timeMS;					// time now + offset in millisecond
	long		MSleft;					// Milliseconds left to millenium including offset

	Date 		DateNow; 				// current date
	Date 		MilleniumDate;			// next millenium date (2000)

	String 		DateNowTxt;


	public void init() {
	
		// Throw up user interface using JPob generator
		JReanimator animator = new JReanimator();
		ClockPanel = (Panel)animator.make("ClockPanel");
		add (ClockPanel);
		Rectangle r = ClockPanel.bounds();
		resize( r.width, r.height);

		Spiral = new Button [SpiralBits +1 ];					// Array to hold spiral buttons
		MilleniumDate	= new Date (100,0,1,0,0,0);     		// init to 2000
		
		// Locate Java Constructor Items
		for (int btnCount = 0; btnCount < SpiralBits; btnCount++) {
			Spiral [btnCount]	= (Button)animator.locate ("ClockPanel",	"b" + btnCount);
		}
		DateTime	= (Label)animator.locate		("ClockPanel",	"DateTime");
		title		= (Label)animator.locate		("ClockPanel",	"title");
		CDsecs		= (Label)animator.locate		("ClockPanel",	"CDsecs");
		CDdays		= (Label)animator.locate		("ClockPanel",	"CDdays");
		TimeNow		= (Button)animator.locate 		("ClockPanel",	"TimeNow");
		SecondsPop	= (Choice)animator.locate 		("ClockPanel",	"SecondsPop");
		DaysPop		= (Choice)animator.locate 		("ClockPanel",	"DaysPop");

		//JPob bug workaround
		SecondsPop.move 	(16,88);
		DaysPop.move		(16,112);
		
		
		// put default character into spiral buttons
		for (int btnCount = 0; btnCount < SpiralBits; btnCount++) {
			Spiral [btnCount].setLabel("*");
		}

		MilleniumMS = MilleniumDate.getTime();

		TimeNow.hide ();			// hide the button to show current time
		
		repaint();
		validate ();
	}
	
	// Handle click on the spiral and other panel objects
	public boolean action(Event e, Object arg) {
		String	SelectedSecondsTxt;
		Long	SelectedSeconds;
		String	SelectedDaysTxt;
		Long	SelectedDays;
		
		
		if (e.target == TimeNow) {
			OffsetMS = 0;
			TimeNow.hide ();		
			}
		
		// check if user hit a button in spiral & then change time left if so
		for (int btnCount = 0; btnCount < SpiralBits; btnCount++) {
			if (e.target == Spiral [btnCount]) {
				TimeNow.show ();									// Show the reset button
			//	System.out.println ("button hit: " + btnCount);
				OffsetMS = 1 << (btnCount + 1);
			//	System.out.println ("(OffsetMS << btnCount)) =" + (OffsetMS << btnCount));
			//	System.out.println ("MilleniumMS = " + MilleniumMS);
				OffsetMS =   MilleniumMS - timeNowMS - 1000*OffsetMS;
				
			}				
		}

		// user changed number of days to go		
		if (e.target == DaysPop){
			SelectedDaysTxt = DaysPop.getSelectedItem();
			try {
				SelectedDays = Long.valueOf(SelectedDaysTxt);
			} catch (Exception ex) {
				SelectedDays = new Long (0);
				return super.action(e, arg);					// yes, I know, this is awful
			}

			OffsetMS =   MilleniumMS - timeNowMS - 1000*((60*60*24) + 2) *SelectedDays.longValue();
			DaysPop.select(0);
			TimeNow.show ();									// Show the reset button
		}


		// user changed number of seconds to go		
		if (e.target == SecondsPop){
			SelectedSecondsTxt = SecondsPop.getSelectedItem();
			try {
				SelectedSeconds = Long.valueOf(SelectedSecondsTxt);
			} catch (Exception ex) {
				SelectedSeconds = new Long (0);
				return super.action(e, arg);					// yes, I know, this is awful
			}
	
			// the offset, trow in 2 extra seconds because of event delay
			OffsetMS =   MilleniumMS - timeNowMS - 1000*(SelectedSeconds.longValue() + 2);
			SecondsPop.select(0);
			TimeNow.show ();									// Show the reset button
		}
		
		
	
		return super.action(e, arg);
	}

	
	public void start() {
	  if(timer == null)
	    {
	      timer = new Thread(this);
	      timer.start();
	    }
	}

	public void stop() {
	  timer = null;
	}

	public void run() {

		while (timer != null) {
		    try {Thread.sleep(1000);} catch (InterruptedException e){}
		    UpdateDisplay();
	  	}
		timer = null;
	}

// Update display: Spiral Counter, Date time diplay etc.	
	public void UpdateDisplay () {
		long 	tempLong;	

		long	SecondsLeft;
		
		DateNow = new Date();			// Get system time form host PC
		timeNowMS = DateNow.getTime();
		timeMS = timeNowMS + OffsetMS;	// offset time
		DateNow.setTime(timeMS);		// current time offset by OffsetMS.

		// Display current offset time		
		DateNowTxt = DateNow.toLocaleString();
		DateTime.setText (DateNowTxt);

		
		// Milli seconds to champagne
		if (MilleniumMS > timeMS) 
			MSleft = MilleniumMS - timeMS;	
		else
			MSleft = timeMS - MilleniumMS;
			
		SecondsLeft		= MSleft/1000;
				
		CDsecs.setText(String.valueOf (SecondsLeft));
		
		// and days
		CDdays.setText (String.valueOf (SecondsLeft/86400)); // *** need to add 1?
		
		// Display SpiralBinary
				
		tempLong = SecondsLeft;
		for (int SpiralCount = 0; SpiralCount < SpiralBits; SpiralCount++) {		
			if ((tempLong & 0x1) == 1) {
				Spiral [SpiralCount].setLabel("*");
				//Spiral [SpiralCount].setForeground (Color.black);
				
			} else {
				Spiral [SpiralCount].setLabel("");
				//Spiral [SpiralCount].setForeground (Color.white);

							
			}
			tempLong >>>= 1;		
		}
	}
}
