"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var temen = require("balena-temen");
var cloneDeep = require("lodash/cloneDeep");
var get = require("lodash/get");
var isPlainObject = require("lodash/isPlainObject");
var merge = require("lodash/merge");
var set = require("lodash/set");
var runFormulas = function (schema, value) {
    var data = cloneDeep(value);
    replaceDataWithFormulaContent(schema, data);
    var evaluate;
    try {
        evaluate = temen.evaluate(data);
    }
    catch (e) {
        console.error('Caught error when evaluating formulas', e);
        evaluate = value;
    }
    var startingState = defaultValueForSchema(schema);
    return merge(startingState, value, evaluate);
};
exports.runFormulas = runFormulas;
var defaultValueForSchema = function (schema) {
    return schema.type === 'array' ? [] : {};
};
exports.defaultValueForSchema = defaultValueForSchema;
var replaceDataWithFormulaContent = function (schema, data) {
    var keys = getFormulaKeys(schema).map(function (path) {
        return {
            formula: get(schema, path),
            path: path.replace(/properties\./g, ''),
        };
    });
    keys.forEach(function (formula) {
        var fullPath = formula.path;
        var formulaText = formula.formula;
        if (!fullPath.includes('.items.')) {
            set(data, fullPath, formulaText);
        }
        else {
            var pathFragments = fullPath.split('.items.');
            replaceArrayWithFormulaContent(pathFragments, data, formulaText);
        }
    });
};
var replaceArrayWithFormulaContent = function (pathFragments, data, formulaText) {
    var firstFragment = pathFragments[0];
    var lastFragment = pathFragments[1];
    var array = data[firstFragment] || [];
    if (pathFragments.length > 2) {
        var subFragments_1 = pathFragments.slice(1, pathFragments.length);
        array.forEach(function (item) {
            replaceArrayWithFormulaContent(subFragments_1, item, formulaText);
        });
    }
    else {
        array.forEach(function (item) {
            set(item, lastFragment, formulaText);
        });
    }
};
var getFormulaKeys = function (obj, prefix) {
    if (prefix === void 0) { prefix = ''; }
    var keys = Object.keys(obj);
    prefix = prefix ? prefix + '.' : '';
    return keys.reduce(function (result, key) {
        if (isPlainObject(obj[key])) {
            result = result.concat(getFormulaKeys(obj[key], prefix + key));
        }
        else if (key === '$$formula') {
            result.push(prefix + key);
        }
        return result;
    }, []);
};
