#!/usr/bin/perl
##!/usr/bin/perlml

# By Mathias Moe (mathias@jpg.no) for Fr. James Smith, march 2019
use lib "/home/stfrancisdesales/";
use Data::ICal;
#use Data::ICal::Entry;
use DateTime;
use DateTime::Format::ICal;
use JSON;
use Data::Dumper;

sub ical_entry_type {'VEVENT'};

sub optional_unique_properties {
    my $self = shift;
    my @ret = $self->rfc_strict ? () : ("uid");
    if (not $self->vcal10) {
        push @ret, qw(
            class  created  description  dtstart  geo
            last-modified  location  organizer  priority
            dtstamp  sequence  status  summary  transp
            url  recurrence-id

            dtend duration
        );
    } else {
        push @ret, qw(
            class dcreated completed description dtstart dtend
            last-modified location rnum priority
            sequence status summary transp
            url
        );
    }
    return @ret;
}


# Set outfile here
my $outfile = "/home/apps1/htdocs/mathias/CalTest/sfds.ics";
my $infile   = "/home/apps1/htdocs/mathias/CalTest/jms.ics";
my $source = "http://www.rotundasoftware.com/ministry/FSSPATL/schedules/?pointer=last";
my $today = DateTime->now(time_zone => "local")->ymd('');

# Glob up the infile. We need to process it "manually" since Data::ICal doesn't have a
# parse method

my $document = do {
    local $/ = undef;
    open my $fh, "<", $infile or die "could not open $file: $!"; 
    <$fh>;
	};

my $start = "";
my $end  = "";

if ($document =~ s/(.*?)BEGIN:VEVENT/BEGIN:VEVENT/s) {
	$start = $1;
	chomp($start);
	}
if ($document =~ s/(.*)(END:VEVENT)//s) {
	$events     = "$1$2";
	$end = $document;
	}

# go trough the events and discart the ones that are too old
my @oks = ();
my @es = split('END:VEVENT', $events);
for $e (@es) {
	if ($e =~ m/DTSTART\:(\d+)/m) {
		$estart = $1;
		if ($estart + 0 >= $today) {
			push(@oks,$e);
			}
		}
	}

# Join the surviving elements back into $document, add start and end.
$document = ($start . join("END:VEVENT", @oks) . (scalar(@oks) ? "END:VEVENT" : "") . $end);

# Instanciate the calendar with the old calendar file
# my $calendar = Data::ICal->new(filename => $infile);
my $calendar = Data::ICal->new(data => $document);


# Data source
my $source = `curl -s -L "$source"`;

# Remove anything befor this
$source =~ s/^.*window.Baseline.bootstrapData =//s;

# Remove anything after this:
$source =~ s/^(.*?)\;window\.Baseline.*$/$1/s;


my $calendardata = decode_json($source);

my @masses = @{$calendardata->{ms}};

foreach $mass (@masses) {
	# print "$mass->{dateTime}: $mass->{name}\n";

	# Date-time is ALMOST ISO-8601
	my $datetime = $mass->{dateTime};
	$datetime =~ m/(\d{4})-(\d{2})-(\d{2})\s(\d{2})\:(\d{2})\:(\d{2})/;
	$dt = DateTime->new(
		year       => $1,
		month      => $2,
		day        => $3,
		hour       => $4,
		minute     => $5,
		second     => $6,
		nanosecond => 0
#		time_zone  => 'America/New_York'
		);

	$end = DateTime->new(
		year       => $1,
		month      => $2,
		day        => $3,
		hour       => $4,
		minute     => $5,
		second     => $6,
		nanosecond => 0
#		time_zone  => 'America/New_York'
		);


	# If name is set, use this else use label	
	my $summary = (($mass->{name} =~ m/\w/) ? $mass->{name} : $mass->{label});

	# Add hours and minutes to get end
	$end->add( hours => $mass->{duration}->{hours}, minutes => $mass->{duration}->{minutes} );

	
	my $ts = DateTime->now;

	my $vevent = Data::ICal::Entry::Event->new();
#	my $vevent = Data::ICal::Entry->new();

    $vevent->add_properties(
        summary => $summary,
        description => "",
        # Dat*e*::ICal is not a typo here
        dtstart   => DateTime::Format::ICal->format_datetime($dt),
        dtend     => DateTime::Format::ICal->format_datetime($end),
        dtstamp => DateTime::Format::ICal->format_datetime($ts),
        uid        => $mass->{_id}
        );


	$calendar->add_entry($vevent);
	}


