<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  xmlns:sparql="http://www.w3.org/2005/sparql-results#">

<xsl:strip-space elements="*" />
<xsl:preserve-space elements="sparql:literal" />
<xsl:output method="text" />

<xsl:param name="tqx" />

<xsl:variable name="defaultNs">
  <xsl:call-template name="namespace">
    <xsl:with-param name="string" select="/rdf:RDF/rdf:Description[1]/rdf:type[1]/@rdf:resource" />
  </xsl:call-template>
</xsl:variable>

<xsl:template match="sparql:sparql">
  <xsl:param name="tqx" select="$tqx" />
  
  <xsl:variable name="reqId">
    <xsl:variable name="fromTQX">
      <xsl:call-template name="parseTQX">
        <xsl:with-param name="param" select="'reqId'" />
        <xsl:with-param name="tqx" select="$tqx" />
      </xsl:call-template>
    </xsl:variable>
    <xsl:choose>
      <xsl:when test="$fromTQX != ''">
        <xsl:value-of select="$fromTQX" />
      </xsl:when>
      <xsl:otherwise>
        <xsl:text>0</xsl:text>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>
  
  <xsl:variable name="version">
    <xsl:variable name="fromTQX">
      <xsl:call-template name="parseTQX">
        <xsl:with-param name="param" select="'version'" />
        <xsl:with-param name="tqx" select="$tqx" />
      </xsl:call-template>
    </xsl:variable>
    <xsl:choose>
      <xsl:when test="$fromTQX != ''">
        <xsl:value-of select="$fromTQX" />
      </xsl:when>
      <xsl:otherwise>
        <xsl:text>0.6</xsl:text>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>
  
  <xsl:variable name="out">
    <xsl:variable name="fromTQX">
      <xsl:call-template name="parseTQX">
        <xsl:with-param name="param" select="'out'" />
        <xsl:with-param name="tqx" select="$tqx" />
      </xsl:call-template>
    </xsl:variable>
    <xsl:choose>
      <xsl:when test="$fromTQX != ''">
        <xsl:value-of select="$fromTQX" />
      </xsl:when>
      <xsl:otherwise>
        <xsl:text>json</xsl:text>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>
  
  <xsl:variable name="responseHandler">
    <xsl:variable name="fromTQX">
      <xsl:call-template name="parseTQX">
        <xsl:with-param name="param" select="'responseHandler'" />
        <xsl:with-param name="tqx" select="$tqx" />
      </xsl:call-template>
    </xsl:variable>
    <xsl:choose>
      <xsl:when test="$fromTQX != ''">
        <xsl:value-of select="$fromTQX" />
      </xsl:when>
      <xsl:otherwise>
        <xsl:text>google.visualization.Query.setResponse</xsl:text>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>
  
  <xsl:value-of select="$responseHandler" />
  <xsl:text>({</xsl:text>
  <xsl:text>version:</xsl:text><xsl:value-of select="$version" /><xsl:text>,</xsl:text>
  <xsl:text>status:'ok',</xsl:text>
  <xsl:text>reqId:</xsl:text><xsl:value-of select="$reqId" /><xsl:text>,</xsl:text>
  <xsl:text>table:{</xsl:text>
  <xsl:apply-templates select="sparql:head" />
  <xsl:apply-templates select="sparql:results" />
  <xsl:text>}</xsl:text><!-- end table -->
  <xsl:text>})</xsl:text>
</xsl:template>

<xsl:template match="sparql:head">
  <xsl:text>cols:[</xsl:text>
  <xsl:for-each select="sparql:variable">
    <xsl:apply-templates select="." />
    <xsl:if test="position() != last()">,</xsl:if>
  </xsl:for-each>
  <xsl:text>],</xsl:text>
</xsl:template>
  
