<?php

use Mockery as m;

use EasyRdf\Resource;
use EasyRdf\Literal;

/**
 *
 */
class ThemeControllerTest extends TestCase {

    public function setUp() {

        parent::setup();

    }

    public function tearDown() {
        m::close();
        parent::tearDown();
    }

    public function testIndex() {

        $query = [
            'index' => env('ELASTICSEARCH_INDEX'),
            'body' => [
                'size' => 0,
                'query' =>[
                    'match_all' => (object) null
                ],
                'aggs' => [
                    "subjects" => [
                        "nested" => [ "path" => "subject" ],
                        "aggs" => [
                            "subjects" => [
                                "terms" => [
                                    "field" => "subject.label_code",
                                    "size" => config('corpusparole.theme_default_limit'),
                                    "order" => [ '_count' => 'desc' ],
                                    "include" => ".*\|bnf\|.*"
                                ]
                            ],
                            "subjects_count" => [
                                "cardinality" => [
                                    "field" => "subject.label_code"
                                ]
                            ]
                        ]
                    ]
                ]
            ]
        ];

        Es::shouldReceive('search')
            ->once()
            ->with($query)
            ->andReturn([
                "took" => 27,
                "timed_out" => false,
                "_shards" => [
                    "total" => 1,
                    "successful" => 1,
                    "failed" => 0
                ],
                "hits" => [
                    "total" => 3011,
                    "max_score" => 0.0,
                    "hits" => [ ]
                ],
                "aggregations" => [
                    "subjects" => [
                        "doc_count" => 41524,
                        "subjects" => [
                            "doc_count_error_upper_bound" => 0,
                            "sum_other_doc_count" => 13678,
                            "buckets" => [ [
                                "key" => "professions|bnf|ark:/12148/cb13318415c",
                                "doc_count" => 1412
                            ], [
                                "key" => "travail non rémunéré|bnf|ark:/12148/cb16604691s",
                                "doc_count" => 1092
                            ], [
                                "key" => "famille|bnf|ark:/12148/cb119339867",
                                "doc_count" => 1050
                            ], [
                                "key" => "oiseaux|bnf|ark:/12148/cb11932889r",
                                "doc_count" => 1003
                            ], [
                                "key" => "météorologie|bnf|ark:/12148/cb11932496x",
                                "doc_count" => 1001
                            ], [
                                "key" => "plantes|bnf|ark:/12148/cb11933145f",
                                "doc_count" => 995
                            ], [
                                "key" => "animaux sauvages|bnf|ark:/12148/cb11930908q",
                                "doc_count" => 989
                            ], [
                                "key" => "arbres|bnf|ark:/12148/cb11934786x",
                                "doc_count" => 989
                            ] ]
                        ],
                        "subjects_count" => [
                            "value" => 999
                        ]
                    ]
                ]
            ]);
        $response = $this->get('/api/v1/stats/themes/');
        $response
            ->assertStatus(200)
            ->assertJson(["themes" => [
            "http://ark.bnf.fr/ark:/12148/cb13318415c" => ['label' => 'professions', 'count' => 1412 ],
            "http://ark.bnf.fr/ark:/12148/cb16604691s" => ['label' => 'travail non rémunéré', 'count' => 1092 ],
            "http://ark.bnf.fr/ark:/12148/cb119339867" => ['label' => 'famille', 'count' => 1050 ],
            "http://ark.bnf.fr/ark:/12148/cb11932889r" => ['label' => 'oiseaux', 'count' => 1003 ],
            "http://ark.bnf.fr/ark:/12148/cb11932496x" => ['label' => 'météorologie', 'count' => 1001 ],
            "http://ark.bnf.fr/ark:/12148/cb11933145f" => ['label' => 'plantes', 'count' => 995  ],
            "http://ark.bnf.fr/ark:/12148/cb11930908q" => ['label' => 'animaux sauvages', 'count' => 989 ],
            "http://ark.bnf.fr/ark:/12148/cb11934786x" => ['label' => 'arbres', 'count' => 989 ]
        ], "meta" => ['total' => 999]]);

    }

