"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.unescape = unescape;
exports._evaluate = _evaluate;
exports.evaluate = evaluate;
const fromUnitBundle_1 = require("./fromUnitBundle");
const parser_1 = require("./parser");
function unescape(str) {
    return str.replace(/\\([nrtbfv\\'"0])/g, (match, ch) => {
        switch (ch) {
            case 'n':
                return '\n';
            case 'r':
                return '\r';
            case 't':
                return '\t';
            case 'b':
                return '\b';
            case 'f':
                return '\f';
            case 'v':
                return '\v';
            case '\\':
                return '\\';
            case '"':
                return '"';
            case '0':
                return '\0';
            default:
                return match;
        }
    });
}
function _evaluate(tree, specs, classes, resolver = () => {
    return undefined;
}) {
    const { value, children } = tree;
    switch (tree.type) {
        case parser_1.TreeNodeType.Identifier:
            return value;
        case parser_1.TreeNodeType.Null:
            return null;
        case parser_1.TreeNodeType.StringLiteral:
            return unescape(value.substring(1, value.length - 1));
        case parser_1.TreeNodeType.BooleanLiteral:
            return value === 'true' ? true : false;
        case parser_1.TreeNodeType.NumberLiteral:
            return Number.parseFloat(value);
        case parser_1.TreeNodeType.ArrayLiteral: {
            const array = [];
            for (const element of children) {
                if (element.type !== parser_1.TreeNodeType.Invalid) {
                    array.push(_evaluate(element, specs, classes, resolver));
                }
            }
            return array;
        }
        case parser_1.TreeNodeType.ObjectLiteral: {
            const object = {};
            for (const entry of children) {
                if (entry.type === parser_1.TreeNodeType.KeyValue) {
                    const [key, value] = entry.children;
                    object[_evaluate(key, specs, classes)] = _evaluate((value.value && value) || key, specs, classes, resolver);
                }
                else if ((0, parser_1._isValidObjKeyType)(entry)) {
                    object[entry.value] = entry.value;
                }
            }
            return object;
        }
        case parser_1.TreeNodeType.Unit: {
            const str = value.substring(1);
            const bundle = evaluate(str, specs, classes);
            return (0, fromUnitBundle_1.fromUnitBundle)(bundle, specs, classes);
        }
        case parser_1.TreeNodeType.Url: {
            return resolver(value);
        }
        default:
            throw new Error('invalid data string');
    }
}
function evaluate(value, specs, classes, resolver = () => {
    return undefined;
}) {
    const tree = (0, parser_1.getTree)(value, false, false);
    return _evaluate(tree, specs, classes, resolver);
}
//# sourceMappingURL=evaluate.js.map