#!/usr/bin/perl -w

use strict;

use Test::More tests => 15;

use DateTime::Format::ICal;
use DateTime::Span;

my $ical = 'DateTime::Format::ICal';

{
    # this is an example from rfc2445 
    my $recur =
        $ical->parse_recurrence( recurrence => 'freq=monthly;count=10;byday=1fr',
                                 dtstart    => $ical->parse_datetime( '19970905T090000' )
                               );
    my @r;
    while ( my $dt = $recur->next )
    {
        push @r, $ical->format_datetime( $dt );
    }

    my $s1 = join ',', @r;

    my $s2 = join ',', qw( 1997-09-05T09:00:00
                           1997-10-03T09:00:00
                           1997-11-07T09:00:00
                           1997-12-05T09:00:00
                           1998-01-02T09:00:00
                           1998-02-06T09:00:00
                           1998-03-06T09:00:00
                           1998-04-03T09:00:00
                           1998-05-01T09:00:00
                           1998-06-05T09:00:00
                         );

    $s2 =~ s/[-:]//g;

    is( $s1, $s2, "recurrence parser is ok" );
}

{
    # DTSTART;TZID=US-Eastern:19980101T090000
    # RRULE:FREQ=YEARLY;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA
    my $recur =
        $ical->parse_recurrence
            ( recurrence => 'FREQ=YEARLY;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA',
              dtstart    => $ical->parse_datetime( '19980101T090000' )
            );

    my @str = $ical->format_recurrence( $recur );
    is( "@str", 'RRULE:FREQ=YEARLY;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA',
        'unbounded recurrence formats ok' );

    my $union = $recur->union( 
                           $ical->parse_datetime( '19980303T030303' )
                        );
    @str = $ical->format_recurrence( $union );
    is( "@str", 'RRULE:FREQ=YEARLY;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA '.
                'RDATE:19980303T030303',
        'unbounded recurrence union formats ok' );

    my $recur2 =
        $ical->parse_recurrence
            ( recurrence => 'FREQ=YEARLY;BYMONTH=2;BYDAY=SU,MO,TU,WE,TH,FR,SA',
              dtstart    => $ical->parse_datetime( '19980101T090000' )
            );

    my $union2 = $recur->union( $recur2 );
    @str = $ical->format_recurrence( $union2 );
    is( "@str", 'RRULE:FREQ=YEARLY;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA '.
                'RRULE:FREQ=YEARLY;BYMONTH=2;BYDAY=SU,MO,TU,WE,TH,FR,SA',
        'union of unbounded recurrences formats ok' );

    my $union3 = $union2->union(
                           $ical->parse_datetime( '19980303T030303' )
                        );
    @str = $ical->format_recurrence( $union3 );
    is( "@str", 'RRULE:FREQ=YEARLY;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA '.
                'RRULE:FREQ=YEARLY;BYMONTH=2;BYDAY=SU,MO,TU,WE,TH,FR,SA '.
                'RDATE:19980303T030303',
        'deep union of unbounded recurrences formats ok' );

    # exclude date

    my $exclude = $union2->union(
                           $ical->parse_datetime( '19980303T030303' )
                        )->complement(
                           $ical->parse_datetime( '19980404T040404' )
                        );
    @str = $ical->format_recurrence( $exclude );
    is( "@str", 'RRULE:FREQ=YEARLY;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA '.
                'RRULE:FREQ=YEARLY;BYMONTH=2;BYDAY=SU,MO,TU,WE,TH,FR,SA '.
                'RDATE:19980303T030303 '.
                'EXDATE:19980404T040404',
        'complement of date formats ok' );

    # clone keeps formatting

    @str = $ical->format_recurrence( $exclude->clone );
    is( "@str", 'RRULE:FREQ=YEARLY;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA '.
                'RRULE:FREQ=YEARLY;BYMONTH=2;BYDAY=SU,MO,TU,WE,TH,FR,SA '.
                'RDATE:19980303T030303 '.
                'EXDATE:19980404T040404',
        'clone formats ok' );

    # exclude rule
    # exclude date + exclude rule

    my $exclude2 = $exclude->complement( $recur );
    @str = $ical->format_recurrence( $exclude2 );
    is( "@str", 'RRULE:FREQ=YEARLY;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA '.
                'RRULE:FREQ=YEARLY;BYMONTH=2;BYDAY=SU,MO,TU,WE,TH,FR,SA '.
                'RDATE:19980303T030303 '.
                'EXDATE:19980404T040404 '.
                'EXRULE:FREQ=YEARLY;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA',
        'complement of rule formats ok' );

    # exclude date + add date should die
    # exclude rule + add date should die

    my $mixed = $exclude->union( 
                           $ical->parse_datetime( '19980303T030303' )
                        );
    @str = ('Error');
    eval { @str = $ical->format_recurrence( $mixed ); };  # should die!
    is( "@str", 'Error',
        'exclude + complement of date cannot format' );


    # date + exclude rule -- should fail

    my $mixed2 = DateTime::Set->from_datetimes( 
                     dates => [ 
                         $ical->parse_datetime( '19980303T030303') 
                     ] )
                 ->union ( $recur );
    @str = ('Error');
    eval { @str = $ical->format_recurrence( $mixed2 ); };  # should die!
    is( "@str", 'Error',
        'unblessed date + recurrence cannot format' );


    # blessed date + rule

    my $mixed3 = DateTime::Set::ICal->from_datetimes(
                     dates => [
                         $ical->parse_datetime( '19980303T030303')
                     ] )
                 ->union ( $recur );
    @str = ('Error');
    eval { @str = $ical->format_recurrence( $mixed3 ); };  # should not die!
    is( "@str", 'RDATE:19980303T030303 '.
                'RRULE:FREQ=YEARLY;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA',
        'blessed date + recurrence formats ok' );

    # blessed date + exclude rule
    # NOTE: this test was removed because the result of
    #  complement is not unbounded!
    #
    # my $mixed4 = DateTime::Set::ICal->from_datetimes(
    #                 dates => [
    #                     $ical->parse_datetime( '19980303T030303')
    #                 ] )
    #             ->complement ( $recur );
    # @str = ('Error');
    # eval { @str = $ical->format_recurrence( $mixed4 ); };  # should not die!
    # is( "@str", 'RDATE:19980303T030303 '.
    #            'EXRULE:FREQ=YEARLY;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA',
    #     'blessed date + exclude recurrence formats ok' );


}

