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.
:)
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 adserver        = "http://art-decor.org/ns/art-decor-server" at "../api/api-server-settings.xqm";

declare namespace http                  = "http://expath.org/ns/http-client";
declare variable $strDecorServicesURL         := adserver:getServerURLServices();

let $searchString               := if (request:exists()) then (request:get-parameter('searchString',())) else ('lich')
let $projectPrefix              := if (request:exists()) then (request:get-parameter('project',())) else ('demo1-')
(:normally we only want repository codeSystems, but when we are looking for a prototype, we want to include codeSystems from our own project:)
let $includeLocal               := if (request:exists()) then (request:get-parameter('includelocal','false')='true') else (true())

let $decor                      := $get:colDecorData//decor[project/@prefix=$projectPrefix]

let $buildingBlockRepositories  := 
    if ($includeLocal) then (
        $decor/project/buildingBlockRepository[empty(@format)] | 
        $decor/project/buildingBlockRepository[@format='decor'] | 
        <buildingBlockRepository url="{adserver:getServerURLServices()}" ident="{$projectPrefix}" format="decor"/>
    )
    else (
        $decor/project/buildingBlockRepository[empty(@format)] | 
        $decor/project/buildingBlockRepository[@format='decor']
    )
let $luceneQuery                := 
    <query>
        <bool>
        {
            for $term in tokenize(lower-case(normalize-space($searchString)),'\s')
            return
                <wildcard occur="must">{concat('*', $term, '*')}</wildcard>
        }
        </bool>
    </query>
let $luceneOptions              := art:getSimpleLuceneOptions()

let $result                     := 
    for $repository in $buildingBlockRepositories
    let $repourl                := $repository/@url
    let $repoident              := $repository/@ident
    let $cachedProject          := 
        if ($repourl = $strDecorServicesURL) then
            art:getDecorByPrefix($repoident)
        else (
            $get:colDecorCache//cacheme[@bbrurl = $repourl][@bbrident = $repoident]
        )
    return
    <repositoryList url="{$repourl}" ident="{$repoident}">
    {
        if ($cachedProject) then (
            attribute cachedProject {'true'},
            $cachedProject//codeSystem[@id = $searchString] | 
            $cachedProject//codeSystem[@id][ft:query(@name, $luceneQuery, $luceneOptions)] |
            $cachedProject//codeSystem[@id][ft:query(@displayName, $luceneQuery, $luceneOptions)]
        )
        else (
            attribute cachedProject {'false'},
            let $service-uri    := xs:anyURI(concat($repourl,'/SearchCodeSystem?searchString=',encode-for-uri($searchString),'&amp;prefix=',$repoident))
            let $requestHeaders := 
                <http:request method="GET" href="{$service-uri}">
                    <http:header name="Content-Type" value="text/xml"/>
                    <http:header name="Cache-Control" value="no-cache"/>
                    <http:header name="Max-Forwards" value="1"/>
                </http:request>
            let $server-response        := http:send-request($requestHeaders)
            
            return $server-response[2]//codeSystem[@id]
        )
        
    }
    </repositoryList>

return
<result count="{count($result//codeSystem)}" search="{$searchString}" includelocal="{$includeLocal}">
{
    for $objects in $result//codeSystem
    let $id             := $objects/(@id|@ref)
    group by $id
    order by $objects[1]/@name
    return
        <codeSystem uuid="{util:uuid()}" id="{$id}">
        {
            if (count($decor/terminology/codeSystem[@ref=$id]) > 0) then attribute alreadyrefed {'true'} else (),
            for $object in $objects
            order by $object/@effectiveDate descending
            return
                <codeSystem uuid="{util:uuid()}">
                {
                    $object/ancestor::repositoryList/@url,
                    $object/ancestor::repositoryList/@ident,
                    $object/(@* except (@uuid|@url|@ident))
                }
                </codeSystem>
        }
        </codeSystem>
}
</result>