JSFormatterDebug = class JSFormatterDebug
{
    constructor(sourceText, sourceType)
    {
        let tree = esprima.parse(sourceText, {attachComment: true, range: true, tokens: true, sourceType});
        let walker = new ESTreeWalker(this._before.bind(this), this._after.bind(this));

        this._statistics = {
            nodeTypes: {},
            tokenTypes: {},
        };

        this._nextCommentId = 1;

        this._lines = [];
        this._tokens = tree.tokens;
        this._tokensLength = this._tokens.length;
        this._tokenIndex = 0;
        this._debugHeader();
        walker.walk(tree);
        this._debugAfterProgramNode(tree);
        this._debugFooter();
    }

    // Public

    get debugText()
    {
        return this._lines.join("\n");
    }

    // Private

    _pad(str, width)
    {
        let result = str;
        for (let toPad = width - result.length; toPad > 0; --toPad)
            result += " ";
        return result;
    }

    _debugHeader()
    {
        let nodeString = this._pad("Node Type", 25);
        let tokenTypeString = this._pad("Token Type", 20);
        let tokenValueString = "Token Value";
        this._lines.push(nodeString + " " + tokenTypeString + " " + tokenValueString);
        this._lines.push("-".repeat(25) + " " + "-".repeat(20) + " " + "-".repeat(20));
    }

    _debugFooter()
    {
        this._lines.push("");
        this._lines.push(this._pad("Node Type", 25) + " Frequency");
        this._lines.push("-".repeat(25) + " " + "-".repeat(15));
        let groups = [];
        for (let key of Object.keys(this._statistics.nodeTypes))
            groups.push([key, this._statistics.nodeTypes[key]]);
        groups.sort((a, b) => b[1] - a[1]);
        for (let [nodeType, frequency] of groups)
            this._lines.push(this._pad(nodeType, 25) + " " + frequency);

        this._lines.push("");
        this._lines.push(this._pad("Token Type", 20) + " Frequency");
        this._lines.push("-".repeat(20) + " " + "-".repeat(15));
        groups = [];
        for (let key of Object.keys(this._statistics.tokenTypes))
            groups.push([key, this._statistics.tokenTypes[key]]);
        groups.sort((a, b) => b[1] - a[1]);
        for (let [tokenType, frequency] of groups)
            this._lines.push(this._pad(tokenType, 20) + " " + frequency);
    }

    _debug(node, token)
    {
        let nodeString = this._pad(node.type, 25);
        let tokenTypeString = this._pad(token.type, 20);
        let tokenValueString = token.value;
        this._lines.push(nodeString + " " + tokenTypeString + " " + tokenValueString);

        if (!this._statistics.nodeTypes[node.type])
            this._statistics.nodeTypes[node.type] = 0;
        if (!this._statistics.tokenTypes[token.type])
            this._statistics.tokenTypes[token.type] = 0;
        this._statistics.nodeTypes[node.type]++;
        this._statistics.tokenTypes[token.type]++;
    }

    _debugComments(comments, trailing)
    {
        for (let comment of comments) {
            if (!comment.__id)
                comment.__id = this._nextCommentId++;
            let nodeString = this._pad(`** ${trailing ? "T " :"L "}Comment (${comment.__id})`, 25);
            let commentTypeString = this._pad(comment.type, 20);
            let commentValueString = comment.value;
            this._lines.push(nodeString + " " + commentTypeString + " " + commentValueString);
        }
    }

    _debugAfterProgramNode(programNode)
    {
        if (programNode.body.length) {
            let lastNode = programNode.body[programNode.body.length - 1];
            if (lastNode.trailingComments)
                this._debugComments(lastNode.trailingComments, true);
        } else {
            if (programNode.leadingComments)
                this._debugComments(programNode.leadingComments);
            if (programNode.trailingComments)
                this._debugComments(programNode.trailingComments, true);
        }
    }

    _before(node)
    {
        if (!node.parent)
            return;

        while (this._tokenIndex < this._tokensLength && this._tokens[this._tokenIndex].range[0] < node.range[0]) {
            let token = this._tokens[this._tokenIndex++];
            this._debug(node.parent, token);
        }

        if (node.leadingComments)
            this._debugComments(node.leadingComments);
    }

    _after(node)
    {
        while (this._tokenIndex < this._tokensLength && this._tokens[this._tokenIndex].range[0] < node.range[1]) {
            let token = this._tokens[this._tokenIndex++];
            this._debug(node, token);
        }

        if (node.trailingComments)
            this._debugComments(node.trailingComments, true);
    }
}
