// SPDX-License-Identifier: Apache-2.0
import { expect } from 'chai';
import { Lexer } from '../../../../../src/data/key/lexer/lexer.js';
import { Forest } from '../../../../../src/data/key/lexer/forest.js';
import { ConfigKeyError } from '../../../../../src/data/key/config-key-error.js';
function overlappingPathLexer() {
    const lexerMap = new Map([
        ['root.object.value1', '1'],
        ['root.object.value2', '2'],
        ['root.object.value3', '3'],
        ['root.array.0.index1', '4'],
        ['root.array.0.index2', '5'],
        ['root.array.0.index3', '6'],
        ['deployments.0.clusters.0', 'true'],
        ['deployments.0.clusters.1', 'false'],
        ['deployments.0.settings.0.0', 'bob'],
        ['deployments.0.settings.0.1', 'charlie'],
    ]);
    const lexer = new Lexer(lexerMap);
    lexer.renderTrees();
    expect(lexer.rootNodes).to.have.lengthOf(2);
    const rootNode = lexer.rootNodes.find(v => v.name === 'root');
    expect(rootNode.name).to.equal('root');
    expect(rootNode.children).to.have.lengthOf(2);
    const subObjectNode = rootNode.children.find(v => v.name === 'object');
    expect(subObjectNode).to.not.be.undefined.and.not.be.null;
    expect(subObjectNode.children).to.have.lengthOf(3);
    const subArrayNode = rootNode.children.find(v => v.name === 'array');
    expect(subArrayNode).to.not.be.undefined.and.not.be.null;
    expect(subArrayNode.children).to.have.lengthOf(1);
    expect(subArrayNode.isArray()).to.be.true;
    const subArrayIndexNode = subArrayNode.children[0];
    expect(subArrayIndexNode).to.not.be.undefined.and.not.be.null;
    expect(subArrayIndexNode.name).to.equal('0');
    expect(subArrayIndexNode.isArrayIndex()).to.be.true;
    expect(subArrayIndexNode.children).to.have.lengthOf(3);
    const index1Node = subArrayIndexNode.children.find(v => v.name === 'index1');
    expect(index1Node).to.not.be.undefined.and.not.be.null;
    expect(index1Node.isLeaf()).to.be.true;
    expect(index1Node.value).to.be.equal('4');
    const deploymentsNode = lexer.rootNodes.find(v => v.name === 'deployments');
    expect(deploymentsNode).to.not.be.undefined.and.not.be.null;
    expect(deploymentsNode.children).to.have.lengthOf(1);
    expect(deploymentsNode.isArray()).to.be.true;
    const deploymentsArrayIndexNode = deploymentsNode.children[0];
    expect(deploymentsArrayIndexNode).to.not.be.undefined.and.not.be.null;
    expect(deploymentsArrayIndexNode.isArrayIndex()).to.be.true;
    const clustersNode = deploymentsArrayIndexNode.children[0];
    expect(clustersNode).to.not.be.undefined.and.not.be.null;
    expect(clustersNode.name).to.equal('clusters');
    expect(clustersNode.isArray()).to.be.true;
    expect(clustersNode.children).to.have.lengthOf(2);
    const clustersArrayIndex0Node = clustersNode.children[0];
    expect(clustersArrayIndex0Node).to.not.be.undefined.and.not.be.null;
    expect(clustersArrayIndex0Node.isArrayIndex()).to.be.true;
    expect(clustersArrayIndex0Node.isLeaf()).to.be.true;
    expect(clustersArrayIndex0Node.value).to.be.equal('true');
    const clustersArrayIndex1Node = clustersNode.children[1];
    expect(clustersArrayIndex1Node).to.not.be.undefined.and.not.be.null;
    expect(clustersArrayIndex1Node.isArrayIndex()).to.be.true;
    expect(clustersArrayIndex1Node.isLeaf()).to.be.true;
    expect(clustersArrayIndex1Node.value).to.be.equal('false');
    const settingsNode = deploymentsArrayIndexNode.children[1];
    expect(settingsNode).to.not.be.undefined.and.not.be.null;
    expect(settingsNode.name).to.equal('settings');
    expect(settingsNode.isArray()).to.be.true;
    expect(settingsNode.children).to.have.lengthOf(1);
    const settingsArrayIndex0Node = settingsNode.children[0];
    expect(settingsArrayIndex0Node).to.not.be.undefined.and.not.be.null;
    expect(settingsArrayIndex0Node.name).to.equal('0');
    expect(settingsArrayIndex0Node.isArrayIndex()).to.be.true;
    expect(settingsArrayIndex0Node.children).to.have.lengthOf(2);
    const settingsArrayIndex0Index0Node = settingsArrayIndex0Node.children[0];
    expect(settingsArrayIndex0Index0Node).to.not.be.undefined.and.not.be.null;
    expect(settingsArrayIndex0Index0Node.name).to.equal('0');
    expect(settingsArrayIndex0Index0Node.isLeaf()).to.be.true;
    expect(settingsArrayIndex0Index0Node.value).to.be.equal('bob');
    const settingsArrayIndex0Index1Node = settingsArrayIndex0Node.children[1];
    expect(settingsArrayIndex0Index1Node).to.not.be.undefined.and.not.be.null;
    expect(settingsArrayIndex0Index1Node.name).to.equal('1');
    expect(settingsArrayIndex0Index1Node.isLeaf()).to.be.true;
    expect(settingsArrayIndex0Index1Node.value).to.be.equal('charlie');
    return {
        lexer,
        rootNode,
        subObjectNode,
        subArrayNode,
        subArrayIndexNode,
        deploymentsNode,
        deploymentsArrayIndexNode,
        clustersNode,
    };
}
describe('Lexer', () => {
    it('with empty token in constructor should throw error', () => {
        expect(() => {
            new Lexer(null);
        }).to.throw('tokens must be provided');
    });
    it('with empty formatter in constructor should throw error', () => {
        expect(() => {
            new Lexer(new Map(), null);
        }).to.throw('formatter must be provided');
    });
    it('get rootNodes should return empty array', () => {
        const lexer = new Lexer(new Map());
        expect(lexer.rootNodes).to.be.empty;
    });
    it('rootNodeFor with array segment', () => {
        const lexer = new Lexer(new Map());
        // @ts-expect-error - access private method for testing
        const node = lexer.rootNodeFor(['secret', '42', 'everything', 'is', '42', 'true']);
        expect(node.name).to.equal('secret');
        expect(node.isArray()).to.be.true;
    });
    it('processKeys with an array segment', () => {
        const lexerMap = new Map([
            ['secret.42.is.everything', 'true'],
            ['everything-is-42', 'true'],
            ['secret.42.is.42', 'true'],
            ['42.is.everything', 'true'],
            ['array.0.is.everything', 'true'],
            ['array.1.is.everything', 'true'],
            ['array.alpha.2.is.everything', 'true'],
        ]);
        let lexer = new Lexer(lexerMap);
        expect(() => lexer.rootNodes).to.throw(ConfigKeyError, "Cannot add a leaf node to an array node [ parent: 'secret.42.is', child: 'everything' ]");
        lexerMap.delete('secret.42.is.everything');
        lexer = new Lexer(lexerMap);
        const nodes = lexer.rootNodes;
        expect(nodes).to.have.lengthOf(4);
    });
    it('processKeys works with overlapping paths', () => {
        overlappingPathLexer();
    });
    it('addValue works with overlapping paths', () => {
        const { lexer, rootNode, subObjectNode, subArrayIndexNode } = overlappingPathLexer();
        lexer.addValue('root.array.0.index4', '7');
        lexer.addValue('root.object.value4', '8');
        lexer.addValue('root.object.clusterRef', 'SoloCheck');
        expect(lexer.rootNodes).to.have.lengthOf(2);
        expect(rootNode.children).to.have.lengthOf(2);
        expect(subObjectNode.children).to.have.lengthOf(5);
        expect(subArrayIndexNode.children).to.have.lengthOf(4);
        const index4Node = subArrayIndexNode.children.find((v) => v.name === 'index4');
        expect(index4Node).to.not.be.undefined.and.not.be.null;
        expect(index4Node.isLeaf()).to.be.true;
        expect(index4Node.value).to.be.equal('7');
        expect(subObjectNode.children.some((v) => v.name === 'clusterref')).to.be.false;
        expect(subObjectNode.children.some((v) => v.name === 'clusterRef')).to.be.true;
        const value4Node = subObjectNode.children.find((v) => v.name === 'value4');
        expect(value4Node).to.not.be.undefined.and.not.be.null;
        expect(value4Node.isLeaf()).to.be.true;
        expect(value4Node.value).to.be.equal('8');
        const clusterReference = subObjectNode.children.find((v) => v.name === 'clusterRef');
        expect(clusterReference).to.not.be.undefined.and.not.be.null;
        expect(clusterReference.isLeaf()).to.be.true;
        expect(clusterReference.value).to.be.equal('SoloCheck');
    });
    it('replaceValue works with overlapping paths', () => {
        const { lexer, rootNode, subObjectNode, subArrayNode, subArrayIndexNode } = overlappingPathLexer();
        const forest = Forest.fromLexer(lexer);
        lexer.replaceValue(forest.nodeFor('root.array.0.index1'), '9');
        lexer.replaceValue(forest.nodeFor('root.object.value1'), '10');
        expect(lexer.rootNodes).to.have.lengthOf(2);
        expect(rootNode.children).to.have.lengthOf(2);
        expect(subObjectNode.children).to.have.lengthOf(3);
        expect(subArrayNode.children).to.have.lengthOf(1);
        expect(subArrayIndexNode.children).to.have.lengthOf(3);
        const index1Node = subArrayIndexNode.children.find(v => v.name === 'index1');
        expect(index1Node).to.not.be.undefined.and.not.be.null;
        expect(index1Node.isLeaf()).to.be.true;
        expect(index1Node.value).to.be.equal('9');
        const value1Node = subObjectNode.children.find(v => v.name === 'value1');
        expect(value1Node).to.not.be.undefined.and.not.be.null;
        expect(value1Node.isLeaf()).to.be.true;
        expect(value1Node.value).to.be.equal('10');
    });
});
//# sourceMappingURL=lexer.test.js.map