// Compiled using ts2gas 3.6.5 (TypeScript 4.3.2)
var exports = exports || {};
var module = module || { exports: exports };
Object.defineProperty(exports, "__esModule", { value: true });
exports.executeLongRun = exports.LongRun = void 0;
//import Properties = GoogleAppsScript.Properties.Properties;
/**
 * Long-Running Support
 */
var LongRun = /** @class */ (function () {
    /**
     * Private constructor
     * @private
     */
    function LongRun() {
        /** start time map */
        this.startTimeMap = {};
    }
    Object.defineProperty(LongRun, "instance", {
        /**
         * Returns singleton instance.
         */
        get: function () {
            if (!this._instance) {
                this._instance = new LongRun();
            }
            return this._instance;
        },
        enumerable: false,
        configurable: true
    });
    /**
     * Returns if function is running now.
     * @param funcName
     */
    LongRun.prototype.isRunning = function (funcName) {
        // get spreadsheet properties
        var properties = PropertiesService.getScriptProperties();
        var running = properties.getProperty(LongRun.PREFIX_RUNNING + funcName);
        return !(running == null || running === '');
    };
    /**
     * Sets the function is running
     * @param funcName
     * @param running
     */
    LongRun.prototype.setRunning = function (funcName, running) {
        var properties = PropertiesService.getScriptProperties();
        var key = LongRun.PREFIX_RUNNING + funcName;
        if (running) {
            properties.setProperty(key, "running");
        }
        else {
            properties.deleteProperty(key);
        }
    };
    /**
     * Sets max execution seconds
     * @param seconds
     */
    LongRun.prototype.setMaxExecutionSeconds = function (seconds) {
        LongRun.RUNNING_MAX_SECONDS = seconds;
    };
    /**
     * Sets the trigger's delay minutes
     * @param minutes
     */
    LongRun.prototype.setTriggerDelayMinutes = function (minutes) {
        LongRun.RUNNING_DELAY_MINUTES = minutes;
    };
    /**
     * Returns the function parameters
     * @param funcName
     */
    LongRun.prototype.getParameters = function (funcName) {
        var properties = PropertiesService.getScriptProperties();
        var parameters = properties.getProperty(LongRun.PREFIX_OPTION + funcName);
        if (parameters != null) {
            return parameters.split(',');
        }
        else {
            return [];
        }
    };
    /**
     * Sets the function parameters.
     * @param funcName
     * @param parameters
     */
    LongRun.prototype.setParameters = function (funcName, parameters) {
        var properties = PropertiesService.getScriptProperties();
        if (parameters != null) {
            properties.setProperty(LongRun.PREFIX_OPTION + funcName, parameters.join(','));
        }
        else {
            properties.deleteProperty(LongRun.PREFIX_OPTION + funcName);
        }
    };
    /**
     * Starts or Resumes Long-Run process.
     * @param funcName
     * @returns start index ( 0 for the first time )
     */
    LongRun.prototype.startOrResume = function (funcName) {
        // save start time
        this.startTimeMap[funcName] = new Date().getTime();
        // get properties of spreadsheet
        var properties = PropertiesService.getScriptProperties();
        // set running-flag
        this.setRunning(funcName, true);
        // if the trigger exists, delete it.
        this.deleteTrigger(LongRun.PREFIX_TRIGGER_KEY + funcName);
        // get start index
        var startPos = parseInt(properties.getProperty(LongRun.PREFIX_START_POS + funcName));
        if (!startPos) {
            return 0;
        }
        else {
            return startPos;
        }
    };
    /**
     * Determines whether the process should be suspended.
     * If it should be suspended, the next trigger will be registered.
     * @param funcName
     * @param nextIndex - start position when resuming
     * @return true - it should be suspended
     */
    LongRun.prototype.checkShouldSuspend = function (funcName, nextIndex) {
        var startTime = this.startTimeMap[funcName];
        var diff = (new Date().getTime() - startTime) / 1000;
        // If it's past the specified time, suspend the process
        if (diff >= LongRun.RUNNING_MAX_SECONDS) {
            // register the next trigger and set running-flag off
            this.registerNextTrigger(funcName, nextIndex);
            return true;
        }
        else {
            return false;
        }
    };
    /**
     * Resets Long-Running variables
     * @param funcName
     */
    LongRun.prototype.reset = function (funcName) {
        // delete trigger
        this.deleteTrigger(LongRun.PREFIX_TRIGGER_KEY + funcName);
        // delete spreadsheet properties
        var properties = PropertiesService.getScriptProperties();
        properties.deleteProperty(LongRun.PREFIX_START_POS + funcName);
        properties.deleteProperty(LongRun.PREFIX_OPTION + funcName);
        properties.deleteProperty(LongRun.PREFIX_RUNNING + funcName);
        properties.deleteProperty(LongRun.PREFIX_TRIGGER_KEY + funcName);
    };
    /**
     * Resets Long-Running variables if there is no next trigger.
     * Returns whether the command has finished or not.
     * @param funcName
     */
    LongRun.prototype.end = function (funcName) {
        var ret = false;
        if (!this.existsNextTrigger(funcName)) {
            this.reset(funcName);
            ret = true;
        }
        return ret;
    };
    /**
     * Returns if there is next trigger.
     * @param funcName
     */
    LongRun.prototype.existsNextTrigger = function (funcName) {
        var triggerId = PropertiesService.getScriptProperties().getProperty(LongRun.PREFIX_TRIGGER_KEY + funcName);
        return triggerId != null;
    };
    /**
     * register the next trigger and set running-flag off
     * @param funcName
     * @param nextIndex - start position when resuming
     */
    LongRun.prototype.registerNextTrigger = function (funcName, nextIndex) {
        // get spreadsheet properties
        var properties = PropertiesService.getScriptProperties();
        properties.setProperty(LongRun.PREFIX_START_POS + funcName, String(nextIndex)); // save next start position
        this.setTrigger(LongRun.PREFIX_TRIGGER_KEY + funcName, funcName); // set trigger
        // turn off running-flag
        properties.deleteProperty(LongRun.PREFIX_RUNNING + funcName);
    };
    /**
     * Deletes the trigger
     * @param triggerKey
     */
    LongRun.prototype.deleteTrigger = function (triggerKey) {
        var triggerId = PropertiesService.getScriptProperties().getProperty(triggerKey);
        if (!triggerId)
            return;
        ScriptApp.getProjectTriggers().filter(function (trigger) {
            return trigger.getUniqueId() == triggerId;
        })
            .forEach(function (trigger) {
            ScriptApp.deleteTrigger(trigger);
        });
        PropertiesService.getScriptProperties().deleteProperty(triggerKey);
    };
    /**
     * Sets a trigger
     * @param triggerKey
     * @param funcName
     */
    LongRun.prototype.setTrigger = function (triggerKey, funcName) {
        this.deleteTrigger(triggerKey); // delete if exists.
        var dt = new Date();
        dt.setMinutes(dt.getMinutes() + LongRun.RUNNING_DELAY_MINUTES); // will execute after the specified time
        var triggerId = ScriptApp.newTrigger(funcName).timeBased().at(dt).create().getUniqueId();
        // save the trigger id to delete the trigger later.
        PropertiesService.getScriptProperties().setProperty(triggerKey, triggerId);
    };
    // constants
    LongRun.PREFIX_RUNNING = "running_";
    LongRun.PREFIX_TRIGGER_KEY = "trigger_";
    LongRun.PREFIX_START_POS = "start_";
    LongRun.PREFIX_OPTION = "option_";
    LongRun.RUNNING_MAX_SECONDS = 4 * 60;
    LongRun.RUNNING_DELAY_MINUTES = 1;
    LongRun.EXECUTE_LONGRUN_FUNCNAME = "_executeLongRun";
    return LongRun;
}());
exports.LongRun = LongRun;
/**
 * A function allows you to easily execute long-run task using the LongRun class.
 *
 * @param mainFuncName - Name of the function to be executed each time.
 * @param loopCount - Number of times to execute the main function.
 * @param params - Parameters passed to each function (string[]). (optional)
 * @param initializerName - Name of the first function to be executed on first or restart. (optional)
 * @param finalizerName - Name of the function to be called on interruption or when all processing is complete. (optional)
 *
 * The definition of each function to be passed should be as follows.
 *  - Main function:  function [function name](index: number, params: string[]) {...}
 *  - Initializer:    function [function name](startIndex: number, params: string[]) {...}
 *  - Finalizer:      function [function name](isFinished: boolean, params: string[]) {...}
 *
 * Note that it is not possible to use executeLongRun() to execute different long-time processes simultaneously.
 */
