// ******************************************
// * $Id$
// *
// *   sendAPP()
// *
// * sendAPP function is used to send APP push notifications
// *
// * arguments:
// *           p_perslid_key: Send the notificatie to this perslid
// *             p_msg: APP message to send.
// *
// ******************************************
function sendAPP( p_perslid_key
                , p_msg
                , p_url
                , noti_json
                )
{
    try
    {
        var keeploglevel = S("puo_loglevel");
        var APPsend = false;

        var sql = "SELECT aut_client_perslid_key "
                + "     , aut_client_perslid_pushtoken "
                + "     , aut_client_perslid_device_id "
                + "     , aut_client_perslid_device_name "
                + "     , aut_client_id"
                + "     , prs_perslid_naam_friendly"
                + "     , ba.*"
                + "  FROM aut_client_perslid acp"
                + "     , aut_client ac"
                + "     , prs_bedrijf b"
                + "     , prs_bedrijfadres ba"
                + "     , prs_v_perslid_fullnames p"
                + " WHERE acp.aut_client_key = ac.aut_client_key"
                + "   AND prs_bedrijfadres_startdatum <= SYSDATE"  // geen reden om hier meerdere van te hebben, maar zo werkt het eenmaal
                + "   AND acp.prs_perslid_key = " + p_perslid_key
                + "   AND acp.prs_perslid_key = p.prs_perslid_key"
                + "   AND ac.prs_bedrijf_key = b.prs_bedrijf_key(+)" // outer join alleen omdat FCLTAPP1 hardcoded is
                + "   AND b.prs_bedrijf_key = ba.prs_bedrijf_key(+)"
                + "   AND ba.prs_bedrijfadres_type(+) = 'N'"; // Notificatie
        var oRs = Oracle.Execute(sql);
        while (!oRs.Eof)
        {   // Let op: lang niet alles wordt (al) ondersteund
            var bedrijfadres = { key:             oRs("prs_bedrijf_key").value,
                                url:             oRs("prs_bedrijfadres_url").value,
                                encoding:        oRs("prs_bedrijfadres_encoding").value,
                                ordermode:       oRs("prs_bedrijfadres_ordermode").value,
                                typeopdr_key:    oRs("mld_typeopdr_key").value,
                                certificateName: oRs("prs_bedrijfadres_certificate").value || "",
                                extension:       oRs("prs_bedrijfadres_ext").value||"",
                                flexfiles:       oRs("prs_bedrijfadres_flexfiles").value,
                                AttachFile:      oRs("prs_bedrijfadres_attachfile").Value,// Eén vaste bijlage ('algemene voorwaarden') om bij te sluiten
                                XSLbedr:         (oRs("prs_bedrijfadres_xsl").value||"").toLowerCase(),
                                username:        oRs("prs_bedrijfadres_username").value,
                                password:        oRs("prs_bedrijfadres_password").value,
                                privkey:         oRs("prs_bedrijfadres_privkey").value,
                                authmethod:      oRs("prs_bedrijfadres_authmethod").value || 0,
                                scope:           oRs("prs_bedrijfadres_oa_scope"),
                                soapversion:     oRs("prs_bedrijfadres_soapversion").value,
                                soapaction:      oRs("prs_bedrijfadres_soapaction").value,
                                locksecret:      oRs("prs_bedrijfadres_locksecret").value,
                                loglevel:        oRs("prs_bedrijfadres_loglevel").value
                            };
            if (!bedrijfadres.url)
            {
                oRs.MoveNext()
                continue;
            }

            if (!oRs("aut_client_perslid_pushtoken").Value)
            {
                Log2File(1, "APP bericht: '" + p_msg + "' *niet* verzonden naar " + p_perslid_key + " want aut_client_perslid_pushtoken is leeg");
                oRs.MoveNext()
                continue;
            }
            if (bedrijfadres.loglevel > S("puo_loglevel"))
            {
                settings.overrule_setting("puo_loglevel", bedrijfadres.loglevel);
                Log2File(1, "puo_loglevel overruled by prs_bedrijfadres_loglevel: " + bedrijfadres.loglevel);
            }

            // Dit zou ik het liefst doen met een stylesheet achtige oplossing en dan een XML2JSON
            // Enerzijds wil je echter gewoon de volledige standaard xml_content gebruiken
            // maar anderzijds zit daar in het bijzonder het pushtoken niet in
            // Bovendien kan ik me ook goed een APP voorstellen waarbij het pushtoken in de url moet komen,
            // dat red je ook weer niet echt met een stylesheet.
            // Welbeschouwd moet er misschien beter een plugin achtige constructie komen?
            // Praktijk afwachten maar
            if (bedrijfadres.url == "https://fcm.googleapis.com/fcm/send")
            {
                throw { description: "Old style firebase not supported"};
            }
            else if (bedrijfadres.url == "https://fcm.googleapis.com/v1/projects/facilitor-165209/messages:send")
            {
                var json = {
                    "message": {
                        "notification": {
                            "title": "Facilitor",
                            "body": p_msg
                            },
                        "token": oRs("aut_client_perslid_pushtoken").Value
                    }
                }

                if (S("puo_forceapppushtoken"))
                {
                json.notification.to = S("puo_forceapppushtoken");
                }
                if (p_url)
                {
                    json.message.data = {
                        "url": p_url,
                         "fullurl": S("puo_fclt_web_url") + p_url + (p_url.indexOf("?")>=0?"&":"?")+ "fac_id=" + customerId // als de APP een webclient van FACILITOR is kan hij hier 'naar toe' springen
                     }
}
            }
            else
            {
                throw { description: "unsupported push url" };
            }

            var body = JSON.stringify(json);
            var forcemsg = "APP bericht: '{0}'\n    wordt via {1} verzonden naar: {2}/{3}".format(p_msg, oRs("aut_client_id").Value,
                                                                                                         oRs("prs_perslid_naam_friendly").Value,
                                                                                                         oRs("aut_client_perslid_device_name").Value);
            Log2File(1, forcemsg);
            Log2File(2, "Registered pushtoken: " + oRs("aut_client_perslid_pushtoken").Value);

            if (S("puo_forceapppushtoken"))
            {
                Log2File(1, "        (effective to pushtoken: " + json.Tag + ")");
            }

            Log2File(2, "Payload: " + body);
            var params = bedrijfadres;
            params.data = body;

            params.headers = { "Content-Type": "application/json" };
            if (bedrijfadres.authmethod==5)
            {
                var gAuth = getGoogleAccessToken(bedrijfadres, "https://www.googleapis.com/auth/firebase.messaging");
                params.headers["Authorization"] = "Bearer {0}".format(gAuth.AccessToken);
            }
            var xmlHTTP = doHTTP(bedrijfadres.url, params);
            if (xmlHTTP.status >= 200 && xmlHTTP.status <= 299)
            {
                APPsend = true;
            }
            else
            {   // errors blijven status 200 opleveren en zijn door doHTTP nog niet gelogged
                Log2File(0, "APP push xmlHTTP error "
                                    + xmlHTTP.status + "/ " + xmlHTTP.statusText
                                                    + "/" + xmlHTTP.responseText);
            }
            if (S("puo_loglevel") != keeploglevel)
                settings.overrule_setting("puo_loglevel", keeploglevel); // was mogelijk overruled
            oRs.MoveNext()
        }
        oRs.Close();
        return APPsend;
    }
    catch (e)
    {
        Log2File(1, "function sendAPP failed: " + e.description);
        throw (e);
    }
}