{
    # another example from rfc2445
    # DTSTART;TZID=US-Eastern:19980101T090000
    # RRULE:FREQ=YEARLY;UNTIL=2000-01-31T09:00:00;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA
    my $recur =
        $ical->parse_recurrence
            ( recurrence => 'FREQ=YEARLY;UNTIL=20000131T090000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA',
              dtstart    => $ical->parse_datetime( '19980101T090000' )
            );

    my @r;
    my @dt;
    for ( 1 .. 2 )
    {
        my $dt = $recur->next;
        push @dt, $dt;
        push @r, $ical->format_datetime( $dt );
    }

    my $s1 = join ',', @r;

    my $s2 = join ',', ( '1998-01-01T09:00:00',
                         '1998-01-02T09:00:00'
                       );

    $s2 =~ s/[-:]//g;

    is( $s1, $s2, "recurrence parser with 'until' is ok" );

    # recurrence formatter

    my @str = $ical->format_recurrence( @dt );
    is( "@str", 'RDATE:19980101T090000,19980102T090000',
        'datetime recurrence formats ok' );

    # recurrence formatter - with mixed timezones

    $dt[0]->set_time_zone( 'UTC' );
    $dt[1]->set_time_zone( 'America/Chicago' );
    @str = $ical->format_recurrence( @dt );
    is( "@str", 'RDATE:19980101T090000Z '.
                'RDATE;TZID=America/Chicago:19980102T090000',
        'datetime with time zones recurrence formats ok' );

    # recurrence formatter - with spans

    push @dt, $recur->next;
    # the end time zone will be translated to 
    # the start time zone (America/Chicago)
    $dt[2]->set_time_zone( 'America/New-York' );
    my $spanset = DateTime::SpanSet->from_spans(
        spans => [
            DateTime::Span->from_datetimes( start => $dt[0], end => $dt[0] ),
            DateTime::Span->from_datetimes( start => $dt[1], before => $dt[2]),
        ]
    );
    @str = $ical->format_recurrence( $spanset );
    is( "@str", 
        'RDATE:19980101T090000Z '.
        'RDATE;VALUE=PERIOD;TZID=America/Chicago:19980102T090000/19980103T080000',
        'datetime spans with time zones recurrence formats ok' );
}

1;