// $Revision$
// $Id$
//
// In kader van FCLT#62383
// Een parameter: UDL voor database connectie

var doDelete = (WScript.Arguments.Length > 0 && WScript.Arguments(0) == "DODELETE");
if (!doDelete)
    WScript.Echo("Simulation only. Call me using DODELETE to actually change something");

var fso = new ActiveXObject("Scripting.FileSystemObject");
function __Log(s)
{
    WScript.Echo(s);
    var logPath = "../../../temp/" + CustId;
    var flog = fso.OpenTextFile(logPath + "/gencleanup_"+CustId+".log", 8 /* ForAppending */, true /* create */);
    flog.WriteLine(s);
    flog.Close();
}

function isOffline()
{
    var fso = new ActiveXObject("Scripting.FileSystemObject");
    if (fso.FileExists("../offline.html"))
        return true;
    if (fso.FileExists("../../offline.html"))
        return true;
    if (fso.FileExists("../../../temp/offline.html"))
        return true;

    return false;
}

function cleanup_bijlagen()
{
    function getFlexfilesPath(customerId)
    {
        var sql = "SELECT COALESCE(fac_setting_pvalue, fac_setting_default) fac_setting_value"
                + "  FROM fac_setting"
                + " WHERE fac_setting_name = 'flexfilespath'";
        var oRs = Oracle.Execute(sql);
        var v = "";
        if (!oRs.eof)
        {
            v = oRs("fac_setting_value").Value;
        }
        oRs.Close();

        if (v.substr(0,1) == '@') // Old style
        {
            var fso = new ActiveXObject("Scripting.FileSystemObject");
            v = fso.GetAbsolutePathName("../../../cust/" + customerId + "/flexfiles")
            __Log("flexfilespath is set to " + v);
        }
        else if (v.substr(0,1) == '*') // *_DATA wordt branch20163_DATA of FPlace5i_DATA
        {
            var fso = new ActiveXObject("Scripting.FileSystemObject");
            v = fso.GetAbsolutePathName("../../..") + v.substr(1) + "/" + customerId;
            __Log("flexfilespath is set to " + v);
        }
        return v
    }

    function quoted_sql(tekst, maxlen) // maxlen is optioneel
    {
        if (tekst == null)
            return "NULL";
        if (!maxlen)
            maxlen = 4000;
        // Haal alle lage bytes (muv TAB (x09), LF (x0A) en CR (x0D)) er uit. Die representeren
        // geen geldig karakter in Windows-1252 of iso-8859. Ook in UTF-8 staan ze niet voor
        // tekst, mochten we dat ooit willen gaan ondersteunen.
        // Voor ultieme veiligheid ook maar de hoge unicodes er uit? Neen, EURO is ten slotte
        // ook een 'hoge' unicode
        tekst = tekst.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F]+/g, "?");
        tekst = tekst.substr(0, maxlen);
        // FSN#35288: '{' naar CHR(123) voorkomt Unspecified Error
        return "'" + tekst.replace(/\'/g,"''").replace(/\{/g,"'||CHR(123)||'") + "'"; // " syntax highlight correctie
    }

    //
    // Main
    //
    var deleted = { files: 0, records: 0, errors: 0, total: 0 };
    var flexfilespath = getFlexfilesPath(CustId);

    // Laat root_key naar zichzelf verwijzen om te voorkomen dat een record niet verwijderd kan worden
    // omdat er een ander nog te verwijderen record bestaat die nog naar hem verwijst.
    var sql = "UPDATE fac_bijlagen"
            + "   SET fac_bijlagen_root_key = fac_bijlagen_key"
            + " WHERE fac_bijlagen_verwijder IS NOT NULL";
    if (doDelete)
        Oracle.Execute(sql);

    // Alle records die op verwijderd staan en waaraan niet meer gerefereerd wordt in een niet-te-verwijderen
    // record mogen opgeruimd worden.
    var sql = "SELECT a.fac_bijlagen_key"
            + "     , a.fac_bijlagen_module"
            + "     , a.fac_bijlagen_refkey"
            + "     , a.fac_bijlagen_disk_directory map"
            + "     , COALESCE(a.fac_bijlagen_disk_filename, a.fac_bijlagen_filename) filename"
            + "  FROM fac_bijlagen a"
            + " WHERE a.fac_bijlagen_verwijder IS NOT NULL"
            + "   AND NOT EXISTS (SELECT 1"
            + "                     FROM fac_bijlagen b"
            + "                    WHERE b.fac_bijlagen_root_key = a.fac_bijlagen_key"
            + "                      AND b.fac_bijlagen_verwijder IS NULL"
            + "                   )"
            + " ORDER BY fac_bijlagen_disk_directory"
    var oRs = Oracle.Execute(sql);
    while (!oRs.eof)
    {
        // Verwijder bijlage van schijf.
        // Fac_bijlagen_disk_directory kan ook "*see root*" zijn als root_key verwijst naar een ander record.
        // Hierbij hoeft er geen bestand te worden verwijderd, alleen maar het record.
        deleted.total++;
        var del_key = oRs("fac_bijlagen_key").Value;
        var module = oRs("fac_bijlagen_module").Value;
        var refkey = oRs("fac_bijlagen_refkey").Value;
        var del_file = flexfilespath + "/" + oRs("map").Value + "/" + oRs("filename").Value;
        __Log("\nConsidering fac_bijlagen_key: " + del_key + " module " + module + " refkey " + refkey+ " file " + del_file);
        try
        {
            if (!fso.FileExists(del_file))
            {
                __Log("File not/no longer found. Just delete database record");
            }
            else
            {
                // Controle: bestaat er nog een actief bestand.
                var sql_a = "SELECT COUNT(*) aantal"
                          + "  FROM fac_bijlagen"
                          + " WHERE fac_bijlagen_disk_directory = " + quoted_sql(oRs("map").Value) //  'MLD/M1271___/M1271330/2803'
                          + "   AND fac_bijlagen_filename = " + quoted_sql(oRs("filename").Value)  //  'test_1.pdf'
                          + "   AND fac_bijlagen_verwijder IS NULL"
                          + "   AND fac_bijlagen_key <> " + del_key; //351198;  --, 351199
                var oRs_a = Oracle.Execute(sql_a);
                if (oRs_a("aantal").Value == 0)
                {   // Er is geen bestand met dezelfde naam in die map gevonden die niet verwijderd is, dus dan mag dit record weg.
                    //__Log(del_file);
                    if (fso.FileExists(del_file))
                    {
                        if (doDelete)
                        {
                            fso.DeleteFile(del_file);
                            __Log("Deleted: " + del_file)
                        }
                        else
                            __Log("PSEUDO delete file " + del_file);
                        deleted.files++;
                    }
                    else
                        __Log("Would delete but file already gone")
                }
                else
                    __Log("Won't delete because of other references")
                oRs_a.Close();
            }

            // De bijlage bij dit record is nu echt weg dus mag het record ook weg.
            sql_d = "DELETE"
                  + "  FROM fac_bijlagen"
                  + " WHERE fac_bijlagen_key = " + del_key;
            if (doDelete)
            {
                __Log("DELETE database record fac_bijlagen_key = " + del_key);
                Oracle.Execute(sql_d);
            }
            else
                __Log("PSEUDO DELETE database record fac_bijlagen_key = " + del_key);
            deleted.records++;
        }
        catch(e)
        {
            deleted.errors++;
            __Log("Could not delete " + del_key +": " + del_file + ": " + e.description);
        }
        oRs.MoveNext();
    }
    oRs.Close();
    __Log( "files deleted: "   + deleted.files   + "\n"
         + "records deleted: " + deleted.records + "\n"
         + "errors: "          + deleted.errors  + "\n"
         + "total count: "     + deleted.total
         );
}

