<?php

use Illuminate\Support\Facades\Facade;

use CorpusParole\Repositories\RdfDocumentRepository;
use CorpusParole\Libraries\Sparql\SparqlClient;
use CorpusParole\Models\Document;
use CorpusParole\Models\DocumentResult;


use Mockery as m;

class DocumentRepositoryTest extends TestCase {

    const TEST_DOC = <<<EOT
    @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
    @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
    @prefix sesame: <http://www.openrdf.org/schema/sesame#> .
    @prefix owl: <http://www.w3.org/2002/07/owl#> .
    @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
    @prefix fn: <http://www.w3.org/2005/xpath-functions#> .

    _:genid-2267740936ad4d04a567e6787732f0dd-genid1 a <http://www.europeana.eu/schemas/edm/Place> ;
        owl:sameAs <http://sws.geonames.org/3038033/> ;
        <http://www.w3.org/2004/02/skos/core#note> "northlimit=47.431892250000033; southlimit=49.053971250000046;westlimit=6.846186050000028; eastlimit=8.232571550000074;"^^<http://purl.org/dc/terms/Box> , "FR"^^<http://purl.org/dc/terms/ISO3166> , "France, Alsace"@fr .

    <%1\$scrdo-ALA_738> a <http://www.openarchives.org/ore/terms/Aggregation> ;
        <http://www.europeana.eu/schemas/edm/aggregatedCHO> <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-ALA_738> ;
        <http://www.europeana.eu/schemas/edm/dataProvider> "Atlas linguistiques, cultures et parlers régionaux de France" ;
        <http://www.europeana.eu/schemas/edm/hasView> <http://cocoon.huma-num.fr/data/ala/ALA_738.mp3> , <http://cocoon.huma-num.fr/data/ala/ALA_738_22km.wav> ;
        <http://www.europeana.eu/schemas/edm/isShownAt> <http://corpusdelaparole.huma-num.fr/corpus-app#/detail/crdo-ALA_738> ;
        <http://www.europeana.eu/schemas/edm/isShownBy> <http://cocoon.huma-num.fr/data/ala/masters/ALA_738.wav> ;
        <http://www.europeana.eu/schemas/edm/provider> "Corpus de la Parole"@fr ;
        <http://www.europeana.eu/schemas/edm/rights> <http://creativecommons.org/licenses/by-nc-nd/4.0/> .

    <http://cocoon.huma-num.fr/data/ala/ALA_738.mp3> a <http://www.europeana.eu/schemas/edm/WebResource> ;
        <http://purl.org/dc/elements/1.1/format> "audio/mpeg"^^<http://purl.org/dc/terms/IMT> ;
        <http://purl.org/dc/terms/created> "1996"^^<http://purl.org/dc/terms/Period> ;
        <http://purl.org/dc/terms/extent> "PT01H11M29S" ;
        <http://purl.org/dc/terms/issued> "2014-11-10T14:27:08+01:00"^^<http://purl.org/dc/terms/W3CDTF> ;
        <http://www.europeana.eu/schemas/edm/isDerivativeOf> <http://cocoon.huma-num.fr/data/ala/masters/ALA_738.wav> .

    <http://cocoon.huma-num.fr/data/ala/masters/ALA_738.wav> a <http://www.europeana.eu/schemas/edm/WebResource> ;
        <http://purl.org/dc/elements/1.1/format> "audio/x-wav"^^<http://purl.org/dc/terms/IMT> ;
        <http://purl.org/dc/terms/created> "1996"^^<http://purl.org/dc/terms/Period> ;
        <http://purl.org/dc/terms/extent> "PT01H11M29S" ;
        <http://purl.org/dc/terms/issued> "2014-11-10T14:27:08+01:00"^^<http://purl.org/dc/terms/W3CDTF> .

