<% /*
    $Revision$
    $Id$

    File:        default.inc
    Description: Gaat over alle settings
    Parameters:
    Context:     Vanuit ELK asp bestand
*/

var FCLTVersion="2025.4";
var FCLTMinDatabaseSchema="52"; // Alleen de cijfers

var custpath = rooturl + "/cust/" + customerId;  // path to customer files

var hiresTimer = null;

/* global */
settings =
{
    overrule: {},
    pagecache: {},

    aspdefaults :
            { perfmon_threshold:      { v: 2000 }, // is al nodig om de settings uit de database te kunnen halen
              // Onderstaande settings hebben een default die custpath afhankelijk is.
              // In de database kunnen ze nog wel overruled worden
              flexfilespath:          { v: Server.MapPath(custpath + "/flexfiles") },
              bdradrfiles_path:       { v: custpath + "/bdradrfiles" },

              // Merk op dat onderstaande paden (ook) via http benaderd worden. Daarom in
              // eerste instantie nog geen Server.MapPath
              // Sommige staan nog onder /flexfiles/ voor backwards compatibiliteit hoewel
              // logischer is om ze ooit allemaal onder een /photos/ te plaatsen
              image_path_virtual:     { v: custpath },
              menu_image_path:        { v: custpath + "/flexfiles/menu/" },
              menu_image_url_path:    { v: custpath + "/flexfiles/MENUURL/" },
              style_image_path:       { v: custpath + "/photos/styling/" },
              alg_image_path:         { v: custpath + "/photos/" },
              prs_image_path:         { v: custpath + "/flexfiles/prs/" },
              res_image_path:         { v: custpath + "/photos/" },
              resd_image_path:        { v: custpath + "/flexfiles/RES/IMAGES/DISC/" },
              bes_image_path:         { v: custpath + "/photos/BES/" },
              besd_image_path:        { v: custpath + "/flexfiles/BES/IMAGES/DISC/" },
              bgtd_image_path:        { v: custpath + "/flexfiles/BGT/IMAGES/DISC/" },
              cntd_image_path:        { v: custpath + "/flexfiles/CNT/IMAGES/DISC/" },
              insd_image_path:        { v: custpath + "/flexfiles/INS/IMAGES/DISC/" },
              ins_image_path:         { v: custpath + "/photos/INS/" },
              mrk_image_path:         { v: custpath + "/flexfiles/MRK/" },
              mlds_image_path:        { v: custpath + "/flexfiles/MLD/IMAGES/STDM/" },
              mldg_image_path:        { v: custpath + "/photos/MLD/STDMGROEP/" },
              mldd_image_path:        { v: custpath + "/flexfiles/MLD/IMAGES/DISC/" },
              mldsd_image_path:       { v: custpath + "/flexfiles/MLD/IMAGES/SRTDISC/" }
            },

    // Laad alle settings uit de database
    loadSET : function(force)
    {
        // Onderstaande tak bevat de voorwaarden waaronder we mogelijk *niet* hoeven te re-cachen
        if (    !force                                                      // Niet geforceerd
             && typeof Application("SET_TM_" + customerId) != "undefined"   // We hebben ooit gecached
             && typeof Application("DEFAULTS_DB_SCHEMA") != "undefined"     // Er is bij een voorgaande cache het DB schema nummer opgeslagen
             && typeof Application("SET_" + customerId + "_DB_SCHEMA") != "undefined" // We hebben bij een voorgaande cache ons eigen schemanummer opgeslagen
             && parseInt(Application("SET_" + customerId + "_DB_SCHEMA"), 10) <= parseInt(Application("DEFAULTS_DB_SCHEMA"), 10)) // Ons schemanummer is niet nieuwer dan die van de opgeslagen defaults
        {
            if (typeof CACHE_checkfreshness == "undefined")
                return; // we hebben ze al gecached en we gaan geen freshness controleren
            // Ok, freshness controleren
            var sql = "SELECT MAX(fac_setting_datum) max_date"
                    + "  FROM fac_setting";
            var oRs = Oracle.Execute(sql);
            var max_date = new Date(oRs("max_date").Value);
            oRs.Close();
            var lastCache = new Date(Application("SET_TM_" + customerId));
            if (max_date <= lastCache)
            {   // Dan misschien alleen default.csx compileren
                FCLTHeader.testTemplateCssRefresh();
                return; // Cache is verder vers genoeg
            }
            __DoLog("Forced settings cache reload. Cache was loaded " + toISODateTimeString(lastCache, true) + ", last setting is " + toISODateTimeString(max_date, true), "#ffff00");
        }
        // else { altijd re-cachen }

        Application.Lock();

        // Application pool restart detection
        if (typeof Application("SET_INSTANCE_TIME") == "undefined")
        {
            var tm_start = new Date();
            Application("SET_INSTANCE_TIME") = tm_start.getTime(); // Estimated application pool start
            Application("SET_INSTANCE_RANDOM") = shared.random(32); // om met fac_verify te kijken of S("puo_fclt_web_url") goed staat
            if (tm_start.getHours() >= 9 && tm_start.getHours() <= 17) // Tijdens kantooruren registreren we in de AiAi logger
            {
                var keeplog = __LogfileName;
                var folder = Server.MapPath(rooturl + "/temp/_AiAi_error");
                var fso = Server.CreateObject("Scripting.FileSystemObject");
                if (!fso.FolderExists(folder))
                    fso.CreateFolder(folder);
                var nowtxt = toISODateString(new Date());
                /* global */ __LogfileName = folder + "/log_" + nowtxt + ".html";
                try
                {
                    var WshShell = new ActiveXObject("WScript.Shell");
                    var pool_id = WshShell.ExpandEnvironmentStrings("%APP_POOL_ID%");
                }
                catch (e)
                {
                    pool_id = "<unknown>";
                }
                if (!pool_id.match(/API/)) // API application pools kunnen regulier herstarten
                {
                    var txt = "Unexpected Application pool '{0}' (re)start at {1} during office hours".format(pool_id, toISODateTimeString(tm_start, true));
                    __DoLog(txt, "#f00");
                    __Logstd(txt, "E");
                    __DoLog("CustomerId: {0}".format(customerId));
                    __DoLog("Triggered by {0}://{1}".format(String(Request.ServerVariables("SERVER_PORT")) == '443'?"https":"http",
                                                            String(Request.ServerVariables("HTTP_HOST"))));
                }
                __LogfileName = keeplog;
            }
        }

        // Eigenlijk moet DBLANG ook gewoon een setting worden. Simuleer dat hier
        var oRs = Oracle.Execute("SELECT fac_version_lang, fac_version_schema FROM fac_version");
        Application("SET_T_DB_LANG") = "string"; // Is voor alle klanten gelijk
        Application("SET_" + customerId + "_DB_LANG") = oRs("fac_version_lang").Value;
        Application("SET_T_DB_SCHEMA") = "string"; // Is voor alle klanten gelijk
        Application("SET_" + customerId + "_DB_SCHEMA") = oRs("fac_version_schema").Value;
        oRs.Close();

        var oRs = Oracle.Execute("SELECT value FROM nls_database_parameters WHERE parameter = 'NLS_CHARACTERSET'");
        Application("SET_T_DB_CHARSET") = "string"; // Is voor alle klanten gelijk
        Application("SET_" + customerId + "_DB_CHARSET") = oRs("value").Value;
        oRs.Close();

        // Settings cachen.
        // Voor defaults delen we de waarde over alle klanten.
        var sql = "SELECT fac_setting_name,"
                + "       fac_setting_type,"
                + "       fac_setting_default,"
                + "       fac_setting_pvalue"
                + "  FROM fac_setting";
        var oRs = Oracle.Execute(sql);
        var updateDefaultsDBSchema =    typeof Application("DEFAULTS_DB_SCHEMA") == "undefined" // Laatste cache heeft geen schemanummer opgeslagen
                                     || parseInt(Application("DEFAULTS_DB_SCHEMA"), 10) < parseInt(Application("SET_" + customerId + "_DB_SCHEMA"), 10); // Of ons schemanummer is nieuwer
        while (!oRs.Eof)
        {
            var n = oRs("fac_setting_name").Value;
            var t = oRs("fac_setting_type").Value;
            var v = oRs("fac_setting_pvalue").Value;
            var d = oRs("fac_setting_default").Value;

            // Controleer voor elke klant bij het cachen of er nog (meer) defaults gezet moeten worden
            // Handig tijdens development als een klant al meer setting records heeft dan degene die
            // 's nachts voor het eerst is opgestart
            if (!(n in this.aspdefaults))
            {
                var defaultDiscrepancy = (Application("SET_T_" + n) != t || Application("SET_DEFAULT_" + n) != d); // Onze default wijkt af van de gecachede default
                if (    typeof Application("SET_DEFAULT_" + n) == "undefined"   // Er is geen huidige default waarde gecached
                     || updateDefaultsDBSchema && defaultDiscrepancy)           // Of de cache is achterhaald
                {
                    if (typeof Application("DEFAULTS_SET_BY_CUSTOMER") == "undefined")
                    {
                        Application("DEFAULTS_SET_BY_CUSTOMER") = customerId;
                        Application("DEFAULTS_SET_TIMESTAMP") = toISODateTimeString(new Date());
                    }
                    // Cache de defaultwaarde/type
                    Application("SET_T_" + n) = t;
                    Application("SET_DEFAULT_" + n) = d; // Is voor alle klanten gelijk
                }
                else if (defaultDiscrepancy)
                {
                    __DoLog("Vreemd. Default voor " + n
                            + " is gecached als " + Application("SET_T_" + n) + "/" + Application("SET_DEFAULT_" + n)
                            + " terwijl onze fac_setting zegt " + t + "/" + d, "#f00");
                    __DoLog("Defaults waarschijnlijk geladen vanuit {0} ({1}) op {2}"
                                .format(Application("DEFAULTS_SET_BY_CUSTOMER"),  "DB" + Application("DEFAULTS_DB_SCHEMA"), Application("DEFAULTS_SET_TIMESTAMP")));
                }
            }

            if (!v && n in this.aspdefaults) // Default waarde is al in ASP gezet
            {
                v = this.aspdefaults[n].v;
                t = typeof v;
            }

            // Normaal gesproken zijn dit absolute paden maar we staan ook relatieve
            // paden ten opzichte van de root toe
            if (n == "flexfilespath")
            {
                v = oRs("fac_setting_pvalue").Value || oRs("fac_setting_default").Value;
                if (v.substr(0,1) == '@')
                {
                    // backwards compatible: flexfiles onder de CUST-folder.
                    v = Server.MapPath(custpath + "/flexfiles");
                    t = typeof v;
                }
                else if (v.substr(0,1) == '*') // *_DATA wordt branch20211_DATA of FPlace5i_DATA
                {                         // (Op FACWS001 overrulen we dat voor branches meestal naar Trunk_Data)
                    v = Server.MapPath(rooturl || "/") + v.substr(1) + "/" + customerId;
                    var fso = Server.CreateObject("Scripting.FileSystemObject");
                    v = fso.GetAbsolutePathName(v); // Technisch niet nodig maar toch '..' wegwerken
                    __Log("Path {0} is set to {1}".format(n, v));
                }
            }

            if (v == null) // niet opslaan als het de default waarde is
            {
                Application.Contents.Remove("SET_" + customerId + "_" + n); // Voor zelfzame geval dat iemand via de GUI setting wist
            }
            else
            {
                Application("SET_" + customerId + "_" + n) = v;
            }
            //Response.Write(oRs("fac_setting_name").Value + ": " + typeof v);
            oRs.MoveNext();
        }
        oRs.Close();

        if (updateDefaultsDBSchema) {
            Application("DEFAULTS_DB_SCHEMA") = Application("SET_" + customerId + "_DB_SCHEMA");
        }

        Application("SET_" + customerId) = toISODateTimeString(new Date());
        Application("SET_TM_" + customerId) = new Date().getTime();
        var sql = "SELECT MAX(adm_tracking_date)"
                + "  FROM adm_tracking"
                + " WHERE adm_tracking_revision IS NOT NULL";
        var oRs = Oracle.Execute(sql);
        Application(customerId + "_ADMTRACK") = new Date(oRs(0).Value).getTime();
        oRs.Close();

        // Op deze plek van de code komen we doorgaans eens per dag
        fclt_register_task(); // voor als eventueel tsk_master is gewijzigd

        // set "portalert" with S("fac_portalert_XD") if available
        if (S("fac_portalert_xd") != "")
        {
            Application("portalalert") = S("fac_portalert_xd");
        }
        Application.UnLock();

        return true; // first time today
    },
    // Get setting value
    // finalTry -->geef fatal error bij problemen
    //             (zonder finalTry proberen we eerst de cache te verversen)
    finalTry: false, // semi-globale ipv. parameter om nasty-recursion te voorkomen
    get_setting : function _get_setting(s, defval, nooverrule)
    {
        if (!nooverrule && s.toLowerCase() in settings.overrule)
            return settings.overrule[s.toLowerCase()];

        if (s in this.pagecache)
            return this.pagecache[s];

        var v = Application("SET_" + customerId + "_" + s);
        if (typeof v == "undefined")
            var v = Application("SET_DEFAULT_" + s); // Overrule.DEFAULT uit custenv.wsc

        try
        {
            if (typeof v == "undefined")
            {
                if (s in this.aspdefaults)
                    return this.aspdefaults[s].v; // Alleen voor perfmon_threshold nodig bij allereerste keer cachen
                else
                    throw { description: "Setting is missing. Perhaps it is time to upgrade the database." };
            }
            var t = Application("SET_T_" + s);
            switch (t)
            {
                case "string":
                    v = v || "";
                    break;
                case "number":
                    v = parseInt(v);
                    break;
                case "float":
                    v = parseFloat(v);
                    break;
                case "boolean":
                    v = (v == "true") || (v == "1") || (v.toLowerCase() == "yes");
                    break;
                case "array":
                    v = v? v.split(",") : [];
                    break;
                case "json":
                    try
                    {
                      if (v)
                      {
                        v = JSON.parse(v);
                      }
                    }
                    catch (e)
                    {   // Zou niet mogen gebeuren maar vanwege zeer hoge impact (gebruiker
                        // kan echt niets meer) toch maar onderscheppen.
                      __DoLog("eval van options mislukt: " + e.description, "#FF0000")
                      __DoLog(v);
                      v = "";
                    }
                    break;
            }
            //__Log("Setting " + s + " is type " + t + " en v=" + v + " ("+(typeof v)+")");
            settings.pagecache[s] = v; // voor de volgende keer op deze pagina
            return v;
        }
        catch(e)
        {
            if (settings.finalTry)
            {
                if (typeof defval != "undefined")
                    return defval;
                __DoLog("Could not retrieve setting " + s + "\n" + e.description, "FF0000");
                var txt = "Could not retrieve setting <strong>" + s + "</strong><br>" + e.description;
                var sql = "SELECT MAX(adm_tracking_date)"
                        + "  FROM adm_tracking"
                        + " WHERE adm_tracking_name = 'FAC_SET.SRC'";
                var oRs = Oracle.Execute(sql);
                if (!oRs.Eof)
                {
                    __DoLog("FAC_SET.SRC was last loaded " + toISODateTimeString(oRs(0).Value));
                }
                oRs.Close();
                var txt = "Setting '{0}' is missing.".format(s);
                if (Application("otap_environment") == "O")
                {
                    txt += "\nOTAP hint: laatste upgrade of recreate draaien of Overrule.DEFAULT toevoegen aan cust/custenv.wsc";
                }
                _AiAi(txt);
            }
            else
            {   // Kan gebeuren vlak na een upgrade als mensen binnenkomen via SSO of via een API
                // CACHE_checkfreshness is alleen gezet op de voorpagina maar daar komen die twee niet per se langs
                // Met name in de API wil ik CACHE_checkfreshness niet aanzetten: te duur. Daarom robuust bouwen
                settings.finalTry = true;
                settings.loadSET(true);
                return settings.get_setting(s, defval); // laatste poging
            }
        }
    },
    // Set setting value (res_t1 gebruikt dat bijvoorbeeld)
    // Alleen zeer tijdelijk effect voor rest van het bestand
    overrule_setting : function (s, v)
    {
        settings.overrule[s.toLowerCase()] = v;
    }
}

// Shorthand
function S(s, defval)
{
    return settings.get_setting(s, defval)
}

function isutf8()
{
    return S("DB_CHARSET") == 'AL32UTF8';
}
%>
