<?php

namespace sparql;

use \ML\JsonLD\JsonLD;

const SPARQL_ENDPOINT  = 'http://localhost:3030/dokk/query';

 
/**
 * Query the SPARQL endpoint with a POST request and return
 * the response.
 */
function query ($query, $format = 'json')
{
    $content = [ 'query' => $query, 'format' => $format ];
    
    $options = [ 'http' => [
        'header'  => "Content-type: application/x-www-form-urlencoded\r\n",
        'method'  => 'POST',
        'content' => http_build_query ($content)
    ]];
    
    $data = file_get_contents (SPARQL_ENDPOINT, FALSE, stream_context_create ($options));
    
    if ($format == 'json')
        return json_decode ($data, TRUE);
    
    return $data;
}

// Change frame of some JSON-LD data (previously retrieved).
// https://json-ld.org/spec/latest/json-ld-framing/
function apply_frame ($data, $frame = '')
{
    if (gettype ($data) === 'array')
        $data = json_encode ($data);
    
    if (gettype ($frame) === 'array')
        $frame = json_encode ($frame);
    
    /**
     * json_decode (json_encode ()) required because JsonLD returns a PHP object,
     * but we want to return an Array.
     */
    return json_decode (json_encode (JsonLD::frame ($data, $frame)), TRUE);
}


/***********************************************
 * QUERIES TO BUILD A NEW DOKK NODE
 **********************************************/


/**
 * Add tags to an URI. These are useful to identify some properties of $uri,
 * which are used to decide how to render the final page (eg. which properties
 * to use or alternate values).
 */
function tag_node ($uri)
{
    $tags = [];
    
    // Is this a SPDX license?
    $query = '
        PREFIX spdx: <http://spdx.org/rdf/terms#>

        ASK FROM <graph:spdx>
        { <' . $uri . '> a spdx:License }';
    
    $tags['spdx-license'] = query ($query)['boolean'];
    
    // Is this a free software from the FSD?
    $query = '
        PREFIX fsd-c: <http://directory.fsf.org/wiki/Special:URIResolver/Category-3A>

        ASK FROM <graph:free-software-directory>
        { <' . $uri . '> a fsd-c:Entry }';
    
    $tags['fsd'] = query ($query)['boolean'];
    
    return $tags;
}

/**
 * Build the actual node of the dokk graph.
*/
function dokk_node ($uri, $tags)
{
    $node = NULL;
    
    // This node is a SPDX license
    if ($tags['spdx-license'])
    {
        
        $query = '
            DESCRIBE <' . $uri . '>
            FROM <graph:spdx>';
        
        $properties = sparql_query ($query);
        
        $node = [
            'schema:sameAs'                     => $properties['@id'],
            'schema:name'                       => $properties['name'],
            'schema:disambiguatingDescription'  => $properties['licenseId'] . ' software license',
            'schema:description'                => ''
        ];
        
    } elseif ($tags['fsd']) {
        
        $query = '
            PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
            PREFIX fsd-p: <http://directory.fsf.org/wiki/Special:URIResolver/Property-3A>
            
            DESCRIBE <' . $uri . '>
            FROM <graph:free-software-directory>';
        
        $properties = query ($query);
        
        $node = [
            'schema:sameAs'                     => $properties['@id'],
            'schema:name'                       => $properties['Property-3AName'],
            'schema:disambiguatingDescription'  => array_key_exists ('Property-3AUse', $properties) && gettype ($properties['Property-3AUse']) == 'string' ? $properties['Property-3AUse'] : '',
            'schema:description'                => $properties['Property-3AShort_description']
        ];
        
    }
    
    if (is_null ($node))
        return NULL;
    
    $node['dokk:uri'] = $node['schema:name'] . '_(' . $node['schema:disambiguatingDescription'] . ')';
    
    // Replace white spaces in DOKK URL with underscores
    $node['dokk:uri'] = preg_replace ('/\s+/', '_', $node['dokk:uri']);
    
    return $node;
}


/**
 * Loop all nodes in Fuseki.
 */
function next_node ($offset = 0)
{
    $query = '
        SELECT DISTINCT ?subject
        FROM <graph:spdx>
        FROM <graph:free-software-directory>
        WHERE {
            ?subject a ?class .
            FILTER (!isBlank (?subject))
        }
        LIMIT 1
        OFFSET ' . $offset;
    
    return query ($query);
}


/***********************************************
 * QUERIES USED FOR TEMPLATES
 **********************************************/


function describe ($uri, $graph = NULL)
{
    $query = 'DESCRIBE <' . $uri . '>';
    
    if (gettype ($graph) === 'string')
        $query = [ $query ];
    
    if (gettype ($graph) === 'array')
        foreach ($graph as $a_graph)
            $query .= 'FROM <' . $a_graph . '>';
    
    return query ($query);
}
