#!/usr/bin/perl

use strict;
use warnings;

use Date::Calc qw( Add_Delta_Days Day_of_Week );

sub pasen_datum ($) {
	my ($year) = @_;
	my $a = $year % 19;
	my $b = int($year / 100);
	my $c = $year % 100;
	my $d = int($b / 4);
	my $e = $b % 4;
	my $g = int( (8*$b + 13) / 25 );
	my $theta = int( (11*($b-$d-$g)-4) / 30 );
	my $phi = int( (7*$a+$theta+6) / 11 );
	my $psi = (19*$a+($b-$d-$g)+15-$phi) % 29;
	my $i = int( $c / 4 );
	my $k = $c % 4;
	my $lambda = ((32+2*$e)+2*$i-$k-$psi) % 7;
	my $n = int( (90+($psi+$lambda)) / 25 );
	my $p = (19+($psi+$lambda)+$n) % 32;
	return ($year, $n, $p);
}

sub vevent {
	my ($startyear, $startmonth, $startday, $endyear, $endmonth, $endday, $summary) = @_;
	print "BEGIN:VEVENT\n",
		"DTSTART;VALUE=DATE:", sprintf("%04d%02d%02d", $startyear, $startmonth, $startday), "\n",
		"DTEND;VALUE=DATE:", sprintf("%04d%02d%02d", $endyear, $endmonth, $endday), "\n",
		"SUMMARY:", $summary, "\n",
		"END:VEVENT\n";
}

sub vevent_recurring {
	my ($startyear, $startmonth, $startday, $endyear, $endmonth, $endday, $summary) = @_;
	print "BEGIN:VEVENT\n",
		"DTSTART;VALUE=DATE:", sprintf("%04d%02d%02d", $startyear, $startmonth, $startday), "\n",
		"DTEND;VALUE=DATE:", sprintf("%04d%02d%02d", $endyear, $endmonth, $endday), "\n",
		"SUMMARY:", $summary, "\n",
		"RRULE:FREQ=YEARLY;INTERVAL=1\n",
		"END:VEVENT\n";
}


sub longevent {
	my ($year, $month, $day, $days, $summary) = @_;
	my ($endyear, $endmonth, $endday) = Add_Delta_Days($year, $month, $day, $days);
	return vevent($year, $month, $day, $endyear, $endmonth, $endday, $summary);
}

sub dayevent {
	my ($year, $month, $day, $summary) = @_;
	return longevent($year, $month, $day, 1, $summary);
}


print "BEGIN:VCALENDAR\n";
vevent_recurring(2000, 1, 1, 2000, 1, 2, "Nieuwjaar");
vevent_recurring(2000, 5, 1, 2000, 5, 2, "Dag van de Arbeid");
vevent_recurring(2000, 7, 1, 2000, 9, 1, "Zomervakantie");
vevent_recurring(2000, 7, 21, 2000, 7, 22, "Nationale feestdag");
vevent_recurring(2000, 8, 15, 2000, 8, 16, "OLV Hemelvaart");
vevent_recurring(2000, 11, 1, 2000, 11, 2, "Allerheiligen");
vevent_recurring(2000, 11, 11, 2000, 11, 12, "Wapenstilstand");
vevent_recurring(2000, 12, 25, 2000, 12, 26, "Kerstmis");
for my $year (2000..2099) {
	my @pasen = pasen_datum($year);
	dayevent(@pasen, "Pasen");
	my @paasmaandag = Add_Delta_Days(@pasen, 1);
	dayevent(@paasmaandag, "Paasmaandag");
	my @pinksteren = Add_Delta_Days(@pasen, 7*7);
	dayevent(@pinksteren, "Pinksteren");
	my @pinkstermaandag = Add_Delta_Days(@pasen, 7*7+1);
	dayevent(@pinkstermaandag, "Pinkstermaandag");
	my @hemelvaart = Add_Delta_Days(@pinksteren, -10);
	dayevent(@hemelvaart, "Hemelvaart");

	my @krokus = Add_Delta_Days(@pasen, -7*7 -1);
	longevent( @krokus, 7+2, "Krokusvakantie" );

	my @paasvakantie;
	if( $pasen[1] == 3 ) {
		@paasvakantie = Add_Delta_Days(@pasen, -1);
	} elsif( $pasen[2] > 15 ) {
		@paasvakantie = Add_Delta_Days(@pasen, -15);
	} else {
		@paasvakantie = Add_Delta_Days($year, 4, 7, -Day_of_Week($year, 4, 7)-1);
	}
	longevent( @paasvakantie, 14+2, "Paasvakantie");

	# Herfstvakantie de week van 1 november; als 1 nov op zo valt, de dag erna
	my @herfstvakantie = Add_Delta_Days($year, 11, 1, -Day_of_Week($year, 11, 1)-1);
	longevent( @herfstvakantie, 7+2, "Herfstvakantie");

	# Begint de week waarin kerstmis valt, als kertmis op za of zo valt, begint ze de maandag erna
	my @kerstvakantie = Add_Delta_Days($year, 12, 27, -Day_of_Week($year, 12, 27)-1);
	longevent( @kerstvakantie, 14+2, "Kerstvakantie");
}
print "END:VCALENDAR\n";
