'use strict';

var UtilError = require("./UtilError");
var lodashLang = require('lodash/lang');

module.exports = {
    /*
     * Process JSON/Javascript rule set string
     * @document - document object
     * @context - additional objects will be used in rule set script
     * @ruleset - evaluated JSON/Javascript flow
     * @scope - additional scope objects will be plugged in to rule se scope
     */
    processJsonRuleset: function (document, context, ruleset, scope, callback) {
        try {
            logger.debug("In process JSON/Javascript Flow...");

            var ntf = {};
            ntf.document = document;
            ntf.context = context;
            if (context.isNew !== undefined) {
              ntf.isNew = context.isNew;
            }
            ntf.user = context.user;
            ntf.logger = context.logger;
            ntf.rsLogger = context.rsLogger;
            ntf.result = {status : null, message : null};
            ntf.scope = scope;
            ntf.runCount = 1;
            ntf.runCountMax = 100;
            ntf.callbackSuccessCompleted = false;
            ntf.documentSession = context.documentSession;

            var callbackSuccess = function () {
                if (!ntf.callbackSuccessCompleted) {
                    ntf.callbackSuccessCompleted = true;

                    ntf.result.status = 'SUCCESS';
                    ntf.result.message = null;
                    callback(ntf.result);
                } else {
                    var msg = "Multiple callbackSuccess calls detected. Please ensure the ruleset only has one callbackSuccess";
                    callbackError(msg);
                }
            };

            var callbackError = function (errMsg) {
                if (errMsg) {
                    if (lodashLang.isError(errMsg)) {
                        var name = errMsg.name;
                        errMsg = errMsg.message;
                    }
                }

                ntf.result.status = 'ERROR';
                ntf.result.message = UtilError.limitErrorMessage(errMsg);
                ntf.result.name = name;
                callback(ntf.result);
            };

            var callbackContinue = function (ntf) {

                // Check if looped too much
                ntf.runCount += 1;
                if (ntf.runCount > ntf.runCountMax) {
                    callbackError('Run Count exceeded -- check there is not a self-looping issue in your script.');
                }
                else {
                    logger.info("Re-executing ruleset in callbackContinue with count: " + ntf.runCount);
                    ruleset.mainRule(ntf, callbackContinue, callbackSuccess, callbackError);
                }
            };

            // In Main Rule
            ruleset.mainRule(ntf, callbackContinue, callbackSuccess, callbackError);

        } catch (e) {
            let msg = `Ruleset Not Found:`;
            if (context.ruleSetDoc) {
              const ruleSetName = context.ruleSetDoc.objectEventDescriptor;
               msg = `Errors in JSON/Javascript ruleset ${ruleSetName ? ruleSetName : 'n/a'}: `;
            }

            if (lodashLang.isError(e)) {
              msg += e.name + ' : ' + e.message;
            } else {
              msg += e;
            }
            logger.error(msg);
            if(scope.rsLogger) {
                scope.rsLogger.error(msg);
                scope.rsLogger.storeMessages();
            }

            callback({
                status: 'ERROR',
                message: UtilError.limitErrorMessage(msg)
            });

        }
    }

};