<xsl:template match="sparql:variable">
  <xsl:variable name="name" select="@name" />
  <xsl:variable name="binding"
    select="(/sparql:sparql/sparql:results/sparql:result/sparql:binding[@name = $name])[1]" />
  <xsl:text>{id:'</xsl:text>
  <xsl:value-of select="@name" />
  <xsl:text>',type:'</xsl:text>
  <xsl:choose>
    <xsl:when test="$binding/sparql:uri">string</xsl:when>
    <xsl:otherwise>
      <xsl:variable name="datatype" select="$binding/sparql:literal/@datatype" />
      <xsl:choose>
        <xsl:when test="$datatype = 'http://www.w3.org/2001/XMLSchema#decimal'">number</xsl:when>
        <xsl:when test="$datatype = 'http://www.w3.org/2001/XMLSchema#integer'">number</xsl:when>
        <xsl:when test="$datatype = 'http://www.w3.org/2001/XMLSchema#float'">number</xsl:when>
        <xsl:when test="$datatype = 'http://www.w3.org/2001/XMLSchema#double'">number</xsl:when>
        <xsl:when test="$datatype = 'http://www.w3.org/2001/XMLSchema#int'">number</xsl:when>
        <xsl:when test="$datatype = 'http://www.w3.org/2001/XMLSchema#boolean'">boolean</xsl:when>
        <xsl:when test="$datatype = 'http://www.w3.org/2001/XMLSchema#date'">date</xsl:when>
        <xsl:when test="$datatype = 'http://www.w3.org/2001/XMLSchema#dateTime'">datetime</xsl:when>
        <xsl:when test="$datatype = 'http://www.w3.org/2001/XMLSchema#time'">timeofday</xsl:when>
        <xsl:otherwise>
          <xsl:variable name="value" select="$binding/sparql:literal" />
          <xsl:choose>
            <xsl:when test="string(number($value)) != 'NaN'">number</xsl:when>
            <xsl:when test="$value = 'true' or $value = 'false'">boolean</xsl:when>
            <xsl:otherwise>string</xsl:otherwise>
          </xsl:choose>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:otherwise>
  </xsl:choose>
  <xsl:text>'}</xsl:text>
</xsl:template>

<xsl:template match="sparql:results">
  <xsl:text>rows:[</xsl:text>
  <xsl:for-each select="sparql:result">
    <xsl:apply-templates select="." />
    <xsl:if test="position() != last()">,</xsl:if>
  </xsl:for-each>
  <xsl:text>]</xsl:text>
</xsl:template>

<xsl:template match="sparql:result">
  <xsl:variable name="result" select="." />
  <xsl:text>{c:[</xsl:text>
  <xsl:for-each select="/sparql:sparql/sparql:head/sparql:variable">
    <xsl:variable name="name" select="@name" />
    <xsl:apply-templates select="$result/sparql:binding[@name = $name]" />
    <xsl:if test="position() != last()">,</xsl:if>
  </xsl:for-each>
  <xsl:text>]}</xsl:text>
</xsl:template>

<xsl:template match="sparql:binding">
  <xsl:text>{v:</xsl:text>
  <xsl:choose>
    <xsl:when test="sparql:uri">
      <xsl:text>'</xsl:text>
      <xsl:value-of select="sparql:uri" />
      <xsl:text>'</xsl:text>
    </xsl:when>
    <xsl:otherwise>
      <xsl:variable name="datatype" select="sparql:literal/@datatype" />
      <xsl:choose>
        <xsl:when test="$datatype = 'http://www.w3.org/2001/XMLSchema#decimal' or
                        $datatype = 'http://www.w3.org/2001/XMLSchema#integer' or
                        $datatype = 'http://www.w3.org/2001/XMLSchema#float' or 
                        $datatype = 'http://www.w3.org/2001/XMLSchema#double' or
                        $datatype = 'http://www.w3.org/2001/XMLSchema#int' or
                        (not($datatype) and string(number(sparql:literal)) != 'NaN')">
          <xsl:value-of select="sparql:literal" />
        </xsl:when>
        <xsl:when test="$datatype = 'http://www.w3.org/2001/XMLSchema#date' or
                        $datatype = 'http://www.w3.org/2001/XMLSchema#dateTime'">
          <xsl:text>new Date(</xsl:text>
          <xsl:value-of select="substring(sparql:literal, 1, 4)" />
          <xsl:text>,</xsl:text>
          <xsl:value-of select="substring(sparql:literal, 6, 2)" />
          <xsl:text>,</xsl:text>
          <xsl:value-of select="substring(sparql:literal, 9, 2)" />
          <xsl:if test="$datatype = 'http://www.w3.org/2001/XMLSchema#dateTime'">
            <xsl:text>,</xsl:text>
            <xsl:value-of select="substring(sparql:literal, 12, 2)" />
            <xsl:text>,</xsl:text>
            <xsl:value-of select="substring(sparql:literal, 15, 2)" />
            <xsl:text>,</xsl:text>
            <xsl:value-of select="substring(sparql:literal, 18, 2)" />
          </xsl:if>
          <xsl:text>)</xsl:text>
        </xsl:when>
        <xsl:when test="$datatype = 'http://www.w3.org/2001/XMLSchema#time'">
          <xsl:text>[</xsl:text>
          <xsl:value-of select="substring(sparql:literal, 1, 2)" />
          <xsl:text>,</xsl:text>
          <xsl:value-of select="substring(sparql:literal, 4, 2)" />
          <xsl:text>,</xsl:text>
          <xsl:value-of select="substring(sparql:literal, 7, 2)" />
          <xsl:text>]</xsl:text>
        </xsl:when>
        <xsl:otherwise>
          <xsl:text>'</xsl:text>
          <xsl:value-of select="sparql:literal" />
          <xsl:text>'</xsl:text>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:otherwise>
  </xsl:choose>
  <xsl:text>}</xsl:text>
</xsl:template>

<xsl:template name="namespace">
  <xsl:param name="string" />
  <xsl:param name="namespace" />
  <xsl:choose>
    <xsl:when test="contains($string, '#')">
      <xsl:value-of select="concat(substring-before($string, '#'), '#')" />
    </xsl:when>
    <xsl:when test="contains($string, '/')">
      <xsl:call-template name="namespace">
        <xsl:with-param name="string" select="substring-after($string, '/')" />
        <xsl:with-param name="namespace"
          select="concat($namespace, substring-before($string, '/'), '/')" />
      </xsl:call-template>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="$namespace" />
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

<xsl:template name="parseTQX">
  <xsl:param name="param" />
  <xsl:param name="tqx" select="$tqx" />
  <xsl:if test="contains($tqx, concat($param, ':'))">
    <xsl:value-of select="substring-before(substring-after(concat($tqx, ';'), concat($param, ':')), ';')" />
  </xsl:if>
</xsl:template>

</xsl:stylesheet>
