"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
function isString(stringToCheck) {
    if (stringToCheck.constructor === String) {
        return true;
    }
    return typeof stringToCheck === "string" || stringToCheck instanceof String;
}
function walk(tree, f, parent, name) {
    if (tree.length !== undefined) {
        let index = 0;
        for (const item of tree) {
            if (item) {
                walk(item, f, tree, index++);
            }
        }
        return;
    }
    for (const i in tree) {
        if (!tree.hasOwnProperty(i)) {
            continue;
        }
        if (/^(parent|parentfield|tree)$/i.test(i)) {
            continue;
        }
        const v = tree[i];
        if (v && v !== tree) {
            if (isString(v)) {
                continue;
            }
            if (v.type !== undefined || v.length !== undefined) {
                walk(v, f, tree, i);
            }
        }
    }
    f(tree, parent, name);
}
function prepareDom(node, tree) {
    walk(node, (item, parent, name) => {
        item.parent = parent;
        item.parentField = name;
        if (tree) {
            item.tree = tree;
        }
    });
}
class TreeVisitor {
    tree;
    constructor(tree) {
        this.tree = tree;
        prepareDom(this.tree, this.tree);
    }
    walk(node, f) {
        walk(node, f);
    }
    visit(e) {
        if (!e) {
            return e;
        }
        let type = e.type;
        if (type) {
            type = type.substr(0, 1).toLowerCase() + type.substr(1);
            const visitor = this[type] || this.expression;
            return visitor.call(this, e);
        }
        if (e.length) {
            const list = [];
            for (const item of e) {
                list.push(this.visit(item));
            }
            return list;
        }
        return e;
    }
    expression(e) {
        // console.log('default expression ' + e.type);
        for (const i in e) {
            if (/parent|tree/i.test(i)) {
                continue;
            }
            const v = e[i];
            if (!v) {
                continue;
            }
            if (isString(v)) {
                continue;
            }
            e[i] = this.visit(v);
        }
        return e;
    }
}
exports.default = TreeVisitor;
//# sourceMappingURL=TreeVisitor.js.map