open (FH, '>', "$outfile") or die $!;
print FH $calendar->as_string;
close FH;





package Data::ICal::Entry::Event;

use base qw/Data::ICal::Entry/;

=head1 NAME

Data::ICal::Entry::Event - Represents an event in an iCalendar file

=head1 SYNOPSIS

    my $vevent = Data::ICal::Entry::Event->new();
    $vevent->add_properties(
        summary => "my party",
        description => "I'll cry if I want to",
        # Dat*e*::ICal is not a typo here
        dtstart   => Date::ICal->new( epoch => time )->ical,
    );

    $calendar->add_entry($vevent);

    $vevent->add_entry($alarm);

=head1 DESCRIPTION

A L<Data::ICal::Entry::Event> object represents a single event in an
iCalendar file.  (Note that the iCalendar RFC refers to entries as
"components".)  It is a subclass of L<Data::ICal::Entry> and accepts
all of its methods.

=head1 METHODS

=cut

=head2 ical_entry_type

Returns C<VEVENT>, its iCalendar entry name.

=cut

sub ical_entry_type {'VEVENT'}

=head2 mandatory_unique_properties

The C<uid> property is mandatory if C<rfc_strict> was passed to
L<Data::ICal/new>.

=cut

sub mandatory_unique_properties {
    my $self = shift;
    return $self->rfc_strict ? ("uid") : ()
}

=head2 optional_unique_properties

According to the iCalendar standard, the following properties may be
specified at most one time for an event:

        class  created  description  dtstart  geo
        last-modified  location  organizer  priority
        dtstamp  sequence  status  summary  transp
        uid  url  recurrence-id

In addition, C<dtend> and C<duration> may be specified at most once
each, but not both in the same entry (though this restriction is not
enforced).

Or if C<< vcal10 => 1 >>:

        class dcreated completed description dtstart dtend
        last-modified location rnum priority
        sequence status summary transp
        url uid

=cut

sub optional_unique_properties {
    my $self = shift;
    my @ret = $self->rfc_strict ? () : ("uid");
    if (not $self->vcal10) {
        push @ret, qw(
            class  created  description  dtstart  geo
            last-modified  location  organizer  priority
            dtstamp  sequence  status  summary  transp
            url  recurrence-id

            dtend duration
        );
    } else {
        push @ret, qw(
            class dcreated completed description dtstart dtend
            last-modified location rnum priority
            sequence status summary transp
            url
        );
    }
    return @ret;
}

=head2 optional_repeatable_properties

According to the iCalendar standard, the following properties may be
specified any number of times for an event:

        attach  attendee  categories  comment
        contact  exdate  exrule  request-status  related-to
        resources  rdate  rrule

Or if C<< vcal10 => 1 >>:

        aalarm  attach  attendee  categories
        dalarm  exdate  exrule  malarm  palarm  related-to
        resources  rdate  rrule

=cut

sub optional_repeatable_properties {
    my $self = shift;
    if (not $self->vcal10) {
        qw(
            attach  attendee  categories  comment
            contact  exdate  exrule  request-status  related-to
            resources  rdate  rrule
        );
    } else {
        qw(
            aalarm  attach  attendee  categories
            dalarm  exdate  exrule  malarm  palarm  related-to
            resources  rdate  rrule
        );
    }
}

=head1 SEE ALSO

=over 4

=item L<Data::ICal::DateTime>

For date parsing and formatting, including denoting "all day" events,
considering using this module. Because it's a "mix in", you can still
use all the methods here as well as the new date handling methods it
defines.

=back

=head1 AUTHOR

Best Practical Solutions, LLC E<lt>modules@bestpractical.comE<gt>

=head1 LICENCE AND COPYRIGHT

Copyright (c) 2005 - 2015, Best Practical Solutions, LLC.  All rights reserved.

This module is free software; you can redistribute it and/or
modify it under the same terms as Perl itself. See L<perlartistic>.

=cut

1;


