<?php

use CorpusParole\Libraries\Mergers\CocoonCollectionRdfMerger;
use CorpusParole\Libraries\CocoonUtils;

use EasyRdf\Graph;
use EasyRdf\Resource;
use EasyRdf\Literal;

use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;

class CocoonCollectionRdfMergerTest extends TestCase
{

    const TEST_INPUT_DOCS = [
        'BASE' => <<<EOT
        @prefix edm: <http://www.europeana.eu/schemas/edm/> .
        @prefix dc11: <http://purl.org/dc/elements/1.1/> .
        @prefix dc: <http://purl.org/dc/terms/> .
        @prefix olac: <http://www.language-archives.org/OLAC/1.1/> .
        @prefix geo: <http://www.w3.org/2003/01/geo/wgs84_pos#> .
        @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
        @prefix skos: <http://www.w3.org/2004/02/skos/core#> .
        @prefix owl: <http://www.w3.org/2002/07/owl#> .

        <%1\$scrdo-COLLECTION_CFPP2000>
          a edm:Collection ;
          dc:isVersionOf <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-COLLECTION_CFPP2000> ;
          dc11:description "Corpus de Français Parlé Parisien des années 2000."@fr, "Le Corpus de FranÃ§ais ParlÃ© Parisien (CFPP2000) est composÃ© d'un ensemble d'interviews non directives sur les quartiers de Paris et de la proche banlieue. Les entretiens, transcrits en orthographe et alignÃ©s au tour de parole, sont disponibles sur le net ; ils sont librement employables en Ã©change de la mention dans la bibliographie des travaux qui en seraient tirÃ©s d'une part de l'adresse du site: http://cfpp2000.univ-paris3.fr/ et d'autre part du document de prÃ©sentation suivant : Branca-Rosoff S., Fleury S., Lefeuvre F., Pires M., 2012, \"Discours sur la ville. PrÃ©sentation du Corpus de FranÃ§ais ParlÃ© Parisien des annÃ©es 2000 (CFPP2000)\". En fÃ©vrier 2013, ce corpus comprenait environ 550 000 mots. Un certain nombre d'outils en ligne, notamment un concordancier et  des outils textomÃ©triques permettent de mener des requÃªtes lexicales et grammaticales. CFPP2000 est particuliÃ¨rement destinÃ© Ã  des analyses sur le franÃ§ais oral. Le projet sous-jacent au corpus est par ailleurs l'Ã©tude des modifications et des variations qui interviennent dans ce qu'on peut considÃ©rer comme un parisien vÃ©hiculaire en tension entre le pÃ´le du standard et le pÃ´le du vernaculaire. Par ailleurs, il comporte des activitÃ©s linguistiques diversifiÃ©es (description de quartier, anecdotes, argumentationâ¦) et on peut par consÃ©quent travailler sur la syntaxe propre Ã  ces diffÃ©rentes utilisations du langage. Il permet enfin d'opposer dialogues (entre enquÃªteur et enquÃªtÃ©s) et multilogues (oÃ¹ la prÃ©sence de plusieurs enquÃªtÃ©s favorise le passage Ã  un registre familier).  CFPP2000 est constituÃ© d'interviews longues (d'une heure en moyenne) intÃ©gralement transcrites. Il est donc utilisable pour examiner les singularitÃ©s qui reviennent Ã  l'idiolecte propre Ã  une personne donnÃ©e, par opposition aux variantes diffusÃ©es dans des groupes plus larges (quartiers, groupes socio-culturels, classe d'Ã¢ge, etc.). Le corpus constitue enfin un ensemble de tÃ©moignages intÃ©ressants sur les reprÃ©sentations de Paris et de sa proche banlieue qui est susceptible d'intÃ©resser des analystes du discours, des sociologues, ou tout simplement des curieux de la ville."@fr ;
          dc11:language <http://lexvo.org/id/iso639-3/gsw> ;
          dc11:publisher <http://viaf.org/viaf/142432638>, "Fédération CLESTHIA", <http://viaf.org/viaf/154862993> ;
          dc11:rights "Copyright (c) Département de dialectologie alsacienne et mosellane de l'Université de Strasbourg" ;
          dc11:type <http://purl.org/dc/dcmitype/Collection> ;
          dc:license <http://creativecommons.org/licenses/by-nc-sa/3.0/> ;
          dc11:subject <http://lexvo.org/id/iso639-3/fra> ;
          dc11:title "Corpus de Français Parlé Parisien des années 2000 (CFPP)"@fr ;
          dc:accessRights "Freely available for non-commercial use" ;
          dc:isPartOf <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-COLLECTION_ALA> ;
          olac:compiler "Branca-Rosoff, Sonia", "Fleury, Serge", "Lefeuvre, Florence", "Pires, Mat" ;
          dc11:contributor "Branca-Rosoff, Sonia", "Fleury, Serge", "Lefeuvre, Florence", "Pires, Mat", <http://viaf.org/viaf/93752300>, "Ville de Paris ", "Délégation générale à la langue française et aux langues de France " ;
          olac:data_inputter "Branca-Rosoff, Sonia", "Lefeuvre, Florence", "Pires, Mat" ;
          olac:depositor <http://viaf.org/viaf/93752300> ;
          olac:developer "Fleury, Serge" ;
          olac:interviewer "Branca-Rosoff, Sonia", "Lefeuvre, Florence", "Pires, Mat" ;
          olac:researcher "Branca-Rosoff, Sonia", "Fleury, Serge", "Lefeuvre, Florence", "Pires, Mat" ;
          olac:sponsor "Ville de Paris ", "Délégation générale à la langue française et aux langues de France " ;
          olac:transcriber "Branca-Rosoff, Sonia", "Lefeuvre, Florence", "Pires, Mat" ;
          dc:available "2013-04-12"^^dc:W3CDTF ;
          dc:created "start=1988; end=1989"^^dc:Period ;
          dc:issued "2013-04-12T22:20:23+02:00"^^dc:W3CDTF ;
          dc:modified "2014-05-10T20:16:27+02:00"^^dc:W3CDTF ;
          dc:spatial [
            a edm:Place ;
            geo:lat "48.8667"^^xsd:float ;
            geo:long "2.3333"^^xsd:float ;
            skos:note "FR"^^dc:ISO3166, "France, Paris, Université Sorbonne Nouvelle Paris 3, site Censier"@fr ;
            owl:sameAs <http://vocab.getty.edu/tgn/7008038>
          ] .
EOT
        ,
        'SOURCE' => <<<EOT
        @prefix edm: <http://www.europeana.eu/schemas/edm/> .
        @prefix dc11: <http://purl.org/dc/elements/1.1/> .
        @prefix dc: <http://purl.org/dc/terms/> .
        @prefix geo: <http://www.w3.org/2003/01/geo/wgs84_pos#> .
        @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
        @prefix skos: <http://www.w3.org/2004/02/skos/core#> .
        @prefix owl: <http://www.w3.org/2002/07/owl#> .

        <%1\$scrdo-COLLECTION_CFPP2000>
          a edm:Collection ;
          dc:isVersionOf <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-COLLECTION_CFPP2000> ;
          dc11:title "Other title"@fr ;
          dc:created "start=1988; end=1989"^^dc:Period ;
          dc:issued "2013-04-12T22:20:23+02:00"^^dc:W3CDTF ;
          dc:modified "2014-05-10T20:16:27+02:00"^^dc:W3CDTF ;
          dc11:language <http://lexvo.org/id/iso639-3/gsw>, <http://lexvo.org/id/iso639-3/fra> ;
          dc:spatial [
            a edm:Place ;
            geo:lat "89.8667"^^xsd:float ;
            geo:long "55.3333"^^xsd:float ;
            skos:note "FR"^^dc:ISO3166, "France, Paris, Université Sorbonne Nouvelle Paris 3, site Censier"@fr, "Other place very important"@fr ;
            owl:sameAs <http://vocab.getty.edu/tgn/1234567890>
          ] .
EOT
    ];

