#!/usr/bin/perl

# converts the trash xml file of AWS Stuttgart (Open pdf in word, convert it to odt, open in LibreOffice, export it as xml) to the txt file needed by Smarthome
$year = 2023;
$filexml = "AWS-Abfallkalender_$year.xml";
$filetxt = "AWS-Abfallkalender_$year.txt";
$leapyear = 0;
@monthnames = ("Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember");
@daynames = ("Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag", "Sonntag");
@summaries = ("rest", "bio", "paper", "yellow");
@summarywords = ("Restmüll", "Biomüll", "Altpapier", "Gelber Sack");
@bioweeks = ();
for($i=0;$i<53;$i++){ $bioweeks[$i] = 0; }

$intro = <<"END";

Abfallwirtschaft Stuttgart
Dienstleistungen
Informationen
Logo Stuttgart
Abfuhrtermine für Hochfirststr. 26
Stadtbezirk: Süd, Stadtteil: Kaltental
Für die Abfuhrtermine benötigen Sie Ihren jeweiligen Leerungsrhythmus.
Hinweis: Abfuhrtermine können betriebsbedingt abweichen! Wir empfehlen bei Bedarf diese Abfrage erneut durchzuführen.

Zeitraum: 01.01.2023 - 31.01.2023
END

$outro = "\nEin Angebot der Landeshauptstadt Stuttgart, Haupt- und Personalamt, Abteilung eGovernment - Impressum";

println("- read file $filexml ...");
open(F, "<$filexml") or die("ERROR: cannot read file $filexml: $!");
while(<F>){	
	$line = $_;
	chomp($line);
	if($line=~/<row/){
		$cellid = -1;
	}
	elsif($line=~/^\d+.*<Text/i){
		$line =~ s/<.+$//;
		$type = trim($line); # 30. Sa 2 !
		($daynr, $dayshort, @rest) = split(/\s+/, $type);
		if(
			(!$leapyear and $daynr>=29 and $cellid==0) or
			($leapyear and $daynr>29 and $cellid==0) or
			($daynr==31 and ($cellid==2 or $cellid==4 or $cellid==7 or $cellid==9))
		){
			$cellid++;
		}
		$cellid++;
		$monthname = $monthnames[$cellid];
		$type = trim(join("", @rest));
		$monthnr = d2(getMonthNr($monthname));
		$daynr =~ s/\D//g;
		$daynr = d2(int($daynr));
		$dayfull = getFullDayName($dayshort);
		$weeknr = getWeekNumberOfDateString("$year-$monthnr-$daynr");
#		println("$monthname, $dayfull $daynr.$monthnr.$year ($type)");
		if($type=~/P/){ # paper and yellow at the same day
			push(@{$typedates{"paper"}}, "$year$monthnr$daynr	$dayfull	$daynr.$monthnr.$year	03-wöchentl.");
			push(@{$typedates{"yellow"}}, "$year$monthnr$daynr	$dayfull	$daynr.$monthnr.$year	03-wöchentl.");
		}
		if($type=~/2/){
			push(@{$typedates{"rest"}}, "$year$monthnr$daynr	$dayfull	$daynr.$monthnr.$year	02-wöchentl.");
		}
		if($type=~/\*/){
			push(@{$typedates{"bio"}}, "$year$monthnr$daynr	$dayfull	$daynr.$monthnr.$year	01-wöchentl.");
			$bioweeks[$weeknr-1] = 1;
		}
		if($type!~/P/ and $type!~/2/ and $type!~/\*/){
			if($type=~/!/){
				push(@{$typedates{"bio"}}, "$year$monthnr$daynr	$dayfull	$daynr.$monthnr.$year	01-wöchentl.");
				$bioweeks[$weeknr-1] = 1;
			}
		}
	}
}
close(F);

# now for every week, in which no bio has been found, push one
# so at first we need the first Thursday of the year
$isThursday = 0;
$daynr = 1;
while(!$isThursday){
	$firstThursday = "$year-01-0$daynr";
	$weekday = getWeekDay($firstThursday);
	last if($weekday eq "Th");
	$daynr++;
}
# $firstThursday is e.g. 2023-01-05
$firstThursdayTS = date2timestamp($firstThursday);
for($w=0;$w<53;$w++){
	next if($bioweeks[$w]);
	$weekThursdayTS = $firstThursdayTS + ($w * 24 * 3600 * 7);
	$weekThursday = timestamp2date($weekThursdayTS);
	next if($weekThursday!~/^$year/);
	($year, $monthnr, $daynr) = split(/\-/, $weekThursday);
	push(@{$typedates{"bio"}}, "$year$monthnr$daynr	Donnerstag	$daynr.$monthnr.$year	01-wöchentl.");
}

println("- write file $filetxt ...");
open(F, ">$filetxt") or die("ERROR: cannot write file $filetxt: $!");
print F $intro;
for($s=0;$s<$#summaries+1;$s++){
	$type = $summaries[$s];
	$typeword = $summarywords[$s];
	print F " $typeword";
	@dates = sort(@{$typedates{$type}});
	for($d=0;$d<$#dates+1;$d++){
		$date = $dates[$d];
		$date =~ s/^\d{8}\s+//;
		print F "\n". $date;
	}
	print F "\n";
}
print F "$outro";
close(F);
println("DONE.");


