#!perl
use Cassandane::Tiny;

sub test_email_query_snooze
    :min_version_3_1 :needs_component_jmap :needs_component_calalarmd
    :needs_component_sieve :JMAPExtensions
{
    my ($self) = @_;
    my $jmap = $self->{jmap};

    # we need 'https://cyrusimap.org/ns/jmap/mail' capability for
    # snoozed property
    my @using = @{ $jmap->DefaultUsing() };
    push @using, 'https://cyrusimap.org/ns/jmap/mail';
    $jmap->DefaultUsing(\@using);

    xlog $self, "Get mailbox id of Inbox";
    my $res = $jmap->CallMethods([['Mailbox/query',
                                   {filter => {role => 'inbox'}}, "R1"]]);
    my $inbox = $res->[0][1]->{ids}[0];

    xlog $self, "create snooze mailbox";
    $res = $jmap->CallMethods([
            ['Mailbox/set', { create => { "1" => {
                            name => "snoozed",
                            parentId => undef,
                            role => "snoozed"
             }}}, "R1"]
    ]);
    $self->assert_str_equals('Mailbox/set', $res->[0][0]);
    $self->assert_str_equals('R1', $res->[0][2]);
    $self->assert_not_null($res->[0][1]{created});
    my $snoozedmbox = $res->[0][1]{created}{"1"}{id};

    my $maildate = DateTime->now();
    $maildate->add(DateTime::Duration->new(seconds => 30));
    my $datestr1 = $maildate->strftime('%Y-%m-%dT%TZ');

    my $draft1 =  {
        mailboxIds => { $snoozedmbox => JSON::true },
        from => [ { name => "Yosemite Sam", email => "sam\@acme.local" } ] ,
        to => [ { name => "Bugs Bunny", email => "bugs\@acme.local" }, ],
        subject => "Memo1",
        snoozed => { "until" => "$datestr1" },
    };

    $maildate->add(DateTime::Duration->new(seconds => -15));
    my $datestr2 = $maildate->strftime('%Y-%m-%dT%TZ');

    my $draft2 =  {
        mailboxIds => { $snoozedmbox => JSON::true },
        from => [ { name => "Yosemite Sam", email => "sam\@acme.local" } ] ,
        to => [ { name => "Bugs Bunny", email => "bugs\@acme.local" }, ],
        subject => "Memo2",
        snoozed => { "until" => "$datestr2" },
    };

    $maildate->add(DateTime::Duration->new(seconds => 30));
    my $datestr3 = $maildate->strftime('%Y-%m-%dT%TZ');

    my $draft3 =  {
        mailboxIds => { $snoozedmbox => JSON::true },
        from => [ { name => "Yosemite Sam", email => "sam\@acme.local" } ] ,
        to => [ { name => "Bugs Bunny", email => "bugs\@acme.local" }, ],
        subject => "Memo3",
        snoozed => { "until" => "$datestr3" },
    };

    $maildate->add(DateTime::Duration->new(seconds => -1));
    my $datestr4 = $maildate->strftime('%Y-%m-%dT%TZ');

    my $draft4 =  {
        mailboxIds => { $snoozedmbox => JSON::true },
        from => [ { name => "Yosemite Sam", email => "sam\@acme.local" } ] ,
        to => [ { name => "Bugs Bunny", email => "bugs\@acme.local" }, ],
        subject => "Memo4",
        snoozed => { "until" => "$datestr4" },
    };

    $maildate->add(DateTime::Duration->new(seconds => 10));
    my $datestr5 = $maildate->strftime('%Y-%m-%dT%TZ');

    my $draft5 =  {
        mailboxIds => { $inbox => JSON::true },
        from => [ { name => "Yosemite Sam", email => "sam\@acme.local" } ] ,
        to => [ { name => "Bugs Bunny", email => "bugs\@acme.local" }, ],
        subject => "Memo5",
        receivedAt => "$datestr5",
    };

    $maildate->add(DateTime::Duration->new(seconds => -5));
    my $datestr6 = $maildate->strftime('%Y-%m-%dT%TZ');

    my $draft6 =  {
        mailboxIds => { $inbox => JSON::true },
        from => [ { name => "Yosemite Sam", email => "sam\@acme.local" } ] ,
        to => [ { name => "Bugs Bunny", email => "bugs\@acme.local" }, ],
        subject => "Memo6",
        receivedAt => "$datestr6",
    };

    xlog $self, "Create 6 drafts";
    $res = $jmap->CallMethods([['Email/set',
                                { create =>
                                  { "1" => $draft1,
                                    "2" => $draft2,
                                    "3" => $draft3,
                                    "4" => $draft4,
                                    "5" => $draft5,
                                    "6" => $draft6 }}, "R1"]]);
    my $id1 = $res->[0][1]{created}{"1"}{id};
    my $id2 = $res->[0][1]{created}{"2"}{id};
    my $id3 = $res->[0][1]{created}{"3"}{id};
    my $id4 = $res->[0][1]{created}{"4"}{id};
    my $id5 = $res->[0][1]{created}{"5"}{id};
    my $id6 = $res->[0][1]{created}{"6"}{id};

    xlog $self, "sort by ascending snoozedUntil";
    $res = $jmap->CallMethods([['Email/query', {
                    sort => [{ property => "snoozedUntil",
                               mailboxId => "$snoozedmbox" }],
                }, "R1"]]);
    $self->assert_num_equals(6, scalar @{$res->[0][1]->{ids}});
    $self->assert_str_equals($id2, $res->[0][1]->{ids}[0]);
    $self->assert_str_equals($id1, $res->[0][1]->{ids}[1]);
    $self->assert_str_equals($id4, $res->[0][1]->{ids}[2]);
    $self->assert_str_equals($id3, $res->[0][1]->{ids}[3]);
    $self->assert_str_equals($id6, $res->[0][1]->{ids}[4]);
    $self->assert_str_equals($id5, $res->[0][1]->{ids}[5]);

    xlog $self, "sort by descending snoozedUntil";
    $res = $jmap->CallMethods([['Email/query', {
                    sort => [{ property => "snoozedUntil",
                               mailboxId => "$snoozedmbox",
                               isAscending => JSON::false }],
                }, "R1"]]);
    $self->assert_num_equals(6, scalar @{$res->[0][1]->{ids}});
    $self->assert_str_equals($id5, $res->[0][1]->{ids}[0]);
    $self->assert_str_equals($id6, $res->[0][1]->{ids}[1]);
    $self->assert_str_equals($id3, $res->[0][1]->{ids}[2]);
    $self->assert_str_equals($id4, $res->[0][1]->{ids}[3]);
    $self->assert_str_equals($id1, $res->[0][1]->{ids}[4]);
    $self->assert_str_equals($id2, $res->[0][1]->{ids}[5]);
}