    <http://cocoon.huma-num.fr/data/ala/ALA_738_22km.wav> a <http://www.europeana.eu/schemas/edm/WebResource> ;
        <http://purl.org/dc/elements/1.1/format> "audio/x-wav"^^<http://purl.org/dc/terms/IMT> ;
        <http://purl.org/dc/terms/created> "1996"^^<http://purl.org/dc/terms/Period> ;
        <http://purl.org/dc/terms/extent> "PT01H11M29S" ;
        <http://purl.org/dc/terms/issued> "2014-11-10T14:27:08+01:00"^^<http://purl.org/dc/terms/W3CDTF> ;
        <http://www.europeana.eu/schemas/edm/isDerivativeOf> <http://cocoon.huma-num.fr/data/ala/masters/ALA_738.wav> .

    <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-ALA_738> a <http://www.europeana.eu/schemas/edm/ProvidedCHO> ;
        <http://purl.org/dc/terms/created> "1996"^^<http://purl.org/dc/terms/Period> ;
        <http://purl.org/dc/terms/extent> "PT01H11M29S" ;
        <http://purl.org/dc/terms/issued> "2014-11-10T14:27:08+01:00"^^<http://purl.org/dc/terms/W3CDTF> ;
        <http://purl.org/dc/elements/1.1/contributor> <http://viaf.org/viaf/61542329> , <http://viaf.org/viaf/9122216> ;
        <http://purl.org/dc/elements/1.1/description> "Extrait des enquêtes dialectologiques en vue de constituer un atlas linguistique de l'Alsace."@fr ;
        <http://purl.org/dc/elements/1.1/language> <http://lexvo.org/id/iso639-3/gsw> ;
        <http://purl.org/dc/elements/1.1/publisher> "Atlas linguistiques, cultures et parlers régionaux de France" ;
        <http://purl.org/dc/elements/1.1/rights> "Copyright (c) Département de dialectologie alsacienne et mosellane de l'Université de Strasbourg" ;
        <http://purl.org/dc/elements/1.1/subject> <http://lexvo.org/id/iso639-3/gsw> , <http://ark.bnf.fr/ark:/12148/cb11931472p> , <http://ark.bnf.fr/ark:/12148/cb11931564b> , <http://ark.bnf.fr/ark:/12148/cb11932194d> , <http://ark.bnf.fr/ark:/12148/cb11933029x> , <http://ark.bnf.fr/ark:/12148/cb11933281k> , <http://ark.bnf.fr/ark:/12148/cb11934740m> , <http://ark.bnf.fr/ark:/12148/cb11935375d> , <http://ark.bnf.fr/ark:/12148/cb11935986q> , <http://ark.bnf.fr/ark:/12148/cb11936549n> , <http://ark.bnf.fr/ark:/12148/cb11937931x> , <http://ark.bnf.fr/ark:/12148/cb119392962> , <http://ark.bnf.fr/ark:/12148/cb119458243> , <http://ark.bnf.fr/ark:/12148/cb11946662b> , <http://ark.bnf.fr/ark:/12148/cb11947332t> , <http://ark.bnf.fr/ark:/12148/cb119481497> , <http://ark.bnf.fr/ark:/12148/cb119591726> , <http://ark.bnf.fr/ark:/12148/cb119756721> , <http://ark.bnf.fr/ark:/12148/cb119757609> , <http://ark.bnf.fr/ark:/12148/cb11975806s> , <http://ark.bnf.fr/ark:/12148/cb119759527> , <http://ark.bnf.fr/ark:/12148/cb12032030g> , <http://ark.bnf.fr/ark:/12148/cb12042429k> , <http://ark.bnf.fr/ark:/12148/cb12099148r> , <http://ark.bnf.fr/ark:/12148/cb12148936v> , <http://ark.bnf.fr/ark:/12148/cb12289036m> , <http://ark.bnf.fr/ark:/12148/cb13318335q> , <http://ark.bnf.fr/ark:/12148/cb133183540> , <http://ark.bnf.fr/ark:/12148/cb13318415c> , <http://ark.bnf.fr/ark:/12148/cb13318491g> , "anthropological_linguistics"^^<http://www.language-archives.org/OLAC/1.1/linguistic-field> , "lexicography"^^<http://www.language-archives.org/OLAC/1.1/linguistic-field> , "phonetics"^^<http://www.language-archives.org/OLAC/1.1/linguistic-field> ;
        <http://purl.org/dc/elements/1.1/title> "Atlas Linguistique et ethnographique de l'Alsace - Enquetes sur la conscience linguistique - ALA_738"@fr ;
        <http://purl.org/dc/elements/1.1/type> <http://ark.bnf.fr/ark:/12148/cb11932135w> , <http://ark.bnf.fr/ark:/12148/cb12481481z> , <http://purl.org/dc/dcmitype/Sound> , "dialogue"^^<http://www.language-archives.org/OLAC/1.1/discourse-type> , "primary_text"^^<http://www.language-archives.org/OLAC/1.1/linguistic-type> ;
        <http://purl.org/dc/terms/accessRights> "Freely available for non-commercial use" ;
        <http://purl.org/dc/terms/available> "2004-07-03"^^<http://purl.org/dc/terms/W3CDTF> ;
        <http://purl.org/dc/terms/isPartOf> <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-COLLECTION_ALA_CL> , <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-COLLECTION_LANGUESDEFRANCE> ;
        <http://purl.org/dc/terms/license> <http://creativecommons.org/licenses/by-nc-nd/2.5/> ;
        <http://purl.org/dc/terms/spatial> _:genid-2267740936ad4d04a567e6787732f0dd-genid1 ;
        <http://www.language-archives.org/OLAC/1.1/depositor> <http://viaf.org/viaf/9122216> ;
        <http://www.language-archives.org/OLAC/1.1/interviewer> <http://viaf.org/viaf/61542329> , <http://viaf.org/viaf/9122216> .
EOT;

