<?xml version="1.0" encoding="UTF-8"?>
<actions>

<meta>
  <description>Template für das Primo-System</description>

  <variable name="baseurl"><description>volle Serverurl</description></variable>

  <variable name="login-url-1"><description>Login-URL für Interne (Studenten)</description></variable>
  <variable name="login-url-2"><description>Login-URL für Externe</description></variable>
  
  <variable name="institute"><description>(veraltet) Institutsid der Bücherei im Primosystem</description></variable>
  
</meta>


<action id="connect">
    <s>declare function local:raise($err){
         string($err) ! (if (matches(., "Anmeldung|login credentials|Passwort|The username you entered cannot be identified|Wrong username or password|Ausweisnummer|Login-Angaben|Benutzername|Anmelde")) then vl:raise-login(.)
         else vl:raise(.))
       };
   $use-rest-api := matches($baseurl, '/primo-explore|/discovery/')
  </s>
  <if test="$use-rest-api">
    <s>
    vid := extract($baseurl, "vid=([^"||$amp||"]+)", 1),
    if (contains($baseurl, "/primo-explore")) then (
      $api-mode := "explore",
      $server := substring-before($baseurl, "/primo-explore"),
      $configuration-url := x"{$server}/primo_library/libweb/webservices/rest/v1/configuration/{$vid}",
      $search-url := x"{$server}/primo_library/libweb/webservices/rest/primo-explore/v1/pnxs",
      $delivery-url := $search-url || "/delivery",
      $account-url := $server || "/primo-explore/account?vid=" || uri-encode($vid),
      $external-login-url := $server || "/primo_library/libweb/primoExploreLogin",
      $account-api-url := $server || "/primo_library/libweb/webservices/rest/v1/myaccount/",
      $renew-url := $account-api-url || "/renew_loan"
    ) else (
      $api-mode := "discovery",
      $server := substring-before($baseurl, "/discovery/"),
      $pub-url := $server || "/primaws/rest/pub",
      $configuration-url := x"{$pub-url}/configuration/vid/{$vid}",
      $search-url := $pub-url || "/pnxs",
      $delivery-url := $pub-url || "/delivery",
      $account-url := $server || "/discovery/account?vid=" || uri-encode($vid),
      $external-login-url := $server || "/primaws/suprimaExtLogin",
      $account-api-url := $server || "/primaws/rest/priv/myaccount/",
      $renew-url := $account-api-url || "/renew_loans"
    )
    </s>
    <json url="{$configuration-url}"/>
    <s>
    xquery version "3.0-videlibri";
    institute := ( $json.primo-view.institution.institution-code, $json.beacon.alternative-institution-code, get("institute"), $vid )[.][1],
    authentication := $json.authentication,
    authentication-header := "",
    search-scopes := $json.primo-view.scopes()
    </s>
  </if>
</action>

<action id="internal-get-jwt">
  <if test="not($authentication-header)">
    <s>
    if ($api-mode = "explore") then (          
      $guestJWT-url := x"{$server}/primo_library/libweb/webservices/rest/v1/guestJwt/{uri-encode($institute)}",
      $loginJWT-url := $server || "/primo_library/libweb/webservices/rest/v1/" || "loginJwtCache/"
    ) else (
      $guestJWT-url := x"{$server}/primaws/rest/pub/institution/{uri-encode($institute)}/guestJwt",
      $loginJWT-url := $server || "/primaws/rest/pub/" || "loginJwtCache/" (:??????:)
    ),
    $guestJWT-url := x"{$guestJWT-url}?isGuest=true&lang=de_DE&targetUrl={uri-encode($account-url)}&viewId={uri-encode($vid)}",
    temp := if (contains($url, "loginId=")) then
              $loginJWT-url ||  extract($url, "loginId=([^&amp;]+)", 1) || "?vid=" || uri-encode($vid)
            else $guestJWT-url
    </s>
    <json url="{$temp}"/>
    <s>let $j := $json where $j return
       authentication-header := if ($j instance of xs:string) then $j
                                else if ($j("jwtData")) then $j("jwtData")
                                else ()
    </s>
  </if>
</action>

