#!perl
use Cassandane::Tiny;

sub test_calendarevent_set_standalone_instances_create
    :min_version_3_5
{
    my ($self) = @_;
    my $jmap = $self->{jmap};
    my $caldav = $self->{caldav};

    xlog "Get event state";
    my $res = $jmap->CallMethods([
        ['CalendarEvent/get', {
            properties => [],
        }, 'R2'],
    ]);
    my $state = $res->[0][1]{state};

    xlog "Create standalone instance";
    $res = $jmap->CallMethods([
        ['CalendarEvent/set', {
            create => {
                instance1 => {
                    calendarIds => {
                        'Default' => JSON::true,
                    },
                    '@type' => 'Event',
                    uid => 'event1uid',
                    title => 'instance1',
                    start => '2021-01-01T11:11:11',
                    timeZone => 'Europe/Berlin',
                    duration => 'PT1H',
                    recurrenceId => '2021-01-01T01:01:01',
                    recurrenceIdTimeZone => 'Europe/London',
                },
            },
        }, 'R1'],
        ['CalendarEvent/get', {
            ids => ['#instance1'],
            properties => ['start', 'timeZone', 'recurrenceId', 'recurrenceIdTimeZone'],
        }, 'R2'],
        ['CalendarEvent/changes', {
            sinceState => $state,
        }, 'R3'],
    ]);
    my $instance1Id = $res->[0][1]{created}{instance1}{id};
    $self->assert_not_null($instance1Id);
    my $xhref1 = $res->[0][1]{created}{instance1}{'x-href'};
    $self->assert_not_null($xhref1);
    $self->assert_str_equals('2021-01-01T11:11:11',
        $res->[1][1]{list}[0]{start});
    $self->assert_str_equals('Europe/Berlin',
        $res->[1][1]{list}[0]{timeZone});
    $self->assert_str_equals('2021-01-01T01:01:01',
        $res->[1][1]{list}[0]{recurrenceId});
    $self->assert_str_equals('Europe/London',
        $res->[1][1]{list}[0]{recurrenceIdTimeZone});
    $self->assert_str_not_equals($state, $res->[0][1]{newState});
    $self->assert_str_not_equals($state, $res->[1][1]{state});
    $self->assert_str_not_equals($state, $res->[2][1]{newState});
    $self->assert_deep_equals([$instance1Id], $res->[2][1]{created});
    $self->assert_deep_equals([], $res->[2][1]{updated});
    $self->assert_deep_equals([], $res->[2][1]{destroyed});
    $state = $res->[2][1]{newState};

    xlog "Can't create a new standalone instance with same recurrence id";
    $res = $jmap->CallMethods([
        ['CalendarEvent/set', {
            create => {
                instance2 => {
                    calendarIds => {
                        'Default' => JSON::true,
                    },
                    '@type' => 'Event',
                    uid => 'event1uid',
                    title => 'instance2',
                    start => '2021-02-02T22:22:22',
                    timeZone => 'Europe/Berlin',
                    duration => 'PT1H',
                    recurrenceId => '2021-01-01T01:01:01',
                    recurrenceIdTimeZone => 'Europe/London',
                },
            },
        }, 'R1'],
        ['CalendarEvent/changes', {
            sinceState => $state,
        }, 'R2'],
    ]);
    $self->assert_str_equals('invalidProperties',
        $res->[0][1]{notCreated}{instance2}{type});
    $self->assert_deep_equals(['uid', 'recurrenceId'],
        $res->[0][1]{notCreated}{instance2}{properties});

    $self->assert_str_equals($state, $res->[0][1]{newState});
    $self->assert_str_equals($state, $res->[1][1]{newState});
    $self->assert_deep_equals([], $res->[1][1]{created});
    $self->assert_deep_equals([], $res->[1][1]{updated});
    $self->assert_deep_equals([], $res->[1][1]{destroyed});

    xlog "Create standalone instance with same uid but different recurrence id";
    $res = $jmap->CallMethods([
        ['CalendarEvent/set', {
            create => {
                instance2 => {
                    calendarIds => {
                        'Default' => JSON::true,
                    },
                    '@type' => 'Event',
                    uid => 'event1uid',
                    title => 'instance2',
                    start => '2021-02-02T02:02:02',
                    timeZone => 'Europe/Berlin',
                    duration => 'PT1H',
                    recurrenceId => '2021-02-02T02:02:02',
                    recurrenceIdTimeZone => 'Europe/London',
                },
            },
        }, 'R1'],
        ['CalendarEvent/get', {
            ids => ['#instance2'],
            properties => ['start', 'timeZone', 'recurrenceId', 'recurrenceIdTimeZone'],
        }, 'R2'],
        ['CalendarEvent/changes', {
            sinceState => $state,
        }, 'R3'],
    ]);
    my $instance2Id = $res->[0][1]{created}{instance2}{id};
    $self->assert_not_null($instance2Id);
    my $xhref2 = $res->[0][1]{created}{instance2}{'x-href'};
    $self->assert_not_null($xhref2);
    $self->assert_str_equals('2021-02-02T02:02:02',
        $res->[1][1]{list}[0]{start});
    $self->assert_str_equals('Europe/Berlin',
        $res->[1][1]{list}[0]{timeZone});
    $self->assert_str_equals('2021-02-02T02:02:02',
        $res->[1][1]{list}[0]{recurrenceId});
    $self->assert_str_equals('Europe/London',
        $res->[1][1]{list}[0]{recurrenceIdTimeZone});

    $self->assert_str_not_equals($state, $res->[0][1]{newState});
    $self->assert_str_not_equals($state, $res->[1][1]{state});
    $self->assert_str_not_equals($state, $res->[2][1]{newState});
    $self->assert_deep_equals([$instance2Id], $res->[2][1]{created});
    $self->assert_deep_equals([], $res->[2][1]{updated});
    $self->assert_deep_equals([], $res->[2][1]{destroyed});
    $state = $res->[2][1]{newState};

    xlog "Assert both events exist";
    $res = $jmap->CallMethods([
        ['CalendarEvent/get', {
            ids => [$instance1Id, $instance2Id],
            properties => ['title', 'recurrenceId', 'recurrenceIdTimeZone'],
        }, 'R1'],
    ]);
    $self->assert_num_equals(2, scalar @{$res->[0][1]{list}});
    $self->assert_num_equals(0, scalar @{$res->[0][1]{notFound}});

    xlog "Assert CalDAV resource contains both instances";
    $res = $caldav->Request('GET', $xhref1);
    $self->assert($res->{content} =~ m/SUMMARY:instance1/);
    $self->assert($res->{content} =~ m/SUMMARY:instance2/);
}