    function __construct(string $name = null) {
        parent::__construct($name);
    }

    public function setUp() {
        parent::setUp();
        $this->graph = new EasyRdf\Graph(config('corpusparole.corpus_doc_id_base_uri')."crdo-ALA_738", sprintf(DocumentRepositoryTest::TEST_DOC, config('corpusparole.corpus_doc_id_base_uri')));
        $this->corpusDocIdBaseUri = config('corpusparole.corpus_doc_id_base_uri');
    }

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


    public function testAll() {
        $expectedId = $this->corpusDocIdBaseUri.'crdo-ALA_738';
        $returnedArray = [
            m::mock('resObj', function($mock) use (&$expectedId) {
                $mock->uri = new EasyRdf\Resource($expectedId);
                $mock->doc = new EasyRdf\Resource("http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-ALA_738");
                $mock->title = new EasyRdf\Literal("Atlas Linguistique et ethnographique de l'Alsace - Enquetes sur la conscience linguistique - ALA_738", null, "fr");
            }),
        ];
        $countArray = [
            m::mock('resObj', function($mock) {
                $mock->count = new EasyRdf\Literal(1, "http://www.w3.org/2001/XMLSchema#integer", null);
            }),
        ];

        $sparqlClientMock = m::mock('CorpusParole\Libraries\Sparql\SparqlClient');
        $sparqlClientMock->shouldReceive('query')->andReturn($countArray, $returnedArray);

        $lexvoResolverMock = m::mock('CorpusParole\Services\LexvoResolverInterface');

        $documentRepository = new \CorpusParole\Repositories\RdfDocumentRepository($sparqlClientMock, $lexvoResolverMock);

        $res = $documentRepository->all();

        $this->assertCount(1, $res, "Should have 1 doc in res");
        $resDoc = $res[0];

        $this->assertInstanceOf(DocumentResult::class, $resDoc, "Res doc must be a Document");
        $this->assertEquals(config('corpusparole.corpus_id_scheme').'crdo-ALA_738', $resDoc->getId(), "id must be crdo...");
        $this->assertEquals($expectedId, $resDoc->getUri(), 'url must be ...');
        $this->assertNotNull($resDoc->getGraph(), 'Graph must be not null');
    }

