#!perl
use Cassandane::Tiny;

sub test_addressbook_set_sharewith
    :min_version_3_9 :needs_component_jmap :needs_dependency_icalvcard
{
    my ($self) = @_;

    my $jmap = $self->{jmap};
    my $admintalk = $self->{adminstore}->get_client();

    my $service = $self->{instance}->get_service("http");

    xlog $self, "create shared account";
    $admintalk->create("user.master");

    my $mastalk = Net::CardDAVTalk->new(
        user => "master",
        password => 'pass',
        host => $service->host(),
        port => $service->port(),
        scheme => 'http',
        url => '/',
        expandurl => 1,
    );

    $admintalk->setacl("user.master", admin => 'lrswipkxtecdan');
    $admintalk->setacl("user.master", master => 'lrswipkxtecdn');

    xlog $self, "create addressbook";
    my $AddressBookId = $mastalk->NewAddressBook('Shared', name => 'Shared AddressBook');
    $self->assert_not_null($AddressBookId);

    xlog $self, "share to user with permission to share";
    $admintalk->setacl("user.master.#addressbooks.$AddressBookId", "cassandane" => 'lrswipkxtecdan') or die;

    xlog $self, "create third account";
    $admintalk->create("user.manifold");

    $admintalk->setacl("user.manifold", admin => 'lrswipkxtecdan');
    $admintalk->setacl("user.manifold", manifold => 'lrswipkxtecdn');

    xlog $self, "and a forth";
    $admintalk->create("user.paraphrase");

    $admintalk->setacl("user.paraphrase", admin => 'lrswipkxtecdan');
    $admintalk->setacl("user.paraphrase", paraphrase => 'lrswipkxtecdn');

    # Call CardDAV once to create manifold's addressbook home #addressbooks
    my $mantalk = Net::CardDAVTalk->new(
        user => "manifold",
        password => 'pass',
        host => $service->host(),
        port => $service->port(),
        scheme => 'http',
        url => '/',
        expandurl => 1,
    );

    # Call CardDAV once to create paraphrase's addressbook home #addressbooks
    my $partalk = Net::CardDAVTalk->new(
        user => "paraphrase",
        password => 'pass',
        host => $service->host(),
        port => $service->port(),
        scheme => 'http',
        url => '/',
        expandurl => 1,
    );

    xlog $self, "sharee gives third user access to shared addressbook";
    $res = $jmap->CallMethods([
            ['AddressBook/set', {
                    accountId => 'master',
                    update => { "$AddressBookId" => {
                            "shareWith/manifold" => {
                                mayRead => JSON::true
                            },
                            "shareWith/paraphrase" => {
                                mayRead => JSON::true,
                                mayWrite => JSON::true,
                            },
             }}}, "R1"]
    ]);
    $self->assert_not_null($res);
    $self->assert_str_equals('AddressBook/set', $res->[0][0]);
    $self->assert_str_equals('R1', $res->[0][2]);
    $self->assert_not_null($res->[0][1]{newState});
    $self->assert_not_null($res->[0][1]{updated});

    xlog $self, "check ACL on JMAP upload folder";
    $acl = $admintalk->getacl("user.master.#jmap");
    %map = @$acl;
    $self->assert_str_equals('lrswitedn', $map{cassandane});
    $self->assert_str_equals('lrw', $map{manifold});
    $self->assert_str_equals('lrswitedn', $map{paraphrase});

    xlog $self, "Update sharewith just for manifold";
    $jmap->CallMethods([
            ['AddressBook/set', {
                    accountId => 'master',
                    update => { "$AddressBookId" => {
                            "shareWith/manifold/mayWrite" => JSON::true,
             }}}, "R1"]
    ]);

    xlog $self, "check ACL on JMAP upload folder";
    $acl = $admintalk->getacl("user.master.#jmap");
    %map = @$acl;
    $self->assert_str_equals('lrswitedn', $map{cassandane});
    $self->assert_str_equals('lrswitedn', $map{manifold});
    $self->assert_str_equals('lrswitedn', $map{paraphrase});

    xlog $self, "Remove the access for paraphrase";
    $res = $jmap->CallMethods([
            ['AddressBook/set', {
                    accountId => 'master',
                    update => { "$AddressBookId" => {
                            "shareWith/paraphrase" => undef,
             }}}, "R1"]
    ]);

    $self->assert_not_null($res);
    $self->assert_str_equals('AddressBook/set', $res->[0][0]);
    $self->assert_str_equals('R1', $res->[0][2]);
    $self->assert_not_null($res->[0][1]{newState});
    $self->assert_not_null($res->[0][1]{updated});

    xlog $self, "check ACL";
    $acl = $admintalk->getacl("user.master.#addressbooks.$AddressBookId");
    %map = @$acl;
    $self->assert_str_equals('lrswipkxtecdan', $map{cassandane});
    $self->assert_str_equals('lrswitedn', $map{manifold});
    $self->assert_null($map{paraphrase});

    xlog $self, "check ACL on JMAP upload folder";
    $acl = $admintalk->getacl("user.master.#jmap");
    %map = @$acl;
    $self->assert_str_equals('lrswitedn', $map{cassandane});
    $self->assert_str_equals('lrswitedn', $map{manifold});
    $self->assert_null($map{paraphrase});
}
