<?php
namespace CorpusParole\Helpers;

use EasyRdf\Resource;
use EasyRdf\Literal;
use EasyRdf\RdfNamespace;

use EasyRdf\Serialiser\Turtle;

/**
 * Globally Inspired by EasyRdf\Serialiser\Turtle::serialiseResource
 */
class RdfHelper {

    private $prefixes = [];

    public function getPrefixes() {
        return $this->prefixes;
    }

    /**
     * Keep track of the prefixes used while serialising
     * @ignore
     */
    public function addPrefix($qname)
    {
        list ($prefix) = explode(':', $qname);
        $this->prefixes[$prefix] = true;
        return $prefix;
    }


    /**
     * Given a IRI string, escape and enclose in angle brackets.
     *
     * @param  string $resourceIri
     *
     * @return string
     */
    public function escapeIri($resourceIri) {
        $escapedIri = str_replace('>', '\\>', $resourceIri);
        return "<span class=\"corpus-rdf-resource\"><span class=\"corpus-rdf-resource-delimiter\">&lt;</span><a class=\"corpus-rdf-resource-link\" href=\"$resourceIri\" target=\"_blank\">".htmlentities($escapedIri)."</a><span class=\"corpus-rdf-resource-delimiter\">&gt;</span></span>";
    }

    /**
     * Insprired by EasyRdf\Serialiser\Turtle::serialiseLiteral
     * Given a string, enclose in quotes and escape any quotes in the string.
     * Strings containing tabs, linefeeds or carriage returns will be
     * enclosed in three double quotes (""").
     *
     * @param  string $value
     *
     * @return string
     */
    public function serialiseLiteral($literal)
    {
        $value = strval($literal);
        $quoted = Turtle::quotedString($value);

        if ($datatype = $literal->getDatatypeUri()) {
            if ($datatype == 'http://www.w3.org/2001/XMLSchema#integer') {
                return sprintf('<span class="corpus-rdf-literal corpus-rdf-literal-value">%d</span>', $value);
            } elseif ($datatype == 'http://www.w3.org/2001/XMLSchema#decimal') {
                return sprintf('<span class="corpus-rdf-literal corpus-rdf-literal-value">%s</span>', $value);
            } elseif ($datatype == 'http://www.w3.org/2001/XMLSchema#double') {
                return sprintf('<span class="corpus-rdf-literal corpus-rdf-literal-value">%e</span>', $value);
            } elseif ($datatype == 'http://www.w3.org/2001/XMLSchema#boolean') {
                return sprintf('<span class="corpus-rdf-literal corpus-rdf-literal-value">%s</span>', $value);
            } else {
                $escaped = $this->serialiseResource($datatype, false);
                return sprintf('<span class="corpus-rdf-literal"><span class="corpus-rdf-literal-value corpus-rdf-literal-value-str">%s</span><span class="corpus-rdf-literal-type-separator">^^</span><span class="corpus-rdf-literal-type">%s</span></span>', $quoted, $escaped);
            }
        } elseif ($lang = $literal->getLang()) {
            return sprintf('<span class="corpus-rdf-literal"><span class="corpus-rdf-literal-value corpus-rdf-literal-value-str">%s</span><span class="corpus-rdf-literal-lang-separator">@</span><span class="corpus-rdf-literal-lang">%s</span></span>',$quoted, $lang);
        } else {
            return "<span class=\"corpus-rdf-literal corpus-rdf-literal-value\">$quoted</span>";
        }
    }

    /**
     * Given a an EasyRdf\Resource or URI, convert it into a string, suitable to
     * be written to a Turtle document. URIs will be shortened into CURIES
     * where possible.
     *
     * @param  Resource|string $resource The resource to convert to a Turtle string
     * @param  boolean $createNamespace  If true, a new namespace may be created
     *
     * @return string
     */
    public function serialiseResource($resource, $createNamespace = false)
    {
        if (is_object($resource)) {
            if ($resource->isBNode()) {
                $uri = preg_replace("/^_\:/", "", $resource->getUri(), 1);
                return "<span class=\"corpus-rdf-blank-node\"><span class=\"corpus-rdf-blank-node-prefix\">_:</span>".htmlentities($uri)."</span>";
            }

            $resource = $resource->getUri();
        }

        $short = RdfNamespace::shorten($resource, $createNamespace);

        if ($short) {
            $prefix = $this->addPrefix($short);
            $shortVal = substr($short, strlen($prefix)+1);
            $namespaceVal = RdfNamespace::namespaces()[$prefix];

            return "<span class=\"corpus-rdf-resource\"><span class=\"corpus-rdf-resource-prefix\" title=\"$namespaceVal\">$prefix</span><span class=\"corpus-rdf-resource-short-separator\">:</span><a class=\"corpus-rdf-resource-link\" href=\"$resource\" target=\"_blank\" title=\"$resource\">".htmlentities($shortVal)."</a></span>";
        }

        return $this->escapeIri($resource);
    }


    public function serialiseValue($val) {

        if($val instanceof Resource) {
            return $this->serialiseResource($val, false);
        } elseif($val instanceof Literal) {
            return $this->serialiseLiteral($val);
        } else {
            throw new \InvalidArgumentException(
                "serialiseObject() requires \$object to be ".
                'of type EasyRdf\Resource or EasyRdf\Literal'
            );
        }

    }

}