    public function testGet() {

        $expectedId = $this->corpusDocIdBaseUri.'crdo-ALA_738';
        $returnedGraph = new EasyRdf\Graph($expectedId, sprintf(DocumentRepositoryTest::TEST_DOC, config('corpusparole.corpus_doc_id_base_uri')));

        $sparqlClientMock = m::mock('CorpusParole\Libraries\Sparql\SparqlClient');
        $sparqlClientMock->shouldReceive('query')->with(\Hamcrest\Text\StringContains::containsString($expectedId))
                ->andReturn($returnedGraph);
        $lexvoResolverMock = m::mock('CorpusParole\Services\LexvoResolverInterface');
        $documentRepository = new \CorpusParole\Repositories\RdfDocumentRepository($sparqlClientMock, $lexvoResolverMock);

        $res = $documentRepository->get('crdo-ALA_738');

        $this->assertInstanceOf(Document::class, $res, "Result must be of type Document");
        $this->assertEquals(config('corpusparole.corpus_id_scheme').'crdo-ALA_738', $res->getId(), 'id should be crdo-ALA_738' );
        $this->assertNotNull($res->getGraph(), "Graph shoul not be null");
        $this->assertTrue(EasyRdf\Isomorphic::isomorphic($res->getGraph(), new EasyRdf\Graph($expectedId, sprintf(DocumentRepositoryTest::TEST_DOC, config('corpusparole.corpus_doc_id_base_uri')))));
    }

    public function testGetShort() {

        $expectedId = $this->corpusDocIdBaseUri.'crdo-ALA_738';
        $returnedGraph = new EasyRdf\Graph($expectedId, sprintf(DocumentRepositoryTest::TEST_DOC, config('corpusparole.corpus_doc_id_base_uri')));

        $sparqlClientMock = m::mock('CorpusParole\Libraries\Sparql\SparqlClient');
        $sparqlClientMock->shouldReceive('query')->with(\Hamcrest\Text\StringContains::containsString($expectedId))
            ->andReturn($returnedGraph);
        $lexvoResolverMock = m::mock('CorpusParole\Services\LexvoResolverInterface');
        $documentRepository = new \CorpusParole\Repositories\RdfDocumentRepository($sparqlClientMock, $lexvoResolverMock);

        $res = $documentRepository->get('crdo-ALA_738', true);

        $this->assertInstanceOf(DocumentResult::class, $res, "Result must be of type DocumentResult");
        $this->assertEquals(config('corpusparole.corpus_id_scheme').'crdo-ALA_738', $res->getId(), 'id should be crdo-ALA_738' );
        $this->assertNotNull($res->getGraph(), "Graph shoul not be null");
        $this->assertTrue(EasyRdf\Isomorphic::isomorphic($res->getGraph(), new EasyRdf\Graph($expectedId, sprintf(DocumentRepositoryTest::TEST_DOC, config('corpusparole.corpus_doc_id_base_uri')))));
    }

    public function testSave() {

        $sparqlClientMock = m::mock('CorpusParole\Libraries\Sparql\SparqlClient', function($mock) {
            $mock->shouldReceive('startTransaction')->andReturn(true)
                ->shouldReceive('deleteWhere')
                ->shouldReceive('delete')->shouldReceive('add')
                ->shouldReceive('commit')->andReturn(true);
        });
        $lexvoResolverMock = m::mock('CorpusParole\Services\LexvoResolverInterface');
        $documentRepository = new \CorpusParole\Repositories\RdfDocumentRepository($sparqlClientMock, $lexvoResolverMock);


        $doc = new Document(config('corpusparole.corpus_doc_id_base_uri')."crdo-ALA_738", $this->graph);
        $doc->updateDiscourseTypes(['oratory','drama','narrative']);

        $res = $documentRepository->save($doc);

        $this->assertTrue($res, 'Has started a transaction');

    }

    public function testCount() {

        $returnedCount = [
            m::mock('resObj', function($mock) {
                $mock->count = new EasyRdf\Literal(1);
            }),
        ];

        $sparqlClientMock = m::mock('CorpusParole\Libraries\Sparql\SparqlClient');
        $sparqlClientMock->shouldReceive('query')->with(\Hamcrest\Text\StringContains::containsString("COUNT"))
                ->andReturn($returnedCount);
        $lexvoResolverMock = m::mock('CorpusParole\Services\LexvoResolverInterface');
        $documentRepository = new \CorpusParole\Repositories\RdfDocumentRepository($sparqlClientMock, $lexvoResolverMock);

    }

}
