// © 1998 Björn Victor

import java.applet.*;
import java.lang.*;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.util.Calendar;
import java.util.GregorianCalendar;


public final class HolidayApplet extends Applet
    implements ActionListener {

    String mprint(int day) {
	if (day <= 31)
	    return (day+ " mars");
	else if (day <= (31+30))
	    return ((day-31)+" april");
	else if (day <= (31+30+31))
	    return ((day-31-30)+" maj");
	else if (day <= (31+30+31+30))
	    return ((day-31-30-31)+" juni");
	else
	    return (day+" mars");

    }

    int easterday_march(int y) {
	// See http://www.cacs.usl.edu/~manaris/fall96/cs150-handouts/hmwk5.txt
	// There are four years, 1954,
	// 1981, 2049, and 2076, for which the algorithm gives a date that is 
	// seven days later than it should be.

	int a,b,c,d,e;

	a = y % 19;
	b = y % 4;
	c = y % 7;
	d = (19*a + 24) % 30;
	e = (2*b + 4*c + 6*d + 5) % 7;

	return (22 + d + e);
	// this is the nth day of March
    }

    int easterday (int y) {
	// See http://aa.usno.navy.mil/AA/faq/docs/faq4.html
	int c, n, k, i, j, l, m, d;

	c = y / 100;
	n = y - 19 * ( y / 19 );
	k = ( c - 17 ) / 25;
	i = c - c / 4 - ( c - k ) / 3 + 19 * n + 15;
	i = i - 30 * ( i / 30 );
	i = i - ( i / 28 ) * ( 1 - ( i / 28 ) * ( 29 / ( i + 1 ) )
			       * ( ( 21 - n ) / 11 ) );
	j = y + y / 4 + i + 2 - c + c / 4;
	j = j - 7 * ( j / 7 );
	l = i - j;
	m = 3 + ( l + 40 ) / 44; // month
	d = l + 28 - 31 * ( m / 4 ); // day

	return((m == 3 ? d : d+31));
    }


    Button button;
    TextField yearfield;
    TextArea display;

    public void init() {
	
	Panel up = new Panel();
	up.setFont(new Font("SansSerif",Font.PLAIN,12));
	up.setLayout(new FlowLayout(FlowLayout.LEFT,5,5));

	Label l = new Label("Vilket år: ",Label.RIGHT);
	int year = Calendar.getInstance().get(Calendar.YEAR);
	yearfield = new TextField(new Integer(year).toString(),6);


	button = new Button("Beräkna helgdagar");
	up.add(l);
	up.add(yearfield);
	up.add(button);
	button.addActionListener(this);

	Panel down = new Panel();
	down.setFont(new Font("SansSerif",Font.PLAIN,12));
	display = new TextArea("",12,30,TextArea.SCROLLBARS_NONE);
	down.add(display);

	setLayout(new BorderLayout());
	add("North",up);
	add("Center",down);

	validate();
    }

//     public synchronized void start() {
// 	button.enable();
//     }
//     public synchronized void stop() {
// 	button.disable();
//     }

    public void actionPerformed(ActionEvent event) {
	// bergis en knapptryckning?
	display.setText(getHolidays(new Integer(yearfield.getText()).intValue()));
	validate();
    }

    String getHolidays(int year) {
	int easter;

	easter = easterday(year);
	// midsommardagen den lördag som infaller under tiden den 20--26 juni
	GregorianCalendar ms = new GregorianCalendar(year,6-1,20);
	int msd = (20+ (Calendar.SATURDAY-ms.get(Calendar.DAY_OF_WEEK)));
	// alla helgons dag den lördag som infaller under tiden den 31
	// oktober--den 6 november
	GregorianCalendar ah = new GregorianCalendar(year,10-1,31);
	int ahd = (Calendar.SATURDAY-ms.get(Calendar.DAY_OF_WEEK));


	return ("Nyårsdagen: 1 januari\n"+
		"Trettondagen: 6 januari\n" +
		"Långfredag: "+ mprint(easter-2) +"\n"+
		"Påskdagen: "+	mprint(easter) +"\n"+
		"Annandag påsk: " + mprint(easter+1) +"\n"+
		"Kristi himmelsfärdsdag: "+ mprint(easter+5*7+4) +"\n"+
		"Pingstdagen: " + mprint(easter+7*7) + "\n"+
		"Annandag pingst: "+ mprint(easter+7*7+1)+"\n"+
		"Midsommardagen: "+ msd+ " juni\n"+
		"Alla helgons dag: "+
		(ahd == 0 ? "31 oktober\n"
		 : (ahd+" november\n"))+
		"Juldagen: 25 december\n"+
		"Annandag jul: 26 december");

    }
}
