xquery version "3.1";

(:~
 : This module provides the motifs for Ahiqar.
 :
 : @author Michelle Weidling
 : :)

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

declare namespace motifsns="http://ahiqar.uni-goettingen.de/ns/motifs";
declare namespace tei="http://www.tei-c.org/ns/1.0";

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

declare function motifs:get-motifs($pages as element(page)+,
    $teixml-uri as xs:string)
as map(*)* {
    let $pageN := string(($pages//tei:pb/@n)[1])
    let $meDoc := doc($commons:tmp || $teixml-uri || ".me.xml")
    let $motifs :=
        for $page in $pages return
            motifs:get-relevant-motifs-md5($page/tei:TEI, $pageN, $meDoc)
    for $motifMd5 in $motifs
        let $motifStart := $meDoc//motifsns:*[@type eq "start"][@md5 eq $motifMd5]
        let $motifEnd := $meDoc//motifsns:*[@type eq "end"][@md5 eq $motifMd5]
        let $motif := ($motifStart, $motifEnd)
        return
            if($motif) then motifs:make-map($motif, $teixml-uri, $pageN) else ()
};

declare function motifs:get-relevant-motifs-md5($page as element(tei:TEI),
    $pageN as xs:string,
    $meDoc as document-node())
as xs:string* {(
    (: all motifs starting and/or ending within this fragment :)
    $page//motifsns:*[@md5]/string(@md5)
    => distinct-values(),

    (: motifs spanning over page :)
    let $pb := ($meDoc//tei:text[@xml:lang = ("ara", "syc")]//tei:pb[@n eq $pageN])[1]
    let $nextPb := $pb/following::tei:pb[1][parent::tei:body eq $pb/parent::tei:body]
    let $motifs-starting-before := $pb/preceding::motifsns:*[@type eq "start"]/@md5
    let $motifs-ending-after    := $nextPb/following::motifsns:*[@type eq "end"]/@md5

    let $count-starting := count($motifs-starting-before)
    let $count-ending   := count($motifs-ending-after)
    return
        if($count-starting lt $count-ending) then
            $motifs-starting-before[. = $motifs-ending-after]
        else
            $motifs-ending-after[. = $motifs-starting-before]
    )
};

declare function motifs:make-map($motif as element()+,
    $teixml-uri as xs:string,
    $pageN as xs:string)
as map(*) {
    map {
        "id": $commons:anno-ns || "/" || $teixml-uri || "/annotation-" || $motif[1]/string(@id),
        "type": "Annotation",
        "body": motifs:get-body-object($motif[1]),
        "target": array {
                map {
                "source": "PLACEHOLDER → TARGET CONTENT HTML IRI",
                "selector": map {
                    "type": "CssSelector",
                    "value": local:make-selectors($motif, $pageN)
                }
            }
        }
    }
};

declare function motifs:get-body-object($motif as element())
as map(*) {
    map {
        "type": "TextualBody",
        "value": motifs:get-body-value($motif),
        "format": "text/plain",
        "x-content-type": "Motif"
    }
};

declare function motifs:get-body-value($motif as element())
as xs:string {
    switch ($motif/local-name())
        case"self_examination_reflection" return "Self-examination/reflection"
        case"social_contacts_no_family" return "Social contacts (no family)"
        case"caution_against_powerful" return "Caution against the powerful"
        case"meekness_showing_respect" return "Meekness/showing respect"
        case"social_contacts_family" return "Social contacts (family)"
        case"loyal_obligation_gods" return "Loyal obligation (gods)"
        case"disciplining_of_sons" return "Disciplining of the sons"
        case"successful_courtier" return "Successful courtier"
        case"wise_fool_sinful" return "Wise fool sinful"
        case"royal_challenges" return "Royal challenged"
        case"treatment_slaves" return "Treatment of slaves"
        case"adherence_wisdom" return "Adherence wisdom"
        case"richness_poverty" return "Richness/poverty"
        case"keeping_secrets" return "Keeping secrets"
        case"parable_animals" return "Parable (animals)"
        case"temptress_women" return "Temptress women"
        case"obeying_parents" return "Obeying parents"
        case"parable_plants" return "Parable (plants)"
        case"burden_debt" return "Burden (debt)"
        case"truth_lying" return "Truth/Lying"
        case"discernment" return "Discernment"
        case"air_castle" return "Air castle"
        case"image_king" return "Image of the king"
        case"intrigue" return "Intrigue"
        case"quarrel" return "Quarrel"
        case"good_name" return "Good name"
        default return "Unknown motif: " || $motif/local-name() || "."
};

declare function motifs:get-target-information($teixml-uri as xs:string,
    $motif as element())
as map(*) {
    map {
        "id": $commons:anno-ns || "/" || $teixml-uri || "/"|| $motif/@id,
        "format": "text/xml",
        "language": $motif/ancestor-or-self::*[@xml:lang][1]/@xml:lang/string()
    }
};


declare function local:make-selectors($motif as element()+,
    $pageN as xs:string)
as xs:string {
    let $motif-start :=
        if ($motif[@type eq "start"] and ($motif[@type eq "start"]/preceding::tei:pb[1]/string(@n) eq $pageN)) then
            $motif[@type eq "start"]
        else
            ()
    (: in some cases we have motif annotations in the data that have an ending processing instruction, but not
    a matching starting one. This can happen during revision or due to copy and paste errors.
    This leads to several ending motifs being detected for one starting motif during the creation of
    the motif expansion intermediate format.
    To mitigate this effect, we now consider only the first ending motif. :)
    let $motif-end :=
        if ($motif[@type eq "end"] and ($motif[@type eq "end"][1]/preceding::tei:pb[1]/string(@n) eq $pageN)) then
            $motif[@type eq "end"][1]
        else
            ()
    let $word-ids :=
        if ($motif-start and $motif-end) then
            $motif-start/following::tei:w[. << $motif-end]/string(@xml:id)
        (: for motifs spanning multiple pages :)
        else if ($motif-start) then
            $motif-start/following::tei:w[. << $motif-start/following::tei:pb[1]]/string(@xml:id)
        else
            $motif-end/preceding::tei:pb[1]/following::tei:w[. << $motif-end]/string(@xml:id)
    let $id-selectors :=
        for $id in $word-ids return
            "#" || $id
    return
        string-join($id-selectors, ",")
};
