#!/usr/bin/perl
# Copyright © 2016 Jonas Smedegaard <dr@jones.dk>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
# Description: Create iCalendar file from multiline news chunks
#
# Depends: libdata-ical-perl libdatetime-timezone-perl libdatetime-format-ical-perl

use strict;
use warnings;

use Data::ICal;
use Data::ICal::Entry::Event;
use DateTime::TimeZone;
use DateTime::Format::ICal;

my $data;
my $calendar = Data::ICal->new( rfc_strict => 1, auto_uid => 1 );
my $tz = DateTime::TimeZone->new( name => 'local' );

# warn about resolved timezone
printf STDERR "using timezone %s - set environment variable TZ to override\n",
	$tz->name;

# slurp input
my @lines;
while (<>) {
	chomp;
	$data .= "$_\n";
}

# parse data and serialize as iCalendar events
#  * Events are newline-newline delimited
#  * First line contains date, location, time(s)
#    * String before date (e.g. weekday) is ignored
#    * Date is formatted as DD.MM.YYYY
#    * Times are formatted as either HH or HH:MM
#    * Times are space-hyphen-space delimited
#    * End time (and delimiter) is optional
#    * string after date (e.g. hour keyword) is ignored
#  * Second line is summary
#  * Third and subsequent lines are description
while (
	$data =~ m{
		(\d{1,2})[./](\d{1,2})[./](\d{4}),\h* # date
		([^\n]+?),?\h* # location
		(\d{1,2})(?::(\d{2}))? # start time
		(?:\h+-\h+(\d{1,2})(?::(\d{2}))?)? # end time
		(?:\h+Uhr)?\h*\n

		([^\n]+)\h*\n # description

		([^\n]+(?:\n[^\n]+)*)\h*\n(?:\n|\z) # description
	}gx
) {
	my ( $dtstart, $dtend );
	$dtstart = DateTime->new(
		year      => $3,
		month     => $2,
		day       => $1,
		hour      => $5,
		minute    => $6 || '00',
		time_zone => $tz,
	);
	if ( defined($7) ) {
		$dtend = DateTime->new(
			year      => $3,
			month     => $2,
			day       => $1,
			hour      => $7,
			minute    => $8 || '00',
			time_zone => $tz,
		);
	}
	my $location    = $4;
	my $summary     = $9;
	my $description = $10;

	my $vevent = Data::ICal::Entry::Event->new();
	$vevent->add_properties(
		dtstart     => DateTime::Format::ICal->format_datetime($dtstart),
		location    => $location,
		summary     => $summary,
		description => $description,
	);
	$vevent->add_property(
		dtend => DateTime::Format::ICal->format_datetime($dtend) )
		if ($dtend);
	$calendar->add_entry($vevent);
}

print $calendar->as_string;