<![CDATA[
  /*
      $Id$

      File:           refresh_webhooks.wsf

      Calling:        cscript ..\..\..\utils\exchange\refresh_webhooks.wsf
      Context:        Scheduled task
      Description:    Maakt voor alle res_ruimte's een webhook waar we notificaties op gaan krijgen
      Note:           De code veronderstelt (nog) dat de current folder een cust/xxxx/exchange folder is
                      Concreter: ../Oracle.udl wordt gebruikt
  */
  ]]>

  <job id="exchange_webhooks">
    <script language="JScript" src="../wsf_shared.js"/>
    <script language="JScript" src="../json2.js"/>
    <script language="JScript" src="ms_graph.js"/>
    <script language="JScript" src="exchange_graph.js"/>
    <script language="JScript" src="../../appl/imp/imp_shared.js"/>
    <script language="JScript" src="res_to_graph.js"/>

    <script language="JScript">
      /* global */ var custabspath = fso.GetAbsolutePathName("../");

      var config = loadconfig("exchange.config");

      if (WScript.Arguments.length > 0)
      {
          var hookurl = WScript.Arguments(0);
      }
      else if (config.hookurl)
      {
          var hookurl = config.hookurl;
      }
      else
      {   // Autodetect ngrok started with: ngrok http sggr.facws001.sg.nl:80
          var ngrokurl = null;
          var fac_version = custabspath.split("\\")[custabspath.split("\\").length - 3]; // 'Branch#####' of 'Trunk', 'APPL' op productie, maar die komt hier niet
          var request = {
            "method": "GET",
            "url": "http://127.0.0.1:4040/api/tunnels/command_line",
            "headers": { "Accept": "application/json" },
            "params": { "callback": function (request, response) {
                __Log("Ngrok detected: " + response.public_url);
                __Log("           tip: view traffic at http://127.0.0.1:4040");
                hookurl = response.public_url + "/" + fac_version + "/";
              }
            }
          }
          doHTTP(request);
      }
      __Log("Using hookurl : " + hookurl);

      var Oracle = new ActiveXObject("ADODB.Connection");
      Oracle.Open('File Name=../oracle.udl'); //../Oracle.udl

      var apiname = 'MSGRAPHNOTIFICATION'; // must point to appl/api/api_msgraphnotification.asp
      var token = requestToken(config);

      var sql = "BEGIN DBMS_APPLICATION_INFO.SET_MODULE ('refresh_webhooks.wsf', NULL); END;";
      var oRs = Oracle.Execute(sql);

      // Determine customerId
      sql = "SELECT fac_version_cust FROM fac_version";
      oRs = Oracle.Execute(sql);
      var customerId = oRs("fac_version_cust").Value;
      oRs.Close();

      // Get the api-(user)key
      sql = "SELECT prs_perslid_key, prs_perslid_apikey FROM prs_perslid WHERE prs_perslid_oslogin = '_MSGRAPHNOTIFICATION'";
      oRs = Oracle.Execute(sql);
      var apikey = oRs("prs_perslid_apikey").Value;
      var user_key = oRs("prs_perslid_key").Value;
      oRs.Close();

      var webhookurl = hookurl + "?API={0}&APIKEY={1}&fac_id={2}".format(apiname, apikey, customerId); // fac_id is vooral voor ngrok nodig

      if (validNotificationUrl(webhookurl)) {
          __Log("SUCCESS\n");
      } else {
          WScript.Quit(1);
      }

      // Verzamel eerst alle actieve subscriptions
      var subscriptionList = [];
      var response = getSubscriptions();
      if (response && response.value) {
        subscriptionList = response.value;
        while (response.skiptoken) {
          response = getSubscriptions(response.skiptoken);
          for (var i = 0; i < response.value.length; i++) {
            subscriptionList.push(response.value[i]);
          }
        }
      }

      sql = "SELECT res_ruimte_key,"
          + "       res_ruimte_extern_id,"
          + "       res_ruimte_graphhooksecret"
          + "  FROM res_ruimte"
          + " WHERE res_ruimte_verwijder IS NULL"
          + "   AND res_ruimte_extern_id IS NOT NULL"
          + " ORDER BY res_ruimte_key"; // ORDER BY alleen om het voorspelbaar te houden

      // Soms zijn we voor de eerste 100 (default ORAOLEDB FetchSize) records meer dan een uur bezig
      // Dan heeft Oracle (of ADO of ORAOLEDB) de recordset gesloten en krijgen we later op de MoveNext()
      // een Unspecified Error
      // Daarom een clientside/static cursor gebruiken. Die heeft (hopelijk) alle records al wel opgehaald
      // oRs = Oracle.Execute(sql);
      var oRs = new ActiveXObject("ADODB.RecordSet");
      oRs.CursorLocation = 3; // adUseClient
      oRs.CursorType = 3; // adOpenStatic
      oRs.Open(sql, Oracle, 3 /*adOpenStatic*/);

      var full_import_app_key = getImportAppKey("EXCHFULL");

      // Per ruimte;
      // 1) Delete webhook
      // 2) Fullsync
      // 3) Create webhook

      while (!oRs.Eof) {
          var token = requestToken(config); // Iedere keer opnieuw. Moet eigenlijk expiration controleren

          var userPrincipalName = oRs("res_ruimte_extern_id").Value;
          var res_ruimte_key = oRs("res_ruimte_key").Value;

          var resourceUpper = ("/users/" + encodeURIComponent(userPrincipalName) + "/events").toUpperCase();

          try {
            for (var i = subscriptionList.length - 1; i >= 0; i--) {
              if (   subscriptionList[i].notificationUrl.toUpperCase().indexOf(hookurl.toUpperCase()) != -1 // Ik ben een subscription op *deze* omgeving
                  && subscriptionList[i].resource.toUpperCase().indexOf(resourceUpper) == 0)                // Ik ben een subscription op *deze* resource (ruimte)
              {
                var request = {
                    "method": "DELETE",
                    "url": "https://graph.microsoft.com/v1.0/subscriptions/" + subscriptionList[i].id,
                    "headers": { "Accept": "application/json", "Authorization": "Bearer " + token }
                }
                if (doHTTP(request)) { // Success?
                  __Log("Deleted subscription for user " + userPrincipalName + " (" + subscriptionList[i].id + ")", "#00FF00");
                  subscriptionList.splice(i, 1);
                }
              }
            }
          } catch (e) {
            var err = "[500] - MS Graph [Refresh Exception] - '" + e.description + "' while deleting subscription for (" + userPrincipalName + ")";
            __DoLog(err, "#FF0000");
            Oracle.Execute("BEGIN fac.putsystemnotification({0}, 3); END;".format(safe.quoted_sql(err))); // 3=portal+email
          }

          // Fullsync bij het aanmaken van een nieuwe subscription zodat we volgens updates snel met een deltatoken kunnen ophalen
          try {
            createSubscription( userPrincipalName,
                                res_ruimte_key,
                                webhookurl,
                                true); // Voorkomt onnodige validaties van de notificatie-url, want dat is hierboven al gebeurd

            // Verwijder de regels van deze ruimte die wachten om opnieuw geprobeert te worden, dat is deprecated;
            var del_sql = "DELETE FROM exc_import"
                        + "      WHERE gelukt IS NULL"
                        + "        AND fac_import_key IN (SELECT fac_import_key"
                        + "                                 FROM fac_import"
                        + "                                WHERE fac_import_refkey = " + res_ruimte_key
                        + "                                  AND fac_import_app_key = " + full_import_app_key + ")";
            Oracle.Execute(del_sql);
          } catch (e) {
            var err = "[500] - MS Graph [EXCHFULL Exception] - " + e.description + " (" + userPrincipalName + ")";
            __DoLog(err, "#FF0000");
            Oracle.Execute("BEGIN fac.putsystemnotification({0}, 3); END;".format(safe.quoted_sql(err))); // 3=portal+email
          } // En door
          oRs.MoveNext();
      }
      oRs.Close();

      // Verwijder nu de overige webhooks, welke dan? Geen idee eigenlijk, maar we gaan ze verwijderen ..
      var deleted = 0;
      for (var i = 0; i < subscriptionList.length; i++) {
        if (   subscriptionList[i].notificationUrl.toUpperCase().indexOf(hookurl.toUpperCase()) != -1 // Ik ben een subscription op *deze* omgeving
            || subscriptionList[i].notificationUrl.indexOf("ngrok") != -1)                            // of een lokale (ngrok)
        {
          var request = {
            "method": "DELETE",
            "url": "https://graph.microsoft.com/v1.0/subscriptions/" + subscriptionList[i].id,
            "headers": { "Accept": "application/json", "Authorization": "Bearer " + token }
          }
          if (doHTTP(request)) {
            deleted++;
          }
        }
      }
      if (deleted) {
        __DoLog(deleted + " remaining subscriptions deleted", "#00FF00");
      }

      Oracle.Close();
    </script>
  </job>