#!perl
use Cassandane::Tiny;

sub test_cardgroup_set_update
    :min_version_3_9
    ($self)
{
    my $jmap = $self->{jmap};

    my $service = $self->{instance}->get_service("http");
    $ENV{DEBUGDAV} = 1;
    my $carddav = Net::CardDAVTalk->new(
        user => 'cassandane',
        password => 'pass',
        host => $service->host(),
        port => $service->port(),
        scheme => 'http',
        url => '/',
        expandurl => 1,
    );

    my $res = $jmap->CallMethods([
        ['ContactCard/set', {
            create => {
                "1" => {
                    '@type' => 'Card',
                    version => '1.0',
                    name => { full => 'John Doe' },
                },
                "2" => {
                    '@type' => 'Card',
                    version => '1.0',
                    name => { full => 'Jane Doe' },
                }
            }
        }, 'R1']
    ]);

    my $id1 = $res->[0][1]{created}{1}{id};
    my $uid1 = $res->[0][1]{created}{1}{uid};
    $self->assert_not_null($uid1);
    my $uid2 = $res->[0][1]{created}{2}{uid};
    $self->assert_not_null($uid2);

    my $name = 'The Doe Family';

    $res = $jmap->CallMethods([
        ['ContactCard/set', {
            create => {
                "1" => {
                    '@type' => 'Card',
                    version => '1.0',
                    kind => 'group',
                    name => { full => $name },
                    members => {
                        $uid1 => JSON::true
                    }
                }
            }
        }, 'R1']
    ]);

    my $id = $res->[0][1]{created}{1}{id};
    my $guid = $res->[0][1]{created}{1}{uid};
    $self->assert_not_null($id);

    # make sure that the group and member hrefs are different
    $res = $jmap->CallMethods([[ "ContactCard/get" => {
        ids => [ $id1 ], properties => [ 'cyrusimap.org:href' ] }, 'thecard' ]]);
    my $href1 = $res->[0][1]{list}[0]{'cyrusimap.org:href'};

    $res = $jmap->CallMethods([[ "ContactCard/get" => {
        ids => [ $id ], properties => [ 'cyrusimap.org:href' ] }, 'thegroup' ]]);
    $self->assert_not_equals($href1,
                             $res->[0][1]{list}[0]{'cyrusimap.org:href'});

    my $href = "Default/$guid.vcf";

    $res = $carddav->Request('GET', $href, '',
                             'Accept' => 'text/vcard; version=4.0');

    my $card = $res->{content};
    $card =~ s/\r?\n[ \t]+//gs;  # unfold long properties

    $self->assert_matches(qr/MEMBER:$uid1/, $card);

    $res = $jmap->CallMethods([
        ['ContactCard/set', {
            update => {
                $id => {
                    "members/$uid2" => JSON::true
                }
            }
         }, "R2"]
    ]);

    $self->assert_not_null($res->[0][1]{updated}{$id});

    $res = $carddav->Request('GET', $href, '',
                             'Accept' => 'text/vcard; version=4.0');

    $card = $res->{content};
    $card =~ s/\r?\n[ \t]+//gs;  # unfold long properties

    $self->assert_matches(qr/MEMBER:$uid2/, $card);
    $self->assert_matches(qr/MEMBER:$uid1/, $card);

    $res = $jmap->CallMethods([
        ['ContactCard/set', {
            update => {
                $id => {
                    "members/$uid1" => JSON::null
                }
            }
         }, "R2"]
    ]);

    $self->assert_not_null($res->[0][1]{updated}{$id});

    $res = $carddav->Request('GET', $href, '',
                             'Accept' => 'text/vcard; version=4.0');

    $card = $res->{content};
    $card =~ s/\r?\n[ \t]+//gs;  # unfold long properties

    $self->assert_matches(qr/MEMBER:$uid2/, $card);
    $self->assert_does_not_match(qr/MEMBER:$uid1/, $card);

    $res = $jmap->CallMethods([
        ['ContactCard/set', {
            update => {
                $id => {
                    kind => 'individual'
                }
            }
         }, "R2"]
    ]);

    $self->assert_not_null($res->[0][1]{notUpdated}{$id});
    $self->assert_str_equals("invalidProperties",
                             $res->[0][1]{notUpdated}{$id}{type});
    $self->assert_str_equals("kind",
                             $res->[0][1]{notUpdated}{$id}{properties}[0]);
}