    public function testIndexAll() {

        $query = [
            'index' => env('ELASTICSEARCH_INDEX'),
            'body' => [
                'size' => 0,
                'query' =>[
                    'match_all' => (object) null
                ],
                'aggs' => [
                    "subjects" => [
                        "nested" => [ "path" => "subject" ],
                        "aggs" => [
                            "subjects" => [
                                "terms" => [
                                    "field" => "subject.label_code",
                                    "size" => config('corpusparole.theme_default_limit'),
                                    "order" => [ '_count' => 'desc' ]
                                ]
                            ],
                            "subjects_count" => [
                                "cardinality" => [
                                    "field" => "subject.label_code"
                                ]
                            ]
                        ]
                    ]
                ]
            ]
        ];

        Es::shouldReceive('search')
            ->once()
            ->with($query)
            ->andReturn([
                "took" => 27,
                "timed_out" => false,
                "_shards" => [
                    "total" => 1,
                    "successful" => 1,
                    "failed" => 0
                ],
                "hits" => [
                    "total" => 3011,
                    "max_score" => 0.0,
                    "hits" => [ ]
                ],
                "aggregations" => [
                    "subjects" => [
                        "doc_count" => 41524,
                        "subjects" => [
                            "doc_count_error_upper_bound" => 0,
                            "sum_other_doc_count" => 13678,
                            "buckets" => [ [
                                "key" => "professions|bnf|ark:/12148/cb13318415c",
                                "doc_count" => 1412
                            ], [
                                "key" => "travail non rémunéré|bnf|ark:/12148/cb16604691s",
                                "doc_count" => 1092
                            ], [
                                "key" => "famille|bnf|ark:/12148/cb119339867",
                                "doc_count" => 1050
                            ], [
                                "key" => "oiseaux|bnf|ark:/12148/cb11932889r",
                                "doc_count" => 1003
                            ], [
                                "key" => "Français|lxv|fra",
                                "doc_count" => 1002
                            ], [
                                "key" => "météorologie|bnf|ark:/12148/cb11932496x",
                                "doc_count" => 1001
                            ], [
                                "key" => "plantes|bnf|ark:/12148/cb11933145f",
                                "doc_count" => 995
                            ], [
                                "key" => "Breton|lxv|bzh",
                                "doc_count" => 992
                            ], [
                                "key" => "animaux sauvages|bnf|ark:/12148/cb11930908q",
                                "doc_count" => 989
                            ], [
                                "key" => "arbres|bnf|ark:/12148/cb11934786x",
                                "doc_count" => 989
                            ] ]
                        ],
                        "subjects_count" => [
                            "value" => 999
                        ]
                    ]
                ]
            ]);
        $response = $this->get('/api/v1/stats/themes/?filter=all');
        $response
            ->assertStatus(200)
            ->assertJson(["themes" => [
            "http://ark.bnf.fr/ark:/12148/cb13318415c" => ['label' => 'professions', 'count' => 1412 ],
            "http://ark.bnf.fr/ark:/12148/cb16604691s" => ['label' => 'travail non rémunéré', 'count' => 1092 ],
            "http://ark.bnf.fr/ark:/12148/cb119339867" => ['label' => 'famille', 'count' => 1050 ],
            "http://ark.bnf.fr/ark:/12148/cb11932889r" => ['label' => 'oiseaux', 'count' => 1003 ],
            "http://lexvo.org/id/iso639-3/fra" => ['label' => 'Français', 'count' => 1002 ],
            "http://ark.bnf.fr/ark:/12148/cb11932496x" => ['label' => 'météorologie', 'count' => 1001 ],
            "http://ark.bnf.fr/ark:/12148/cb11933145f" => ['label' => 'plantes', 'count' => 995  ],
            "http://lexvo.org/id/iso639-3/bzh" => ['label' => 'Breton', 'count' => 992 ],
            "http://ark.bnf.fr/ark:/12148/cb11930908q" => ['label' => 'animaux sauvages', 'count' => 989 ],
            "http://ark.bnf.fr/ark:/12148/cb11934786x" => ['label' => 'arbres', 'count' => 989 ]
        ], "meta" => ['total' => 999]]);

    }