<action id="update-all">
  <s>i := 1, datasend := false()</s>
  <if test="$use-rest-api"><s>
    $request := let $auth := $authentication((if ($type ge 1) then $type else 1))
                let $targeturl := $account-url
                return if ($auth.authentication-system = "ALMA") then
                  (: also use "$external-login-url" for internal login. there is no internal/external login? check configuration backend_system for url? :)
                  request-combine( 
                     {"url": $external-login-url, "method": "POST"},
                     {"authenticationProfile": $auth.profile-name,
                      "institution": $institute,
                      "password": $password,
                      "targetUrl": $targeturl,
                      "username": $username,
                      "view": $vid}
                   )
                 else  $external-login-url || x"?institution={uri-encode($institute)}&target-url={uri-encode($targeturl)}&authenticationProfile={uri-encode($auth.profile-name)}&idpCode={uri-encode($auth.profile-name)}&auth={uri-encode($auth.authentication-system)}&isSilent=false"
                 (:old primo-explore one does not have idpCode= parameter:)
  </s></if>
  <else>
    <s>$request := get("login-url-" || (if ($type ge 1) then $type else 1), ()),
       if ($request) then () else $request := get("login-url")
    </s>
  </else>
  
  <!-- follow links till we reach the login page -->
  <loop test="$i < 10">  
    <try>
      <page url="{$request}"/>
      <catch errors="http:401">
      <s>vl:raise-login("Fehlercode 401 (falsches Passwort?)")</s>
      </catch>
    </try>
    <if test="$use-rest-api and starts-with($raw, '{')">
      <s>let $j := json($raw) where $j("jwtData") return (
          $i := 10000,
          authentication-header := $j("jwtData")
        )</s>
    </if>
    <if test="$i < 10">
      <pattern><t:switch prioritized="true">
        <html t:test="$use-rest-api and $datasend" id="primoExploreRoot">{i:=10000}</html>
        <div   class="EXLPRMLoginCardContentError">{local:raise(.)}</div>
        <div  t:test="$datasend" class="error">{local:raise(.)}</div>
        <span t:test="$datasend" class="login-error">{local:raise(.)}</span>
        <font t:test="$datasend" color="red">{local:raise(.)}<!--htw--></font>
        <p t:test="$datasend" style="color:red;">{local:raise(.)}<!--fu--></p>
        <p t:test="$datasend" class="error">{local:raise(.)}<!--hu intern--></p>
        <p t:test="$datasend" class="text-danger">{local:raise(.)}<!--hu intern new--></p>
        <div t:test="$datasend" class="alert-danger alert-dismissible" role="alert">{local:raise(.)}<!--rwth--></div>
        <p t:test="$datasend" class="output-message output--error">{local:raise(.)}<!--uni münster,mannheim--></p>
        <p class="form-element form-error">{local:raise(.)}<!--uni bochum--></p>
                        
        <form>
          <input name="username"/>
          {request := form(., {"username": $username, "password": $password} ), datasend := true()}
        </form>
        <form>
          <input name="j_username"/>
          {request := form(., ({"j_username": $username, "j_password": $password}, .//button[@name = "_eventId_proceed"] )), datasend := true()}
        </form>
        <html t:test="$use-rest-api" id="primoExploreRoot">{i:=10000}<!--logged in???--></html>
        <DIV class="EXLMyAccountContainer" id="exlidMyAccountContainer"> <DIV class="EXLMyAccountMainContainer"/> 
          {i := 10000}<!--logged in-->
        </DIV>
        <a t:condition="contains(@href, 'myAccountMenu.do')">{$request}</a>
        <form t:condition=" .//@name = ('_eventId_proceed', 'SAMLResponse', 'RelayState') ">
          { let $buttons := ((.//input, .//button)[@type=("submit", "image")], .//button, .//input[@type="button"])
            let $proceed := $buttons[@name = "_eventId_proceed"]
            return
              $request := form(., ($proceed, $buttons)[1] )
          }
        </form>
        <meta http-equiv="refresh">{$request}</meta>
        <a t:condition="contains(@href, '?')">{$request}</a>
        <form>{$request := form(., ((.//input, .//button)[@type=("submit", "image")], .//button, .//input[@type="button"])[1] )}</form>
        <a>{$request}</a>
      </t:switch></pattern>
    </if>
    <s>$i := $i + 1</s>    
  </loop>
    
  <if test="$i < 100">
  <s>vl:raise-internal("Zuviele Weiterleitungen beim Login. Aktuelle Seite: " || base-uri() || substring(join(//body), 1, 1000))</s>
  </if>
    
  <if test="$use-rest-api">
    <call action="primo-explore-update-all"/>
  </if>
  <else>  
    <s>videlibri:delete-current-books()</s>
    <pattern href="list"/>

    <page url="{$orderPage}"/>
    <pattern href="list"/>
  </else>
  
<!--  <error templateFile="loginError"/>-->
</action>

<action id="primo-explore-update-all">
  <call action="internal-get-jwt"/>
  <s>videlibri:delete-current-books()</s>
  <json url="{$account-api-url}/loans?type=active">
    <header>Accept: application/json,*/*</header>
    <header>Authorization: Bearer {$authentication-header}</header>
  </json>
  <s>
  for $loan in $json.data.loans.loan() return
    $book := $loan!{
      "category": itemcategoryname,
      "year": year,
      "author": author,
      "id": callnumber,
      "issueDate"?: loandate[.]!parse-date(., "yyyymmdd"),
      "title": title,
      "libraryBranch": mainlocationname,
      "_itemid": itemid,
      "_loanid": loanid,
      "dueDate"?: duedate[.]!parse-date(., "yyyymmdd"),
      "status": loanstatus,
      "statusId": if (renew eq "Y") then "curious" else "critical",
      "barcode": itembarcode
    }
  </s>
  <json url="{$account-api-url}/requests?vid={$vid}">
    <header>Accept: application/json,*/*</header>
    <header>Authorization: Bearer {$authentication-header}</header>
  </json>
  <s>
    let $data := $json.data return
    for $type in ("hold", "request", "ill")
    let $types := $type || "s"
    for $loan in $data($types)($type)() return
      $book := $loan!{
        "cancelable": cancel eq "Y",
        "libraryBranch": pickuplocationname,
        "author": author,
        "title": title,
        "status": holdstatus,
        "statusId": if (available eq "Y") then "provided" else "ordered",
        "_requestid": requestid,
        "_request_type": $types,
        "issueDate"?: requestdate[.]!parse-date(., "yyyymmdd")
      }
  </s>
</action>

<!--
<action id="update-single">
  <page url="{$book.detailUrl}">
  <template>
    <DIV class="EXLMyAccountContainer" id="exlidMyAccountContainer">
      <template:meta default-text-matching="regex"/>
      <DIV class="EXLMyAccountMainContainer">
        <H1>Details of loan:|Details der Ausleihe:</H1>
        <TABLE class="EXLMyAccountTableDetails">
          <TR><TH>Year:|Jahr:</TH><TD>{book.year:=.}</TD></TR>
          <TR><TH>Call number:|Signatur:</TH><TD>{book.id:=.}</TD></TR>
          <TR t:optional="true"><TH>Loan date:|Ausleihdatum:</TH><TD>{book.issueData:=parse-date(., "dd.mm.yyyy|dd/mm/yyyy")}</TD></TR>
        </TABLE>
      </DIV>
    </DIV>
  </template>
  </page> 
</action>
-->

<!-- renew all: https://tu-berlin.hosted.exlibrisgroup.com/primo_library/libweb/webservices/rest/v1/myaccount/renew_all_loans -->
<action id="renew-list">
  <if test="$use-rest-api">
    <loop var="b" list="$renew-books">
      <page url="{$renew-url}">
        <header>Content-Type: application/json; charset=utf-8</header>
        <header>Accept: application/json,*/*</header>
        <header>Authorization: Bearer {$authentication-header}</header>
        <method>POST</method>
        <post>{{"id": {$b._loanid} }}</post>
      </page>
    </loop>
    <call action="primo-explore-update-all"/>
  </if>
  <else>
    <loop var="b" list="$renew-books">
      <page url="{$b._renewUrl}">
      </page>
    </loop>
    <call action="update-all"/>
  </else>
</action>

<action id="cancel-list">
  <if test="$use-rest-api">
    <loop var="b" list="$cancel-books">
      <page url="{$account-api-url}/cancel_requests">
        <header>Content-Type: application/json; charset=utf-8</header>
        <header>Accept: application/json,*/*</header>
        <header>Authorization: Bearer {$authentication-header}</header>
        <method>POST</method>
        <post>{{"request_id": {$b._requestid}, "request_type": {$b._request_type} }}</post>
      </page>
    </loop>
    <call action="primo-explore-update-all"/>
  </if>
  <else>
    <loop var="b" list="$cancel-books">
      <page url="{$b._cancelUrl}">
      </page>
    </loop>
    <call action="update-all"/>
  </else>
</action>


<action id="search-connect">
  <call action="connect"/>
  <if test="$use-rest-api">
  <!-- or https://tu-berlin.hosted.exlibrisgroup.com/primo_library/libweb/webservices/rest/v1/configuration/TUB/scopes -->
    <s>search-params := (  "title", "author", "free", "keywords", "year", "isbn", 
                           {"name": "libraryBranch", "options": $search-scopes ! scope-id } 
                        )
    </s>
  </if>
</action>

<action id="search">
  <if test="$use-rest-api">
    <variable name="search-keys">{"author": "creator", "title": "title", "free": "any", "keywords": "sub", "isbn": "isbn", "year": "cdate"}</variable>
    <s>
    all-raw-docs := (),
    offset := 0,
    search-branch-id := (for $s at $i in $search-scopes where $s.scope-id eq $book.libraryBranch return $i, 1)[1],
    encoded-scope := uri-encode($search-scopes[$search-branch-id].scope-id),
    encoded-tab := uri-encode($search-scopes[$search-branch-id].tab),
    encoded-query := uri-encode(join(for $key in jn:keys($book) where boolean($book($key)) and exists($search-keys($key)) return
      x"{$search-keys($key)},contains,{$book($key)},AND", ";"
    ))
    </s>
    <s>
    declare function local:encode-request($offset, $limit){
     join((
      "blendFacetsSeparately=false",
      "getMore=0",
      "inst=" || uri-encode($institute),
      "lang=de_DE",
      "limit=" || $limit,
      "offset=" || $offset,
      "mode=advanced",
      "newspapersActive=false",
      "newspapersSearch=false",
      "pcAvailability=true",
      "q=" || $encoded-query,
      "qExclude=",
      "qInclude=",
      "rtaLinks=true",
      "scope=" || $encoded-scope,
      "skipDelivery=Y",
      "sort=rank",
      "tab=" || $encoded-tab,
      "vid=" || uri-encode($vid)
     ), $amp)
    };()
    </s>
    <call action="internal-get-jwt"/>
    <call action="search-next-page"/>
    </if>
  <else>
    <variable name="search-keys">{"author": "creator", "title": "title", "keywords": "subject", "isbn": "isbn", "year": "cdate"}</variable>
  
    <s>redirect:=()</s>
  
    <page url="{$baseurl}search.do?mode=Advanced&amp;fromLogin=true&amp;vid={$institute}" templateFile="searchStart"/>
    
    <page url="{$redirect}" templateFile="searchStart"/>
  
    <page url="{$form}" templateFile="searchList"/>
    
    <page url="{$form}" test="$waiting" templateFile="searchList"/>
  </else>
</action>

<action id="search-next-page">
  <if test="$use-rest-api">
  <!-- /primo_library/libweb/webservices/rest/primo-explore/v1/pnxs 
   or /primo_library/libweb/webservices/rest/primo-explore/v1/pnxs/delivery
  -->
    <json url="{$search-url}?{local:encode-request($offset, 10)}">
      <header>Accept: application/json,*/*</header>
      <header>Authorization: Bearer {$authentication-header}</header>
    </json>
<!-- https://knowledge.exlibrisgroup.com/Primo/Product_Documentation/Technical_Guide/010The_PNX_Record/010PNX_Record_Sections -->
    <s>
        search-result-count := $json.info.total,
        $all-raw-docs[] := $json.docs(),
        for $d at $i in $json.docs() return (
          book := $d.pnx.display ! {
            "title": join((title)()),
            "publisher": join((publisher)()),
            "author": let $a := join((creator, creatorcontrib)[1](), "; ")
                      return if (contains($a, "$$Q")) then substring-before($a, "$$Q") 
                      else $a,
            "year": join((creationdate)()),
            "statusId" ?: switch ((availpnx)()[1])
              case "available" return
                if (contains(replace((availinstitution)()[1], "unavailable", ""), "available")) then "available" else ()
              case "unavailable" return "lend"
              default return (),
            "Schlagwörter!" ?: join((subject)(), ", ")[.],
            "Beschreibung!" ?: join((description)(), ", ")[.],
            "Format!" ?: (format)()[.],
            "Sprache!" ?: (language)()[.],
            "isbn" ?: replace(join((identifier)()), "[$][$].", " "),
            "_offset": $offset + $i 
            (:,
            "_@rta_link": $d("@rta_link"),
            "_@id": $d("@id"):)
          }
        ),
        offset := $offset + 10,
        search-next-page-available := $offset lt $search-result-count
    </s>
  </if>
  <else>
    <page url="{$search-next}" templateFile="searchList">
    </page>
  </else>
</action>

<action id="search-details">
  <if test="$use-rest-api">
  <!--  <page url="{$book('_@rta_link')}">
      <header>Accept: application/json,*/*</header>
      <header>Authorization: Bearer {$authentication-header}</header>
    </page>--> 
    <s>index := xs:integer($book._offset)</s>
    <json url="{$delivery-url}?{local:encode-request($index - 1, 1)}">
      <header>Accept: application/json,*/*</header>
      <header>Authorization: Bearer {$authentication-header}</header>
      <header>Content-Type: application/json; charset=utf-8</header>
      <post>{{"records": [ {serialize-json($all-raw-docs[$index]  )} ] }}</post>
    </json>
    <s>$book.holdings := $json.docs(1).delivery.holding() ! {
          "id": callNumber,
          "statusId": switch (availabilityStatus)
            case "available" return "available" 
            case "unavailable" return "lend"
            default return "unknown"
          ,
          "libraryLocation": subLocation,
          "libraryBranch": libraryCode,
          "orderable": false()
       }
    </s>
  </if>
  <else>
    <page url="{$book.home-url}" templateFile="searchDetails"/>
    <page url="{$book.locations-url}" templateFile="searchDetailsLocations"/>
  </else>
</action>

<action id="catalogue">
  <variable name="url" value="{$baseurl}"/>
</action>

</actions>