function cleanup_temp()
{
    function getMidnightDate(datum)
    {
        var dt = ((typeof datum == "date") ? new Date(datum) : new Date());
        dt.setHours(0);
        dt.setMinutes(0);
        dt.setSeconds(0);

        return dt;
    }

    function getExpireDate(p_keep)
    {   // p_keep: d20 = 20 dagen
        //         m2  = eerste van 2 maand geleden.
        var expire_period = p_keep.substring(0,1);
        var expire_length = p_keep.slice(1);
        var expire_dt = getMidnightDate();
        if (expire_period == "d")
        {
            expire_dt.setDate(expire_dt.getDate() - expire_length);
        }
        else if (expire_period == "m")
        {
            expire_dt.setDate(1);
            expire_dt.setMonth(expire_dt.getMonth() - expire_length);
        }
        return expire_dt;
    }

    function scanFolder(p_thislevel, p_maxlevel, p_thisPath, p_folder, p_file, p_expires)
    {
        p_thislevel++;
        //__Log(p_thislevel+" scanFolder: "+p_thisPath);
        var fso = new ActiveXObject("Scripting.FileSystemObject");
        var thisFolder = fso.GetFolder(p_thisPath);
        if (p_folder)
        {
            var regexp_f = new RegExp(p_folder, "i");
            var enumFolder = new Enumerator(thisFolder.SubFolders);
            for (; !enumFolder.atEnd(); enumFolder.moveNext())
            {
                var thisFolder = enumFolder.item();
                var vName = thisFolder.Name;
                if (vName.match(regexp_f) || p_folder == "^")
                {
                    var nextPath = p_thisPath + vName + "/";
                    if ((p_thislevel >= p_maxlevel))
                    {
                        p_folder = "^";
                    }
                    scanFolder(p_thislevel, p_maxlevel, nextPath, p_folder, p_file, p_expires);
                    scanFile(nextPath, p_file, p_expires);
                }
                else
                {
                    continue;
                }
                //
                var deleteFolder = fso.GetFolder(nextPath);
                if (deleteFolder.Files.Count == 0 && deleteFolder.SubFolders.Count == 0 && (p_thislevel >= p_maxlevel))
                {
                    var err = "";
                    var delFolder = nextPath.substr(0, nextPath.length-1);
                    if (doDelete)
                    {
                        try { fso.DeleteFolder(delFolder, true); } catch (e) { err = "  FAILED"; };
                        __Log("    delete folder: " + delFolder + err);
                    }
                    else
                        __Log("PSEUDO delete folder: " + delFolder + err);
                }
            }
        }
        else
        {
            scanFile(p_thisPath, p_file, p_expires);
        }

    }

    function scanFile(p_thisPath, p_file_regexp, p_expires)
    {
        //__Log("scanFile: "+p_thisPath);
        var fso = new ActiveXObject("Scripting.FileSystemObject");
        var thisFolder = fso.GetFolder(p_thisPath);
        var regexp_f = new RegExp(p_file_regexp, "i");
        var enumFile = new Enumerator(thisFolder.Files);
        for (; !enumFile.atEnd(); enumFile.moveNext())
        {
            var thisFile = enumFile.item();
            var vName = thisFile.Name;
            if (vName.match(regexp_f))
            {
                var file_dt = getMidnightDate(thisFile.DateLastModified);
                if (file_dt < p_expires)
                {
                    files_deleted++;
                    var err ="";
                    if (doDelete)
                    {
                        try { thisFile.Delete(); } catch (e) { err = "  FAILED"; };
                        __Log("    delete file: " + p_thisPath + vName + err);
                    }
                    else
                        __Log("PSEUDO delete file: " + p_thisPath + vName + err);
                }
            }
        }
    }
    //
    // Main
    //
    var tempFolder = "../../../temp/" + CustId + "/";
    var cleanup_regexp_arr =
        [ { expr_folder: "",                        max_checklevel: 9, expr_file: "^(?:log_"+CustId+"_)\\S+\\\.html$",         keep: "d30"} // Alle log_CustId_*.html-bestanden in TEMP\CustId van meer dan 30 dagen oud verwijderen.
        , { expr_folder: "",                        max_checklevel: 9, expr_file: "\\S+\\\.(xml|jpg|jpeg|json|pdf|eml|msg|w2d|png|xlsx|lock)$",keep: "d10"} // Alle *.xml-, *.jpg- en *.json-bestanden in TEMP\CustId van meer dan 10 dagen oud verwijderen.
        , { expr_folder: "",                        max_checklevel: 9, expr_file: "^(?:(putorders.*_"+CustId+"))\\S+\\\.log$", keep: "m1" } // Alle putordersI_CustId_*.log en putorders_CustId_*.log verwijderen van voor de 1-ste van 1 maand geleden.
        , { expr_folder: "",                        max_checklevel: 9, expr_file: "^(?:(tasker.*_"+CustId+"))\\S+\\\.log$", keep: "m1" } // Alle putordersI_CustId_*.log en putorders_CustId_*.log verwijderen van voor de 1-ste van 1 maand geleden.
        , { expr_folder: "^(putorders)$",           max_checklevel: 9, expr_file: "^\\S+\.\\S+$",                              keep: "d30"} // Alles in TEMP\CustId\putorders van meer dan 30 dagen oud verwijderen.
        , { expr_folder: "^(exchange)$",            max_checklevel: 9, expr_file: "^\\S+\\.data$",                             keep: "d10"} // Alle .data in TEMP\CustId\exchange van meer dan 10 dagen oud verwijderen.
        , { expr_folder: "^(ALG|BES|CNT|FIN|INS|MRK|MLD|RES|FAQ|.__NEW__)", max_checklevel: 2, expr_file: "^\\S+",             keep: "d2" } // In mappen TEMP\CustId\Module\*__NEW__* bestanden die ouder zijn dan 2 dagen verwijderen, en als deze map dan leeg is de map ook verwijderen.
        ];

    var files_deleted = 0;
    for (var i=0; i<cleanup_regexp_arr.length; i++)
    {
        var p = cleanup_regexp_arr[i];
        var expires = getExpireDate(p.keep)
        scanFolder(0, p.max_checklevel, tempFolder, p.expr_folder, p.expr_file, expires);
    }
    __Log(">>  "+ files_deleted + " files" + (doDelete ? " " : " to be ") + "deleted.\n");
}


// ****************************************

if (isOffline())
{
    WScript.Echo("FACILITOR is offline, cleanup skipped");  // geen __Log omdat CustId nog niet bekend is
    WScript.Quit(1);
}

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

try
{
    var sql = "SELECT fac_version_cust FROM fac_version";
    var oRs = Oracle.Execute(sql);
    var CustId = oRs(0).Value;
    oRs.Close();
    __Log("\nStarting at " + new Date());
    __Log("CustId: " + CustId);
     var WshNetwork = new ActiveXObject("WScript.Network");
    __Log("User: " + WshNetwork.UserDomain + "\\" + WshNetwork.UserName);

    var sql = "BEGIN fac.initsession(NULL); END;";
    var oRs = Oracle.Execute(sql)

    __Log("Start cleanup_bijlagen")
    cleanup_bijlagen();

    __Log("Start cleanup_temp")
    cleanup_temp();

}
catch(e)
{
    __Log("ERROR: " + e.description)
    throw e;
}

Oracle.Close();
__Log("Done at " + new Date());