    public function testIndexLexvo() {

        $query = [
            'index' => env('ELASTICSEARCH_INDEX'),
            'body' => [
                'size' => 0,
                'query' =>[
                    'match_all' => (object) null
                ],
                'aggs' => [
                    "subjects" => [
                        "nested" => [ "path" => "subject" ],
                        "aggs" => [
                            "subjects" => [
                                "terms" => [
                                    "field" => "subject.label_code",
                                    "size" => config('corpusparole.theme_default_limit'),
                                    "order" => [ '_count' => 'desc' ],
                                    "include" => ".*\|lxv\|.*"
                                ]
                            ],
                            "subjects_count" => [
                                "cardinality" => [
                                    "field" => "subject.label_code"
                                ]
                            ]
                        ]
                    ]
                ]
            ]
        ];

        Es::shouldReceive('search')
            ->once()
            ->with($query)
            ->andReturn([
                "took" => 27,
                "timed_out" => false,
                "_shards" => [
                    "total" => 1,
                    "successful" => 1,
                    "failed" => 0
                ],
                "hits" => [
                    "total" => 3011,
                    "max_score" => 0.0,
                    "hits" => [ ]
                ],
                "aggregations" => [
                    "subjects" => [
                        "doc_count" => 41524,
                        "subjects" => [
                            "doc_count_error_upper_bound" => 0,
                            "sum_other_doc_count" => 13678,
                            "buckets" => [ [
                                "key" => "Français|lxv|fra",
                                "doc_count" => 1002
                            ], [
                                "key" => "Breton|lxv|bzh",
                                "doc_count" => 992
                            ] ]
                        ],
                        "subjects_count" => [
                            "value" => 999
                        ]
                    ]
                ]
            ]);
        $response = $this->get('/api/v1/stats/themes/?filter=lexvo');
        $response
            ->assertStatus(200)
            ->assertJson(["themes" => [
            "http://lexvo.org/id/iso639-3/fra" => ['label' => 'Français', 'count' => 1002 ],
            "http://lexvo.org/id/iso639-3/bzh" => ['label' => 'Breton', 'count' => 992 ]
        ], "meta" => ['total' => 999]]);

    }

    private function getOrderQuery($order) {
        return [
            'index' => env('ELASTICSEARCH_INDEX'),
            'body' => [
                'size' => 0,
                'query' =>[
                    'match_all' => (object) null
                ],
                'aggs' => [
                    "subjects" => [
                        "nested" => [ "path" => "subject" ],
                        "aggs" => [
                            "subjects" => [
                                "terms" => [
                                    "field" => "subject.label_code",
                                    "size" => config('corpusparole.theme_default_limit'),
                                    "order" => $order,
                                    "include" => ".*\|bnf\|.*"
                                ]
                            ],
                            "subjects_count" => [
                                "cardinality" => [
                                    "field" => "subject.label_code"
                                ]
                            ]
                        ]
                    ]
                ]
            ]
        ];

    }

    private function getRespSort() {
        return [
            "took" => 27,
            "timed_out" => false,
            "_shards" => [
                "total" => 1,
                "successful" => 1,
                "failed" => 0
            ],
            "hits" => [
                "total" => 3011,
                "max_score" => 0.0,
                "hits" => [ ]
            ],
            "aggregations" => [
                "subjects" => [
                    "doc_count" => 41524,
                    "subjects" => [
                        "doc_count_error_upper_bound" => 0,
                        "sum_other_doc_count" => 13678,
                        "buckets" => [  ]
                    ],
                    "subjects_count" => [
                        "value" => 999
                    ]
                ]
            ]
        ];
    }

    public function testIndexSort() {

        Es::shouldReceive('search')
            ->once()
            ->with($this->getOrderQuery(['_count' => 'desc']))
            ->andReturn($this->getRespSort());
        $this->get('/api/v1/stats/themes/')->assertStatus(200);

    }

    public function testIndexSortReverseCount() {
        Es::shouldReceive('search')
            ->once()
            ->with($this->getOrderQuery(['_count' => 'asc']))
            ->andReturn($this->getRespSort());
        $this->get('/api/v1/stats/themes/?sort=-count')->assertStatus(200);
    }

    public function testIndexSortLabel() {
        Es::shouldReceive('search')
            ->once()
            ->with($this->getOrderQuery(['_term' => 'asc']))
            ->andReturn($this->getRespSort());
        $this->get('/api/v1/stats/themes/?sort=label')->assertStatus(200);
    }

    public function testIndexSortAlphabetical() {
        Es::shouldReceive('search')
            ->once()
            ->with($this->getOrderQuery(['_term' => 'asc']))
            ->andReturn($this->getRespSort());
        $this->get('/api/v1/stats/themes/?sort=alphabetical')->assertStatus(200);
    }

    public function testIndexSortLabelReverse() {
        Es::shouldReceive('search')
            ->once()
            ->with($this->getOrderQuery(['_term' => 'desc']))
            ->andReturn($this->getRespSort());
        $this->get('/api/v1/stats/themes/?sort=-label')->assertStatus(200);
    }