    const TEST_INPUT_ID = "crdo-COLLECTION_CFPP2000";
    const TEST_CHO_URI = "http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-COLLECTION_CFPP2000";


    private $inputGraphes = [];
    private $resGraph;
    private $merger;

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

    public function setUp() {
        parent::setUp();

        $this->testGraphUri = config('corpusparole.corpus_doc_id_base_uri').CocoonCollectionRdfMergerTest::TEST_INPUT_ID;
        foreach(CocoonCollectionRdfMergerTest::TEST_INPUT_DOCS as $key => $inputDoc) {
            $this->inputGraphes[$key] = new Graph(config('corpusparole.corpus_doc_id_base_uri')."crdo-COLLECTION_CFPP2000", sprintf($inputDoc, config('corpusparole.corpus_doc_id_base_uri')));
        }

        $this->merger = new CocoonCollectionRdfMerger();
        $this->resGraph = $this->merger->mergeGraph($this->inputGraphes['BASE'], $this->inputGraphes['SOURCE']);
    }

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

    /**
     * Just test that the construct and setup are ok
     *
     * @return void
     */
    public function testInit()
    {
        $this->assertTrue(true);
        //echo $this->resGraph->serialise('turtle');
    }

    /**
     * test the result graph.
     *
     * @return void
     */
    public function testResGraph() {
        $this->assertNotNull($this->resGraph, "Res graph must not be null");
        $this->assertEquals(config('corpusparole.corpus_doc_id_base_uri')."crdo-COLLECTION_CFPP2000", $this->resGraph->getUri(), "graph uri must be equals to ".config('corpusparole.corpus_doc_id_base_uri')."crdo-CFPP2000_35_SOUND");
    }



