xquery version "1.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.
:)
(: PATH MUST BE ABSOLUTE BECAUSE THE CONTEXT IS THE APPLY-RULES STYLESHEET:)
import module namespace get         = "http://art-decor.org/ns/art-decor-settings" at "xmldb:exist:///db/apps/art/modules/art-decor-settings.xqm";
(: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 "xmldb:exist:///db/apps/art/modules/art-decor.xqm";
import module namespace gg          = "http://art-decor.org/ns/decor/governancegroups" at "xmldb:exist:///db/apps/art/api/api-decor-governancegroups.xqm";

declare namespace request       = "http://exist-db.org/xquery/request";
declare namespace response      = "http://exist-db.org/xquery/response";
declare namespace xhtml         = "http://www.w3.org/1999/xhtml";

declare %private function local:getLanguageNodes($textNodes as element()*, $languages as item()*) as element()* {
    (: process whatever is in the set :)
    $textNodes
    ,
    (: add any missing languages, compared to project-languages and art-languages on this server :)
    if ($textNodes) then (
        let $language-set   := 
            for $lang in distinct-values($languages)
            return if ($textNodes[@language = $lang]) then () else ($lang)
        
        for $lang in $language-set
        let $matchNode      := $textNodes[starts-with(@language, substring($lang,1,2))]
        let $matchNode      := if ($matchNode) then $matchNode else $textNodes[@language='en-US']
        let $matchNode      := if ($matchNode) then $matchNode else $textNodes[1]
        return
            element {name($textNodes[1])}
            {
                attribute language {$lang}
                ,
                $matchNode[1]/node()
            }
    )
    else ()
};

let $ggroups        := collection($get:strArtData)//governance
let $art-languages  := art:getArtLanguages()
let $gglinks        := gg:getLinkedGovernanceGroups(())
(: map with governance group id as key and 0..* project ids as contents :)
let $ggmap          := map:merge(for $gg in $ggroups/group return map:entry($gg/@id, $gglinks/partOf[@ref = $gg/@id]/../@ref))
(: map with project id as key and 0..* governance group ids as contents :)
let $pggmap         := map:merge(for $gg in $gglinks return map:entry($gg/@ref, $gg/partOf/@ref))

(: get governance groups and their projects first :)
let $governancegroups       :=
    for $gg in $ggroups/group
    let $defaultname            := $gg/name[@language = $gg/@defaultLanguage]
    let $defaultname            := if ($defaultname) then $defaultname[1] else ($gg/name)[1]
    let $linkedprojects         := $get:colDecorData/decor/project[@id = map:get($ggmap, $gg/@id)][not(ancestor::decor[@private = 'true'])]
    order by lower-case($defaultname)
    return
        if (count($linkedprojects)>0) then
            <governancegroup id="{$gg/@id}" defaultLanguage="{$gg/@defaultLanguage}">
            {
                local:getLanguageNodes($gg/name, ($gg/name/@language, $art-languages))
                ,
                for $project in $linkedprojects
                let $defaultname := $project/name[@language = $project/@defaultLanguage]
                let $defaultname := if ($defaultname) then ($defaultname) else ($project/name[1])
                order by lower-case($defaultname)
                return
                   <project>
                   {
                       $project/@id, $project/@prefix, $project/@defaultLanguage,
                       attribute repository {$project/parent::decor/@repository='true'},
                       attribute experimental {$project/@experimental='true'}
                       ,
                       local:getLanguageNodes($project/name, ($project/name/@language, $project/@defaultLanguage, $art-languages))
                    }
                    </project>
           }
           </governancegroup>
        else ()


(: get other projects, skip those who are already part of a governance group that actually exists :)
let $normalprojects :=
    for $project in $get:colDecorData//decor/project[not(ancestor::decor[@private='true'])]
    let $gglinks            := gg:getLinkedGovernanceGroups($project/@id)
    let $ggexists           := for $ggp in $gglinks/partOf/@ref where $ggp = map:keys($ggmap) return $ggp
    let $defaultname        := $project/name[@language = $project/@defaultLanguage]
    let $defaultname        := if ($defaultname) then $defaultname[1] else ($project/name)[1]
    order by lower-case($defaultname)
    return
        if ($ggexists) then () else (
            <project>
            {
                $project/@id, $project/@prefix, $project/@defaultLanguage,
                attribute repository {$project/parent::decor/@repository = 'true'},
                attribute experimental {$project/@experimental = 'true'}
                ,
                local:getLanguageNodes($project/name, ($project/name/@language, $project/@defaultLanguage, $art-languages))
            }
            </project>
        )
return
    <projects>
    {
        $normalprojects, $governancegroups
    }
    </projects>