#!perl
use Cassandane::Tiny;

sub test_mailbox_querychanges_role
    :min_version_3_1
{
    my ($self) = @_;
    my $jmap = $self->{jmap};
    my $inboxId = $self->getinbox()->{id};

    my $res = $jmap->CallMethods([['Mailbox/set', {
        create => {
            1 => {
                parentId => $inboxId,
                name => 'A',
            },
            2 => {
                parentId => $inboxId,
                name => 'B',
                role => 'xspecialuse',
            },
            3 => {
                parentId => $inboxId,
                name => 'C',
                role => 'junk',
            },
        },
    }, "R1"]]);
    my $mboxId1 = $res->[0][1]{created}{1}{id};
    my $mboxId2 = $res->[0][1]{created}{2}{id};
    my $mboxId3 = $res->[0][1]{created}{3}{id};
    $self->assert_not_null($mboxId1);
    $self->assert_not_null($mboxId2);
    $self->assert_not_null($mboxId3);

    my $filter = { hasAnyRole => JSON::true, };
    my $sort = [{ property => "name" }];

    $res = $jmap->CallMethods([['Mailbox/query', {
        filter => $filter, sort => $sort,
    }, "R1"]]);
    my $state = $res->[0][1]->{queryState};
    $self->assert_not_null($state);
    $self->assert_equals(JSON::true, $res->[0][1]->{canCalculateChanges});

    $res = $jmap->CallMethods([['Mailbox/queryChanges', {
        sinceQueryState => $state,
        filter => $filter, sort => $sort,
    }, "R1"]]);
    $self->assert_str_equals($state, $res->[0][1]->{newQueryState});

    # Remove mailbox 2 from results and add mailbox 1
    $res = $jmap->CallMethods([['Mailbox/set', {
        update => {
            $mboxId1 => {
                role => 'trash',
            },
            $mboxId2 => {
                role => undef,
            },
        },
    }, "R1"]]);
    $self->assert(exists $res->[0][1]{updated}{$mboxId1});
    $self->assert(exists $res->[0][1]{updated}{$mboxId2});

    $res = $jmap->CallMethods([['Mailbox/queryChanges', {
        sinceQueryState => $state,
        filter => $filter, sort => $sort,
    }, "R1"]]);

    $self->assert_str_not_equals($state, $res->[0][1]->{newQueryState});
    $self->assert_num_equals(2, scalar @{$res->[0][1]{removed}});
    my %removed = map { $_ => 1 } @{$res->[0][1]{removed}};
    $self->assert(exists $removed{$mboxId1});
    $self->assert(exists $removed{$mboxId2});

    $self->assert_num_equals(1, scalar @{$res->[0][1]{added}});
    $self->assert_str_equals($mboxId1, $res->[0][1]{added}[0]{id});
    $self->assert_num_equals(0, $res->[0][1]{added}[0]{index});
}
