'use strict';

import {expect} from "chai"
import {Node} from "../../../source/types/node.mjs";
import {NodeList} from "../../../source/types/nodelist.mjs";
import {NodeRecursiveIterator} from "../../../source/types/noderecursiveiterator.mjs";

describe('NodeList', function () {
    describe('#constructor', function () {
        it('should create an empty NodeList', function () {
            let nodeList = new NodeList();

            expect(nodeList.size).to.equal(0);
        });

        it('should create a NodeList from an array', function () {
            let nodeList = new NodeList([
                new Node('div'),
                new Node('div'),
                new Node('div')
            ]);

            expect(nodeList.size).to.equal(3);
        });

        it('should create a NodeList from a NodeList', function () {
            let nodeList = new NodeList([
                new Node('div'),
                new Node('div'),
                new Node('div')
            ]);

            let nodeList2 = new NodeList(nodeList);

            expect(nodeList2.size).to.equal(3);
        });
    });

    it('create NodeList', function () {
        expect(new NodeList()).is.instanceof(NodeList);
    })

    it('add Node', function () {
        expect(new NodeList().add(new Node())).to.be.instanceof(NodeList);
    })

    it('remove Node', function () {
        expect(new NodeList().remove(new Node())).to.be.instanceof(NodeList);
    })

    it('has unknown Node', function () {
        expect(new NodeList().has(new Node)).to.be.false;
    })

    it('has added Node', function () {
        const n = new Node;
        expect(new NodeList().add(n).has(n)).to.be.true;
    })

    it('throw exception', function () {
        expect(() => new NodeList().add(1)).to.throw(Error);
    })

    it('check level', function () {

        const root = new Node('root');

        const n1 = new Node('n1');
        const n2 = new Node('n2');
        const n3 = new Node('n3');
        const n4 = new Node('n4');

        const n11 = new Node('n11');
        const n12 = new Node('n12');
        const n13 = new Node('n13');

        const n21 = new Node('n21');
        const n22 = new Node('n22');
        const n23 = new Node('n23');

        const n41 = new Node('n41');
        const n42 = new Node('n42');

        const n411 = new Node('n411');
        const n412 = new Node('n412');
        const n413 = new Node('n413');

        const n4121 = new Node('n4121');

        root.appendChild(n1).appendChild(n2).appendChild(n3).appendChild(n4);
        n1.appendChild(n11).appendChild(n12).appendChild(n13);
        n2.appendChild(n21).appendChild(n22).appendChild(n23);
        n4.appendChild(n41).appendChild(n42);
        n41.appendChild(n411).appendChild(n412).appendChild(n413);
        n412.appendChild(n4121);

        let iterator = new NodeRecursiveIterator(root);

        let result = [];
        for (const n of iterator) {
            expect(n).to.be.an.instanceof(Node);
            result.push(n.value + ":" + n.level);
        }


        expect(result).to.deep.equal([
            'root:0',
            'n1:1',
            'n11:2',
            'n12:2',
            'n13:2',
            'n2:1',
            'n21:2',
            'n22:2',
            'n23:2',
            'n3:1',
            'n4:1',
            'n41:2',
            'n411:3',
            'n412:3',
            'n4121:4',
            'n413:3',
            'n42:2'

        ]);

        n4121.appendChild(new Node('n41211'));

        iterator = new NodeRecursiveIterator(root);
        result = [];
        for (const n of iterator) {
            expect(n).to.be.an.instanceof(Node);
            result.push(n.value + ":" + n.level);
        }

        expect(result).to.deep.equal([
            'root:0',
            'n1:1',
            'n11:2',
            'n12:2',
            'n13:2',
            'n2:1',
            'n21:2',
            'n22:2',
            'n23:2',
            'n3:1',
            'n4:1',
            'n41:2',
            'n411:3',
            'n412:3',
            'n4121:4',
            'n41211:5',
            'n413:3',
            'n42:2'

        ]);


        const bb = new Node('bb') // big bang

        bb.appendChild(root);
        iterator = new NodeRecursiveIterator(bb);

        result = [];
        for (const n of iterator) {
            expect(n).to.be.an.instanceof(Node);
            result.push(n.value + ":" + n.level);
        }

        expect(result).to.deep.equal([
            'bb:0',
            'root:1',
            'n1:2',
            'n11:3',
            'n12:3',
            'n13:3',
            'n2:2',
            'n21:3',
            'n22:3',
            'n23:3',
            'n3:2',
            'n4:2',
            'n41:3',
            'n411:4',
            'n412:4',
            'n4121:5',
            'n41211:6',
            'n413:4',
            'n42:3'

        ]);

    })

    describe('Levels', function () {

        it('n2 should level 2', function () {

            const n0 = new Node('abc');

            const n1 = new Node('def');
            n0.appendChild(n1)

            const n2 = new Node('ghi');
            n1.appendChild(n2);

            const n3 = new Node('jkl');
            n2.appendChild(n3);

            expect(n0.level).to.be.equal(0);
            expect(n1.level).to.be.equal(1);
            expect(n2.level).to.be.equal(2);
            expect(n3.level).to.be.equal(3);

        });
    });


    describe('toString()', function () {

        it('should output empty string', function () {
            const node = new Node();
            expect(node.toString()).is.equal('');
        });

        it('should output string', function () {
            const n0 = new Node('abc');

            const n1 = new Node('def');
            n0.appendChild(n1)

            const n11 = new Node('ghi');
            n0.appendChild(n11)

            const n2 = new Node('jkl');
            n1.appendChild(n2);

            const n3 = new Node('mno');
            n1.appendChild(n3);

            const n4 = new Node('pqr');
            n2.appendChild(n4);

            expect(n2.level).to.be.equal(2)

            //console.log(n0.toString());
            // expect(n0.toString()).is.equal('');
        });
    });


});