    public function testIndexLimit() {

        $query = [
            'index' => env('ELASTICSEARCH_INDEX'),
            'body' => [
                'size' => 0,
                'query' =>[
                    'match_all' => (object) null
                ],
                'aggs' => [
                    "subjects" => [
                        "nested" => [ "path" => "subject" ],
                        "aggs" => [
                            "subjects" => [
                                "terms" => [
                                    "field" => "subject.label_code",
                                    "size" => 3,
                                    "order" => [ '_count' => 'desc' ],
                                    "include" => ".*\|bnf\|.*"
                                ]
                            ],
                            "subjects_count" => [
                                "cardinality" => [
                                    "field" => "subject.label_code"
                                ]
                            ]
                        ]
                    ]
                ]
            ]
        ];

        // This is not normally what should be received, but we test that the limit is respected
        Es::shouldReceive('search')
            ->once()
            ->with($query)
            ->andReturn([
                "took" => 27,
                "timed_out" => false,
                "_shards" => [
                    "total" => 1,
                    "successful" => 1,
                    "failed" => 0
                ],
                "hits" => [
                    "total" => 3011,
                    "max_score" => 0.0,
                    "hits" => [ ]
                ],
                "aggregations" => [
                    "subjects" => [
                        "doc_count" => 41524,
                        "subjects" => [
                            "doc_count_error_upper_bound" => 0,
                            "sum_other_doc_count" => 13678,
                            "buckets" => [ [
                                "key" => "professions|bnf|ark:/12148/cb13318415c",
                                "doc_count" => 1412
                            ], [
                                "key" => "travail non rémunéré|bnf|ark:/12148/cb16604691s",
                                "doc_count" => 1092
                            ], [
                                "key" => "famille|bnf|ark:/12148/cb119339867",
                                "doc_count" => 1050
                            ], [
                                "key" => "oiseaux|bnf|ark:/12148/cb11932889r",
                                "doc_count" => 1003
                            ], [
                                "key" => "météorologie|bnf|ark:/12148/cb11932496x",
                                "doc_count" => 1001
                            ], [
                                "key" => "plantes|bnf|ark:/12148/cb11933145f",
                                "doc_count" => 995
                            ], [
                                "key" => "animaux sauvages|bnf|ark:/12148/cb11930908q",
                                "doc_count" => 989
                            ], [
                                "key" => "arbres|bnf|ark:/12148/cb11934786x",
                                "doc_count" => 989
                            ] ]
                        ],
                        "subjects_count" => [
                            "value" => 999
                        ]
                    ]
                ]
            ]);
        $response = $this->get('/api/v1/stats/themes/?limit=3')->assertStatus(200);
        $response->assertJson(["themes" => [
            "http://ark.bnf.fr/ark:/12148/cb13318415c" => ['label' => 'professions', 'count' => 1412 ],
            "http://ark.bnf.fr/ark:/12148/cb16604691s" => ['label' => 'travail non rémunéré', 'count' => 1092 ],
            "http://ark.bnf.fr/ark:/12148/cb119339867" => ['label' => 'famille', 'count' => 1050 ]
        ], "meta" => ['total' => 999]]);

    }

    public function testIndexIndex() {

        $query = [
            'index' => env('ELASTICSEARCH_INDEX'),
            'body' => [
                'size' => 0,
                'query' =>[
                    'match_all' => (object) null
                ],
                'aggs' => [
                    "subjects" => [
                        "nested" => [ "path" => "subject" ],
                        "aggs" => [
                            "subjects" => [
                                "terms" => [
                                    "field" => "subject.label_code",
                                    "size" => 6,
                                    "order" => [ '_count' => 'desc' ],
                                    "include" => ".*\|bnf\|.*"
                                ]
                            ],
                            "subjects_count" => [
                                "cardinality" => [
                                    "field" => "subject.label_code"
                                ]
                            ]
                        ]
                    ]
                ]
            ]
        ];

        // This is not normally what should be received, but we test that the limit is respected
        Es::shouldReceive('search')
            ->once()
            ->with($query)
            ->andReturn([
                "took" => 27,
                "timed_out" => false,
                "_shards" => [
                    "total" => 1,
                    "successful" => 1,
                    "failed" => 0
                ],
                "hits" => [
                    "total" => 3011,
                    "max_score" => 0.0,
                    "hits" => [ ]
                ],
                "aggregations" => [
                    "subjects" => [
                        "doc_count" => 41524,
                        "subjects" => [
                            "doc_count_error_upper_bound" => 0,
                            "sum_other_doc_count" => 13678,
                            "buckets" => [ [
                                "key" => "professions|bnf|ark:/12148/cb13318415c",
                                "doc_count" => 1412
                            ], [
                                "key" => "travail non rémunéré|bnf|ark:/12148/cb16604691s",
                                "doc_count" => 1092
                            ], [
                                "key" => "famille|bnf|ark:/12148/cb119339867",
                                "doc_count" => 1050
                            ], [
                                "key" => "oiseaux|bnf|ark:/12148/cb11932889r",
                                "doc_count" => 1003
                            ], [
                                "key" => "météorologie|bnf|ark:/12148/cb11932496x",
                                "doc_count" => 1001
                            ], [
                                "key" => "plantes|bnf|ark:/12148/cb11933145f",
                                "doc_count" => 995
                            ], [
                                "key" => "animaux sauvages|bnf|ark:/12148/cb11930908q",
                                "doc_count" => 989
                            ], [
                                "key" => "arbres|bnf|ark:/12148/cb11934786x",
                                "doc_count" => 989
                            ] ]
                        ],
                        "subjects_count" => [
                            "value" => 999
                        ]
                    ]
                ]
            ]);
        $response = $this->get('/api/v1/stats/themes/?limit=3&index=1')->assertStatus(200);
        $response->assertJson(["themes" => [
            "http://ark.bnf.fr/ark:/12148/cb11932889r" => ['label' => 'oiseaux', 'count' => 1003 ],
            "http://ark.bnf.fr/ark:/12148/cb11932496x" => ['label' => 'météorologie', 'count' => 1001 ],
            "http://ark.bnf.fr/ark:/12148/cb11933145f" => ['label' => 'plantes', 'count' => 995  ]
        ], "meta" => ['total' => 999]]);

    }

