xquery version "3.1";

module namespace website="http://ahiqar.uni-goettingen.de/ns/website";

import module namespace commons="http://ahiqar.uni-goettingen.de/ns/commons" at "commons.xqm";
import module namespace rest="http://exquery.org/ns/restxq";

declare namespace tei="http://www.tei-c.org/ns/1.0";
declare namespace tgmd="http://textgrid.info/namespaces/metadata/core/2010";
declare namespace xhtml="http://www.w3.org/1999/xhtml";
declare namespace output="http://www.w3.org/2010/xslt-xquery-serialization";

declare
    %rest:GET
    %rest:HEAD
    %rest:path("/website/manuscripts")
    %output:method("text")
function website:manuscripts() {
    let $ara := local:manuscripts-lang("arabic")
    let $karsh := local:manuscripts-lang("karshuni")
    let $syc := local:manuscripts-lang("syriac")
    let $neo := local:manuscripts-lang("neo-aramaic")
    let $sog := local:manuscripts-lang("sogdian")

    return
        (
            "## The Arabic witnesses",
            $ara,
            "## The Karshuni witnesses",
            $karsh,
            "## The Syriac witnesses",
            $syc,
            "## The Neo-Aramaic witnesses",
            $neo,
            "## The Sogdian witness",
            $sog
        )
};