sub getMonthNr{
	my $month = shift;
	for(my $m=0;$m<$#monthnames+1;$m++){
		return $m+1 if($month eq $monthnames[$m]);
	}
	return -1;
}
sub getFullDayName{
	my $day = shift;
	for(my $m=0;$m<$#daynames+1;$m++){
		return $daynames[$m] if($daynames[$m]=~/$day/);
	}
	return "None";
}
sub getWeekNumberOfDateString{
	my $datestr = shift;
	my $format = shift;
	$format = "%Y-%m-%d" if($format!~/\S/);
	use Time::Piece;
	my $dt = Time::Piece->strptime($datestr, $format);
	return $dt->strftime("%W");
}


### functions ###
sub println{
	my $msg = shift;
	print $msg ."\n";
}
sub trim{
	my $msg = shift;
	$msg =~ s/^\s+//;
	$msg =~ s/\s+$//;
	return $msg;
}
sub timestamp2date{
	my $datets = shift;
	my ($tsec, $tmin, $thour, $tday, $tmon, $tyear) = localtime($datets);
	$tmon = d2($tmon+1); $tyear += 1900; $tday = d2($tday);
	return "$tyear-$tmon-$tday";
}
# convert a date [YY]YY-MM-DD [hh:ss:[mm]] to a timestamp
sub date2timestamp{
	my $datetime = shift;
	$datetime .= " 00:00:00" if($datetime=~/^\d+\-\d{2}\-\d{2}$/);
	my @elems = split(/\s+/, $datetime);
	my $time = pop(@elems);
	$time = trim($time);
	$time = "00:00" if($time!~/\S/);
	$time .= ":00" if($time=~/^\d\d:\d\d$/);
	my @timeelems = split(/:/, $time);
	my $hour = d2($timeelems[0]);
	my $minute = d2($timeelems[1]);
	my $second = d2($timeelems[2]);
	my $date = date2mysql(join(" ", @elems));
	my($year, $month, $day) = split(/\-/, $date);
	$year = "20$year" if(length($year)==2 and $day=~/\S/);
	if($day!~/\S/){
		$day = $month;
		$month = $year;
		my ($tsec, $tmin, $thour, $tday, $tmon, $tyear) = localtime(time);
		$year = $tyear;
	}
	use Time::Local;
	$month--;
	timelocal("$second","$minute","$hour",$day,$month,$year);
}
sub d2{
	my $number = shift;
	return "0$number" if($number<10);
	return $number;
}

sub getWeekDay{
	my $date = shift;
	my $mode = shift;
	$mode = "en" if($mode!~/\S/);
	my @weekdays = ("Su", "Mo", "Tu", "We", "Th", "Fr", "Sa");
	@weekdays = ("So", "Mo", "Di", "Mi", "Do", "Fr", "Sa") if($mode eq "de");
	@weekdays = ("Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag") if($mode eq "defull");
	$timestamp = date2timestamp(date2mysql($date));
	my ($sec, $min, $hour, $mday, $month,
    $year, $wday, $yday, $summertime) = localtime($timestamp);
	return $weekdays[$wday];
}
sub date2mysql{
	my $val = shift;
	my $date = "";
	$val = trim($val);
	$date = "$3-$2-$1" if($val=~/^(\d\d)\.(\d\d)\.(\d\d\d\d)/);
	$date = "$1-$2-$3" if($val=~/^(\d\d\d\d)\-(\d\d)\-(\d\d)/);
	$date = "$3-$2-$1" if($val=~/^(\d\d)\/(\d\d)\/(\d\d\d\d)/);
	$date = "$3-$2-$1" if($val=~/^(\d\d)\-(\d\d)\-(\d\d\d\d)/);
	if($val=~/(\d+)[stndrh\.]{0,2}\s*(\w{3,10})\s*(\d\d\d\d)/i or $val=~/(\d\d\d\d)\s*(\w{3,10})\s*(\d+)\s*[stndrh\.]{0,2}/i){
		my $day = trim($1);
		my $mname = trim($2);
		my $year = trim($3);
		if($day=~/\d{4}/){
			my $tmp = $year;
			$year = $day;
			$day = $tmp;
		}
		$mnr = 1;
		$mnr = 2 if($mname=~/feb/i);
		$mnr = 3 if($mname=~/m[a.]r/i);
		$mnr = 4 if($mname=~/apr/i);
		$mnr = 5 if($mname=~/ma[yi]/i);
		$mnr = 6 if($mname=~/jun/i);
		$mnr = 7 if($mname=~/jul/i);
		$mnr = 8 if($mname=~/aug/i);
		$mnr = 9 if($mname=~/sep/i);
		$mnr = 10 if($mname=~/o[ck]t/i);
		$mnr = 11 if($mname=~/nov/i);
		$mnr = 12 if($mname=~/de[cz]/i);
		$date = "$year-". d2($mnr) ."-$day";
	}
	return $date;
}
sub inArray{
	my $elem = shift;
	my $ref = shift;
	my $isin = 0;
	my $arrelem = "";
	foreach $arrelem(@{$ref}){
		return 1 if($arrelem eq $elem);
	}
	return 0;
}