function executeLongRun(mainFuncName, loopCount, params, initializerName, finalizerName) {
    if (params === void 0) { params = null; }
    if (initializerName === void 0) { initializerName = null; }
    if (finalizerName === void 0) { finalizerName = null; }
    var longRunParams = [];
    longRunParams.push(mainFuncName);
    longRunParams.push(String(loopCount));
    longRunParams.push(initializerName === null ? '' : initializerName);
    longRunParams.push(finalizerName === null ? '' : finalizerName);
    if (params != null && params.length > 0) {
        longRunParams.push(params.join(','));
    }
    LongRun.instance.setParameters(LongRun.EXECUTE_LONGRUN_FUNCNAME, longRunParams);
    _executeLongRun();
}
exports.executeLongRun = executeLongRun;
/**
 * The main body of executeLongRun
 */
function _executeLongRun() {
    var longRun = LongRun.instance;
    // get parameters
    var longRunParams = longRun.getParameters(LongRun.EXECUTE_LONGRUN_FUNCNAME);
    var mainFuncName = longRunParams[0];
    var loopCount = parseInt(longRunParams[1]);
    var initializerName = longRunParams[2];
    var finalizerName = longRunParams[3];
    var params = [];
    for (var i = 4; i < longRunParams.length; i++) {
        params.push('"' + longRunParams[i] + '"');
    }
    var paramsLiteral = '[' + params.join(',') + ']';
    var startIndex = longRun.startOrResume(LongRun.EXECUTE_LONGRUN_FUNCNAME);
    try {
        // *** call initializer ***
        if (initializerName != null && initializerName.length > 0) {
            eval(initializerName + '(' + startIndex + ',' + paramsLiteral + ')');
        }
        // execute the iterative process.
        for (var i = startIndex; i < loopCount; i++) {
            // Each time before executing a process, you need to check if it should be stopped or not.
            if (longRun.checkShouldSuspend(LongRun.EXECUTE_LONGRUN_FUNCNAME, i)) {
                // if checkShouldSuspend() returns true, the next trigger has been set
                // and you should get out of the loop.
                console.log('*** The process has been suspended. ***');
                break;
            }
            // *** call main process ***
            eval(mainFuncName + '(' + i + ',' + paramsLiteral + ')');
        }
    }
    catch (e) {
        console.log(e.message);
    }
    finally {
        // you must always call end() to reset the long-running variables if there is no next trigger.
        var finished = longRun.end(LongRun.EXECUTE_LONGRUN_FUNCNAME);
        // *** call finalizer ***
        if (finalizerName != null && finalizerName.length > 0) {
            eval(finalizerName + '(' + finished + ',' + paramsLiteral + ')');
        }
    }
}