function getGoogleAccessToken(bedrijfadres)
{
    var glob = new ActiveXObject("Chilkat_9_5_0.Global")
    var success = glob.UnlockBundle(S("puo_chilkat_secret"));
    if (success != 1)
        throw { description: glob.LastErrorText };

    // Gebaseerd op https://www.example-code.com/csharp/googleapi_access_token_json.asp
    var jsonKey = bedrijfadres.privkey;

    var gAuth = new ActiveXObject("Chilkat_9_5_0.AuthGoogle");
    gAuth.JsonKey = jsonKey;

    // Choose a scope.
    gAuth.Scope = bedrijfadres.scope;

    // Request an access token that is valid for this many seconds.
    gAuth.ExpireNumSeconds = 3600;

    // If the application is requesting delegated access:
    // The email address of the user for which the application is requesting delegated access,
    // then set the email address here. (Otherwise leave it empty.)
    gAuth.SubEmailAddress = "";

    // Connect to www.googleapis.com using TLS (TLS 1.2 is the default.)
    // The Chilkat socket object is used so that the connection can be established
    // through proxies or an SSH tunnel if desired.
    var tlsSock = new ActiveXObject("Chilkat_9_5_0.Socket");

    try
    {
        var WshShell = new ActiveXObject("WScript.Shell");
        var computername = WshShell.ExpandEnvironmentStrings("%COMPUTERNAME%");
    }
    catch (e)
    {
        var computername = "???";
    }
    if (computername.match(/^P03SSNWEB/))
    {
        tlsSock.HttpProxyForHttp = 1;
        tlsSock.HttpProxyHostname = "fclt-proxy.ssn.aareon.com";
        tlsSock.HttpProxyPort  = 92;
    }

    var success = tlsSock.Connect("www.googleapis.com",443,true,5000);
    if (success != true) {
        throw { description: tlsSock.LastErrorText };
    }

    // Send the request to obtain the access token.
    success = gAuth.ObtainAccessToken(tlsSock);
    if (success != true) {
        throw { description: gAuth.LastErrorText };
    }

    return gAuth
}