xquery version "3.0";
(:
    ART-DECOR® STANDARD COPYRIGHT AND LICENSE NOTE
    Copyright © ART-DECOR Expert Group and ART-DECOR Open Tools GmbH
    see https://docs.art-decor.org/copyright and https://docs.art-decor.org/licenses

    This file is part of the ART-DECOR® tools suite.
:)
(:
    XPath 3.0
        prefix-from-QName(xs:QName(replace((//element/@name)[1],'[\[/].*','')))
        namespace-uri-from-QName(xs:QName(replace((//element/@name)[1],'[\[/].*','')))
:)
import module namespace get         = "http://art-decor.org/ns/art-decor-settings" at "art-decor-settings.xqm";
import module namespace art         = "http://art-decor.org/ns/art" at "art-decor.xqm";
import module namespace decor       = "http://art-decor.org/ns/decor" at "../api/api-decor.xqm";
import module namespace adserver    = "http://art-decor.org/ns/art-decor-server" at "../api/api-server-settings.xqm";

(: decor project also contains @repository and @private markers. Those are ignored for now :)
let $decorProject           := if (request:exists()) then request:get-data()/project else ()
let $decorServicesURL       := adserver:getServerURLServices()
let $fhirServicesURL        := adserver:getServerURLFhirServices()

let $decorServicesURLlower  := lower-case($decorServicesURL)
let $fhirServicesURLlower   := lower-case($fhirServicesURL)

let $decor                  := art:getDecorByPrefix($decorProject/@prefix)

let $check                  := decor:checkAdminPermissionsP($decor)

let $newProject             :=
    <project    id="{$decorProject/@id}" 
                prefix="{$decorProject/@prefix}" 
                experimental="{$decorProject/@experimental}" 
                defaultLanguage="{$decorProject/@defaultLanguage}">
    {
        $decorProject/name,
        for $desc in $decorProject/desc
        return
            art:parseNode($desc)
        ,
        for $copyright in $decorProject/copyright[@*[not(.='')]]
        return
            <copyright>
            {
                $copyright/@*[not(.='')],
                for $node in $copyright/addrLine[.//text()[string-length(normalize-space()) gt 0]]
                return
                    <addrLine>{$node/@*[not(. = '')], $node/node()}</addrLine>
            }
            </copyright>
        ,
        $decorProject/license,
        for $author in $decorProject/author
        let $storedAuthor := $decor/project/author[@id = $author/@id]
        return
           <author>
           {
               $author/(@* except (@dbactive | @expirationDate))[not(.='')],
               if ($author[@active = 'false']) then
                    if ($storedAuthor[@active = 'false']) then
                        (: keep existing expirationDate if present, because apparently he already was inactive. :)
                        ($storedAuthor/@expirationDate)[1]
                    else (
                        (: generate new expirationDate, because apparently he was just made inactive. :)
                        attribute expirationDate {substring(string(current-dateTime()), 1, 19)}
                    )
               else (),
               $author/node()
           }
           </author>
        ,
        for $reference in $decorProject/reference[@url[not(normalize-space(.)='')] | @logo[not(normalize-space(.)='')]]
        return
            <reference>
            {
                if ($reference/@url[not(normalize-space(.) = '')]) then
                    attribute url {$reference/normalize-space(@url)}
                else ()
                ,
                $reference/@logo[not(normalize-space(.) = '')]
            }
            </reference>
        ,
        for $restURI in $decorProject/restURI[not(.='')]
        return
            <restURI>{$restURI/@for, $restURI/@format, $restURI/node()}</restURI>
        ,
        $decorProject/defaultElementNamespace,
        $decorProject/contact,
        for $bbrs in ($decorProject/buildingBlockRepository[@url castable as xs:anyURI][not(@format[not(. = 'decor')])][@ident[not(. = '')]][not(@url = $decorServicesURL and @ident = $decorProject/@prefix)] |
                      $decorProject/buildingBlockRepository[@url castable as xs:anyURI][@format[not(. = 'decor')]][not(@url = ($decorServicesURL, $fhirServicesURL))])
        let $lurl       := lower-case($bbrs/@url)
        let $url        := 
            (: prevent mismatches in casing :)
            if ($lurl = $decorServicesURLlower) then $decorServicesURL else 
            (: prevent mismatches in casing :)
            if ($lurl = $fhirServicesURLlower) then $fhirServicesURL else
            (: prevent mismatches in http versus https :)
            if (substring-after($lurl, ':') = substring-after($decorServicesURLlower, ':')) then $decorServicesURL else
            (: prevent mismatches in http versus https :)
            if (substring-after($lurl, ':') = substring-after($fhirServicesURLlower, ':')) then $fhirServicesURL else (
                $bbrs/@url
            )
        let $ident      := $bbrs/@ident[not(. = '')]
        let $licenseKey := $bbrs/@licenseKey[not(. = '')]
        let $format     := $bbrs/@format[not(. = ('', 'decor'))]
        group by $url, $ident, $licenseKey
        return
            <buildingBlockRepository>{if (string-length($url) gt 0) then attribute url {$url} else (), $ident, $licenseKey, $format}</buildingBlockRepository>
        ,
        (:for $versionInfo in $decorProject/(version|release)
        return
            element {name($versionInfo)} {
                $versionInfo/(@*[string-length()>0] except @publicationstatus),
                for $desc in $versionInfo/(desc|note)
                return 
                    art:parseNode($desc)
            }:)
        $get:colDecorData//project[@id=$decorProject/@id]/(version|release)
    }
    </project>

let $update         := update replace $decor/project with $newProject

(:suppose we have ns elements in the project data, then slap these onto the decor element overwriting any existing declarations:)
let $update-ns      := if ($decorProject[@id][ns]) then (art:setDecorNamespaces($decorProject/@id, $decorProject/ns)) else ()

let $update         := decor:setIsRepositoryP($decor, $decorProject/@repository = 'true')
let $update         := decor:setIsPrivateP($decor, $decorProject/@private = 'true')

return
<data-safe>true</data-safe>