    public function testIndexLimitIndex2() {

        $query = [
            'index' => env('ELASTICSEARCH_INDEX'),
            'body' => [
                'size' => 0,
                'query' =>[
                    'match_all' => (object) null
                ],
                'aggs' => [
                    "subjects" => [
                        "nested" => [ "path" => "subject" ],
                        "aggs" => [
                            "subjects" => [
                                "terms" => [
                                    "field" => "subject.label_code",
                                    "size" => 9,
                                    "order" => [ '_count' => 'desc' ],
                                    "include" => ".*\|bnf\|.*"
                                ]
                            ],
                            "subjects_count" => [
                                "cardinality" => [
                                    "field" => "subject.label_code"
                                ]
                            ]
                        ]
                    ]
                ]
            ]
        ];

        // This is not normally what should be received, but we test that the limit is respected
        Es::shouldReceive('search')
            ->once()
            ->with($query)
            ->andReturn([
                "took" => 27,
                "timed_out" => false,
                "_shards" => [
                    "total" => 1,
                    "successful" => 1,
                    "failed" => 0
                ],
                "hits" => [
                    "total" => 3011,
                    "max_score" => 0.0,
                    "hits" => [ ]
                ],
                "aggregations" => [
                    "subjects" => [
                        "doc_count" => 41524,
                        "subjects" => [
                            "doc_count_error_upper_bound" => 0,
                            "sum_other_doc_count" => 13678,
                            "buckets" => [ [
                                "key" => "professions|bnf|ark:/12148/cb13318415c",
                                "doc_count" => 1412
                            ], [
                                "key" => "travail non rémunéré|bnf|ark:/12148/cb16604691s",
                                "doc_count" => 1092
                            ], [
                                "key" => "famille|bnf|ark:/12148/cb119339867",
                                "doc_count" => 1050
                            ], [
                                "key" => "oiseaux|bnf|ark:/12148/cb11932889r",
                                "doc_count" => 1003
                            ], [
                                "key" => "météorologie|bnf|ark:/12148/cb11932496x",
                                "doc_count" => 1001
                            ], [
                                "key" => "plantes|bnf|ark:/12148/cb11933145f",
                                "doc_count" => 995
                            ], [
                                "key" => "animaux sauvages|bnf|ark:/12148/cb11930908q",
                                "doc_count" => 989
                            ], [
                                "key" => "arbres|bnf|ark:/12148/cb11934786x",
                                "doc_count" => 989
                            ] ]
                        ],
                        "subjects_count" => [
                            "value" => 999
                        ]
                    ]
                ]
            ]);
        $response = $this->get('/api/v1/stats/themes/?limit=3&index=2')->assertStatus(200);
        $response->assertJson(["themes" => [
            "http://ark.bnf.fr/ark:/12148/cb11930908q" => ['label' => 'animaux sauvages', 'count' => 989 ],
            "http://ark.bnf.fr/ark:/12148/cb11934786x" => ['label' => 'arbres', 'count' => 989 ]
        ], "meta" => ['total' => 999]]);
    }

}