declare function local:manuscripts-lang($lang as xs:string) {
    let $teiHeaders :=
        if($lang eq "syriac") then
            commons:get-available-aggregates("3r84g")
            ! commons:get-child-tei-uri(.)
            ! doc(.)//tei:teiHeader
        else if($lang eq "neo-aramaic") then
            commons:get-available-aggregates("40xnp")
            ! commons:get-child-tei-uri(.)
            ! doc(.)//tei:teiHeader
        else if($lang eq "sogdian") then
            commons:get-available-aggregates("41np5")
            ! commons:get-child-tei-uri(.)
            ! doc(.)//tei:teiHeader
        else if($lang eq "arabic") then
            commons:get-available-aggregates("3r9ps")
            ! commons:get-child-tei-uri(.)
            ! doc(.)//tei:teiHeader
        else if($lang eq "karshuni") then
            commons:get-available-aggregates("3r84h")
            ! commons:get-child-tei-uri(.)
            ! doc(.)//tei:teiHeader
        else
            ()

    for $teiHeader at $pos in $teiHeaders
        where $pos
        order by $teiHeader//tei:sourceDesc//tei:idno[not(parent::tei:altIdentifier)][1]
        let $url := "https://ahiqar.uni-goettingen.de/" || $lang || ".html?tido=m" || $pos - 1 || "_i0"

        let $meta := doc( $commons:meta || ($teiHeader/base-uri() => tokenize("/"))[last()])
        let $title := $meta//tgmd:title/text()
        let $title :=
            local:add-empty-line() || "### " || string($title)


        let $listBibl := $teiHeader//tei:listBibl/tei:bibl
        let $bibls :=
                for $bibl in $listBibl
                return
                    if (normalize-space($bibl) != "") then
                        "* " || normalize-space($bibl) || local:add-newline()
                    else
                        ()
        let $listBibl :=
            if (string-join($bibls) => normalize-space() != "") then
                local:add-empty-line() || "#### Bibliography" || local:add-empty-line() || string-join($bibls)
            else
                ()

        let $abstract := $teiHeader//tei:abstract
        let $statements :=
            for $p in $abstract//tei:p return
                let $n := $p/@n
                let $title :=
                    switch ($n)
                        case "general" return "##### General"
                        case "transcription_transliteration" return "##### Transkription / Transliteration"
                        case "script" return "##### Script"
                        case "mistakes" return "##### Mistakes"
                        case "codicology" return "##### Codicology"
                        case "narratology" return "##### Narratology"
                        default return ()
                return
                    if ($p/preceding-sibling::tei:p[@n eq $n] and $p//tei:list) then
                        for $item in $p//tei:list/tei:item return
                            "* " || normalize-space($item) || local:add-newline()
                    else if ($p/preceding-sibling::tei:p[@n eq $n]) then
                        "* " || normalize-space($p) || local:add-newline()
                    else if($p//tei:list) then
                        (
                        local:add-empty-line(),
                        $title,
                        local:add-empty-line(),
                        for $item in $p//tei:list/tei:item return
                            "* " || normalize-space($item) || local:add-newline()
                        )
                    else
                        local:add-empty-line() || $title || local:add-empty-line() || "* " || normalize-space($p) || local:add-newline()

        let $abstract :=
                local:add-empty-line() || "#### Editor's statements" || local:add-empty-line() || string-join($statements)

        (: from here, we have to distinguish manuscripts and prints since their
           teiHeader is quite different. :)
        return
            if ($teiHeader//tei:monogr) then
                let $identifier := local:make-printIdentifier($teiHeader)
                let $history-info :=
                    "* Object type: printed edition" || local:add-newline() ||
                    "* Origin: " || $teiHeader//tei:monogr//tei:pubPlace/string() || local:add-newline() ||
                    "* Date of creation: " || $teiHeader//tei:monogr//tei:date/string()
                let $history :=
                    local:add-empty-line() || "#### History" || local:add-empty-line() || $history-info

                return
                    (
                        $title,
                        local:add-newline() || "view in [edition](" || $url || ")" || local:add-newline(),
                        $identifier,
                        $history,
                        $listBibl,
                        $abstract
                    )
            else
                let $identifier := local:make-msIdentifier($teiHeader)

                let $history := $teiHeader//tei:history
                let $country := $history//tei:country
                let $place-name := $history//tei:placeName
                let $origin-info :=
                    if (normalize-space($country) = "" and normalize-space($place-name) = "") then
                        "unknown"
                    else if (normalize-space($country) != "" and normalize-space($place-name) != "") then
                        $country || ", " || $place-name
                    else if ($country) then
                        $country
                    else
                        $place-name

                let $date-el := $history//tei:date
                let $date :=
                    if ($date-el = "unknown" and ($date-el/@notBefore or $date-el/@notAfter)) then
                        if ($date-el/@notBefore and $date-el/@notAfter) then
                            "unknown; not before " || $date-el/@notBefore || ", not after " || $date-el/@notAfter
                        else if ($date-el/@notBefore) then
                            "unknown; not before " || $date-el/@notBefore
                        else
                            "unknown; not after " || $date-el/@notAfter
                    else
                        $history//tei:date

                let $history-info :=
                    "* Object type: " || $history//tei:objectType || local:add-newline() ||
                    "* Origin: " || $origin-info || local:add-newline() ||
                    "* Date of creation: " || $date
                let $history :=
                    local:add-empty-line() || "#### History" || local:add-empty-line() || $history-info

                let $recording :=
                (
                    util:log-system-out($teiHeader),
                    if ($teiHeader//tei:recordingStmt) then
                        let $link := $teiHeader//tei:recordingStmt//tei:media/@url
                        return
                            local:add-empty-line() ||
                        "<audio controls=''><source src='" || $link || "' type='audio/mp3'></audio><p>In case your browser doesn't support this audio file use this <a href='" || $link || "'>link to the audio</a> instead.</p>"
                        || local:add-newline()
                    else
                        ()
                )

                return
                    (
                        $title,
                        local:add-newline() || "view in [edition](" || $url || ")" || local:add-newline(),
                        $recording,
                        $identifier,
                        $history,
                        $listBibl,
                        $abstract
                    )

};

declare function local:make-msIdentifier($teiHeader as element(tei:teiHeader))
as xs:string {
    let $msIdentifier := $teiHeader//tei:msIdentifier
    let $title := local:add-empty-line() || "#### Manuscript Identifier" ||
            local:add-empty-line()

    let $links :=
        for $url in $msIdentifier//tei:idno[starts-with(., "http")]
            return "([Digital Source](" || $url || "))"
    let $msIdentifier :=
            "* Identifier: " ||
            $msIdentifier/tei:institution/string() || " (" || $msIdentifier/tei:settlement/string() => normalize-space() || "), "
                || $msIdentifier/tei:idno/string() || " "
                || string-join($links, " ")

    let $further-metadata :=
        for $item in $teiHeader//tei:msItem/* return
            if ($item[self::tei:textLang]) then
                local:add-newline() || "* Language: " || $item/string()
            else if ($item[self::tei:respStmt[not(@xml:id eq "owner" or @xml:id eq "anonym")]]) then
                local:add-newline() || "* Responsible: " || $item/tei:persName || " (" || lower-case($item/tei:resp) || ")"
            else if ($item[self::tei:respStmt[@xml:id eq "owner"]]) then
                local:add-newline() || "* Owner(s): " || string-join($item/tei:persName, ", ")
            else
                ()
    let $msItem := string-join($further-metadata, "")

    let $result := $title || $msIdentifier || $msItem

    return
        $result
};

declare function local:make-printIdentifier($teiHeader as element(tei:teiHeader))
as xs:string {
    let $printIdentifier := $teiHeader//tei:monogr
    let $title := local:add-empty-line() || "#### Print Identifier" ||
            local:add-empty-line()
    let $links :=
        for $url in $printIdentifier//tei:idno[starts-with(., "http")]
            return "([Digital Source](" || $url || "))"
    let $identifier :=
            "* Bibliographic Information: " ||
            $printIdentifier/tei:editor/string() || ". " || $printIdentifier/tei:title[@type = "main"]/string() => normalize-space() || " ("
                || $printIdentifier/tei:title[@type = "alt"]/string() || "). "
                || $printIdentifier//tei:pubPlace/string() || " "
                || $printIdentifier//tei:date || ". "
                || $printIdentifier//tei:biblScope || ". "
                || $links

    let $further-metadata :=
        for $item in $teiHeader//tei:msItem/* return
            if ($item[self::tei:textLang]) then
                local:add-newline() || "* Language: " || $item/string()
            else if ($item[self::tei:respStmt]) then
                local:add-newline() || "* Responsible: " || $item/tei:persName || " (" || lower-case($item/tei:resp) || ")"
            else
                ()
    let $item := string-join($further-metadata, "")

    let $result := $title || $identifier || $item

    return
        $result
};

(:~
 : Provides a list of collation results
:)
declare function local:make-list($lang as xs:string) {

    let $sort := function($input) {
                    switch ($input)
                        case "first_narrative_section" return 1
                        case "second_narrative_section" return 2
                        case "third_narrative_section" return 3
                        case "sayings" return 4
                        case "parables" return 5
                        default return 9}

    let $resources := xmldb:get-child-resources("/db/data/collation-results/")
    let $stemmas :=
        $resources
        ! substring-before(., "_result")
        ! replace(., "_first_narrative_section|parables|sayings|second_narrative_section|_third_narrative_section", "")
        ! replace(., "_$", "")
        => sort()
        => distinct-values()
    for $i at $pos in $stemmas[starts-with(., $lang)]
    let $iResources := $resources[starts-with(., $i)]
    return
        element xhtml:div {
            element xhtml:h3 { "Stemma " || $pos },
            element xhtml:div {
                "items included: " || replace($i, "ara_|syc_|karshuni_", "")
            },
            element xhtml:ol {
                let $units := distinct-values(($iResources ! substring-after(., $i || "_") ! substring-before(., "_result") )) => sort((), $sort)
                for $iii in $units
                return
                    element xhtml:li {
                        ($iii => tokenize("_")) ! (upper-case(substring(., 1, 1)) || substring(., 2, 999)) => string-join(" "), (: ← camel-case function :)
                        element xhtml:ul {
                            for $file in $iResources[contains(., $iii)]
                            order by $file
                            return
                                element xhtml:li {
                                    element xhtml:a {
                                        attribute href { "/rest/collation-results/" || $file },
                                        $file => substring-after(".") => upper-case()
                                    }
                                }
                        }
                    }
            }
        }
};

declare function local:add-empty-line()
as xs:string {
    codepoints-to-string( (10, 10) )
};

declare function local:add-newline()
as xs:string{
    codepoints-to-string( (10) )
};

declare
    %rest:GET
    %rest:HEAD
    %rest:path("/website/collation")
    %output:method("xml")
function website:collation() {
    element xhtml:div {
        element xhtml:h2 {
            text { "Arabic" }
        },
        local:make-list("ara"),
        element xhtml:h2 {
            text { "Karshuni" }
        },
        local:make-list("karshuni"),
        element xhtml:h2 {
            text { "Syriac" }
        },
        local:make-list("syc")
    }
};

declare
    %rest:GET
    %rest:HEAD
    %rest:path("/website/motifs")
    %output:method("text")
function website:motifs() {
    util:eval(xs:anyURI("motifs-page.xq"))
};
