#!perl
use Cassandane::Tiny;

sub test_contact_query
    :min_version_3_1
{
    my ($self) = @_;

    my $jmap = $self->{jmap};

    xlog $self, "create contacts";
    my $res = $jmap->CallMethods([['Contact/set', {create => {
                        "1" =>
                        {
                            firstName => "foo", lastName => "last",
                            emails => [{
                                    type => "personal",
                                    value => "foo\@example.com"
                                }]
                        },
                        "2" =>
                        {
                            firstName => "bar", lastName => "last",
                            emails => [{
                                    type => "work",
                                    value => "bar\@bar.org"
                                }, {
                                    type => "other",
                                    value => "me\@example.com"
                                }],
                            addresses => [{
                                    type => "home",
                                   label => undef,
                                    street => "Some Lane 24",
                                    locality => "SomeWhere City",
                                    region => "",
                                    postcode => "1234",
                                    country => "Someinistan",
                                    isDefault => JSON::false
                                }],
                            isFlagged => JSON::true
                        },
                        "3" =>
                        {
                            firstName => "baz", lastName => "last",
                            addresses => [{
                                    type => "home",
                                    label => undef,
                                    street => "Some Lane 12",
                                    locality => "SomeWhere City",
                                    region => "",
                                    postcode => "1234",
                                    country => "Someinistan",
                                    isDefault => JSON::false
                                }]
                        },
                        "4" => {firstName => "bam", lastName => "last",
                                 isFlagged => JSON::false }
                    }}, "R1"]]);

    $self->assert_not_null($res);
    $self->assert_str_equals('Contact/set', $res->[0][0]);
    $self->assert_str_equals('R1', $res->[0][2]);
    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};

    xlog $self, "create contact groups";
    $res = $jmap->CallMethods([['ContactGroup/set', {create => {
                        "1" => {name => "group1", contactIds => [$id1, $id2]},
                        "2" => {name => "group2", contactIds => [$id3]},
                        "3" => {name => "group3", contactIds => [$id4]}
                    }}, "R1"]]);

    $self->assert_not_null($res);
    $self->assert_str_equals('ContactGroup/set', $res->[0][0]);
    $self->assert_str_equals('R1', $res->[0][2]);
    my $group1 = $res->[0][1]{created}{"1"}{id};
    my $group2 = $res->[0][1]{created}{"2"}{id};
    my $group3 = $res->[0][1]{created}{"3"}{id};

    xlog $self, "get unfiltered contact list";
    $res = $jmap->CallMethods([ ['Contact/query', { }, "R1"] ]);

    $self->assert_num_equals(4, $res->[0][1]{total});
    $self->assert_num_equals(4, scalar @{$res->[0][1]{ids}});

    xlog $self, "filter by firstName";
    $res = $jmap->CallMethods([ ['Contact/query', {
                    filter => { firstName => "foo" }
                }, "R1"] ]);
    $self->assert_num_equals(1, $res->[0][1]{total});
    $self->assert_num_equals(1, scalar @{$res->[0][1]{ids}});
    $self->assert_str_equals($id1, $res->[0][1]{ids}[0]);

    xlog $self, "filter by lastName";
    $res = $jmap->CallMethods([ ['Contact/query', {
                    filter => { lastName => "last" }
                }, "R1"] ]);
    $self->assert_num_equals(4, $res->[0][1]{total});
    $self->assert_num_equals(4, scalar @{$res->[0][1]{ids}});

    xlog $self, "filter by firstName and lastName (one filter)";
    $res = $jmap->CallMethods([ ['Contact/query', {
                    filter => { firstName => "bam", lastName => "last" }
                }, "R1"] ]);
    $self->assert_num_equals(1, $res->[0][1]{total});
    $self->assert_num_equals(1, scalar @{$res->[0][1]{ids}});
    $self->assert_str_equals($id4, $res->[0][1]{ids}[0]);

    xlog $self, "filter by firstName and lastName (AND filter)";
    $res = $jmap->CallMethods([ ['Contact/query', {
                    filter => { operator => "AND", conditions => [{
                                lastName => "last"
                            }, {
                                firstName => "baz"
                    }]}
                }, "R1"] ]);
    $self->assert_num_equals(1, $res->[0][1]{total});
    $self->assert_num_equals(1, scalar @{$res->[0][1]{ids}});
    $self->assert_str_equals($id3, $res->[0][1]{ids}[0]);

    xlog $self, "filter by firstName (OR filter)";
    $res = $jmap->CallMethods([ ['Contact/query', {
                    filter => { operator => "OR", conditions => [{
                                firstName => "bar"
                            }, {
                                firstName => "baz"
                    }]}
                }, "R1"] ]);
    $self->assert_num_equals(2, $res->[0][1]{total});
    $self->assert_num_equals(2, scalar @{$res->[0][1]{ids}});

    xlog $self, "filter by text";
    $res = $jmap->CallMethods([ ['Contact/query', {
                    filter => { text => "some" }
                }, "R1"] ]);
    $self->assert_num_equals(2, $res->[0][1]{total});
    $self->assert_num_equals(2, scalar @{$res->[0][1]{ids}});

    xlog $self, "filter by email";
    $res = $jmap->CallMethods([ ['Contact/query', {
                    filter => { email => "example.com" }
                }, "R1"] ]);
    $self->assert_num_equals(2, $res->[0][1]{total});
    $self->assert_num_equals(2, scalar @{$res->[0][1]{ids}});

    xlog $self, "filter by isFlagged (true)";
    $res = $jmap->CallMethods([ ['Contact/query', {
                    filter => { isFlagged => JSON::true }
                }, "R1"] ]);
    $self->assert_num_equals(1, scalar @{$res->[0][1]{ids}});
    $self->assert_str_equals($id2, $res->[0][1]{ids}[0]);

    xlog $self, "filter by isFlagged (false)";
    $res = $jmap->CallMethods([ ['Contact/query', {
                    filter => { isFlagged => JSON::false }
                }, "R1"] ]);
    $self->assert_num_equals(3, scalar @{$res->[0][1]{ids}});

    xlog $self, "filter by inContactGroup";
    $res = $jmap->CallMethods([ ['Contact/query', {
                    filter => { inContactGroup => [$group1, $group3] }
                }, "R1"] ]);
    $self->assert_num_equals(3, scalar @{$res->[0][1]{ids}});

    xlog $self, "filter by inContactGroup and firstName";
    $res = $jmap->CallMethods([ ['Contact/query', {
                    filter => { inContactGroup => [$group1, $group3], firstName => "foo" }
                }, "R1"] ]);
    $self->assert_num_equals(1, scalar @{$res->[0][1]{ids}});
    $self->assert_str_equals($id1, $res->[0][1]{ids}[0]);
}