    /**
     * test the merged Aggregation
     *
     * @return void
     */
    public function testCollectionResource() {
        $collectionResList = $this->resGraph->allOfType('http://www.europeana.eu/schemas/edm/Collection');
        $this->assertCount(1, $collectionResList, "Only one Collection node");
        $collectionRes = $collectionResList[0];

        $this->assertEquals(config('corpusparole.corpus_doc_id_base_uri')."crdo-COLLECTION_CFPP2000",$collectionRes->getUri(),"Collection node uri must be ".config('corpusparole.corpus_doc_id_base_uri')."crdo-COLLECTION_CFPP2000");

        $singleValuesRes = [
            'http://purl.org/dc/elements/1.1/title' => ['size'=>1, 'val' => new Literal("Corpus de Français Parlé Parisien des années 2000 (CFPP)", "fr", null)],
            'http://purl.org/dc/terms/available' => ['size'=>1, 'val' => new Literal("2013-04-12", null, "dc:W3CDTF")],
            'http://purl.org/dc/terms/created' => ['size'=>1, 'val' => new Literal("start=1988; end=1989", null, "dc:Period")],
            'http://purl.org/dc/terms/issued' => ['size'=>1, 'val' => new Literal("2013-04-12T22:20:23+02:00", null, "dc:W3CDTF")],
            'http://purl.org/dc/terms/modified' => ['size'=>1, 'val' => new Literal("2014-05-10T20:16:27+02:00", null, "dc:W3CDTF")],
            'http://purl.org/dc/elements/1.1/language' => ['size' => 2, 'val' => [
                $this->resGraph->resource("http://lexvo.org/id/iso639-3/gsw"),
                $this->resGraph->resource("http://lexvo.org/id/iso639-3/fra"),
            ]]
        ];

        foreach($singleValuesRes as $property => $resVal) {
            $resList = $collectionRes->all($this->inputGraphes['BASE']->resource($property));
            $this->assertCount($resVal['size'], $resList, "$property list size $resVal[size]");
            if($resVal['size'] == 1) {
                $this->assertEquals($resVal['val'], $resList[0], "$property size one not equals");
            }
            else {
                $this->assertEquals($resVal['val'], $resList, "$property size more than one not equals");
            }
        }

    }

    /**
    * Test one to one mapping spatial info
    *
    * @return void
    */
    public function testProvidedCHOSpatial() {
        $collection = $this->resGraph->get('edm:Collection', '^rdf:type');

        $this->assertNotNull($collection);

        $spatials = $collection->all($this->resGraph->resource('http://purl.org/dc/terms/spatial'));

        $this->assertCount(1, $spatials, "Must have only one spatial node");
        $spatial = $spatials[0];
        $this->assertTrue($spatial->isBNode(),"spatial node must be blank");
        $this->assertEquals("edm:Place", $spatial->type(), "spatial node type must be edm:Place");

        $lats = $spatial->all('geo:lat');
        $this->assertCount(1, $lats, "One latitude");
        $this->assertInstanceOf("EasyRdf\Literal", $lats[0], "Latitude must be a litteral");
        $this->assertEquals(Literal::create("48.8667", null, 'xsd:float'), $lats[0], "lat must be '48.8667'^^xsd:float");

        $longs = $spatial->all('geo:long');
        $this->assertCount(1, $longs, "One longitude");
        $this->assertInstanceOf("EasyRdf\Literal", $longs[0], "Longitude must be a litteral");
        $this->assertEquals(Literal::create("2.3333", null, 'xsd:float'), $longs[0], "long must be '2.3333'^^xsd:float");

        $notes = $spatial->all('skos:note');
        $this->assertCount(3, $notes, "3 notes");
        $this->assertContainsOnlyInstancesOf("EasyRdf\Literal", $notes, "Notes mus be only literals");
        $this->assertEquals(Literal::create("FR", null, "dc:ISO3166"), $notes[0], "notes contains 'FR'^^dc:ISO3166");
        $this->assertEquals(Literal::create("France, Paris, Université Sorbonne Nouvelle Paris 3, site Censier", "fr", null), $notes[1], "notes contains 'France, Paris, Université Sorbonne Nouvelle Paris 3, site Censier'@fr");
        $this->assertEquals(Literal::create("Other place very important", "fr", null), $notes[2], "notes contains 'Other place very important'@fr");

        $sameas = $spatial->all('owl:sameAs');
        $this->assertCount(1, $sameas, "1 same as");
        $this->assertContainsOnlyInstancesOf("EasyRdf\Resource", $sameas, "Notes mus be only resources");
        $this->assertEquals('http://vocab.getty.edu/tgn/7008038', $sameas[0]->getUri(), "uri must be http://vocab.getty.edu/tgn/7008038");
    }

    public function testLinkToCocoonCollection() {
        $coll = $this->resGraph->get('edm:Collection', '^rdf:type');

        $this->assertNotNull($coll);

        $versionOfRes = $coll->all("<http://purl.org/dc/terms/isVersionOf>");
        $this->assertCount(1, $versionOfRes, "Must have only on isVersionOf");
        $versionOfRes = $versionOfRes[0];
        $this->assertInstanceOf("EasyRdf\Resource", $versionOfRes, "version Res must be a resource");
        $this->assertEquals(CocoonCollectionRdfMergerTest::TEST_CHO_URI, $versionOfRes->getUri(), "versionof res uri must be sams than source");

    }




}
