const Observable = global.Observable = require('../src/core/Observer');
const Store = require('../src/core/data/store/Store');
const assert = require('chai').assert;

describe('store', function() {

    it('should set and get simple values', function() {
        const s = new Store({});
        s.set('a', 5);
        assert.equal(s.get('a'), 5);
        s.set('b', 'abc');
        assert.equal(s.get('b'), 'abc');
        assert.equal(s.get('a'), 5);
        s.set('c', [1,2,3]);
        assert.deepEqual(s.get('c'), [1,2,3]);
    });
    it('should set complex values', function () {
        const s = new Store({});
        s.set('a.b.c', 33);
        assert.equal(s.get('a.b.c'), 33);
        s.set('a.b', {c:12, d: 20});
        assert.equal(s.get('a.b.c'), 12);
        assert.equal(s.get('a.b.d'), 20);
        s.set('a.b', null);
        assert.equal(s.get('a.b.d'), void 0);
    });

    it('should fire changes for simple values', function () {
        const s = new Store({a:4, b: 5, c: 6});
        let list;
        s.on('change', function(path, val) {
            list.push({path, val})
        });

        list = [];
        s.set('a', 4);
        assert.equal(list.length, 0);


        list = [];
        s.set('b', 4);
        assert.equal(list.length, 1);
        assert.equal(list[0].path, 'b');
        assert.equal(list[0].val, 4);

        list = [];
        s.set('c', {kk: 2});
        assert.equal(list.length, 2);
        assert.equal(list[0].path, 'c.kk');
        assert.equal(list[0].val, 2);

        assert.equal(list[1].path, 'c');
        assert.deepEqual(list[1].val, {kk: 2});

    });
    const logList = function(list) {
        console.log(list.map(({path, val})=>`${path} > ${JSON.stringify(val)}`).join('\n'))
    };
    const fixList = function(list) {
        console.log(`assert.equal(list.length, ${list.length});`);
        console.log(list.map(
          ({path, val}, n)=>
`assert.equal(list[${n}].path, ${JSON.stringify(path)});
assert.deepEqual(list[${n}].val, ${JSON.stringify(val)});
`).join('\n')
        )
    };
    it('should fire changes for complex values', function () {
        const s = new Store({});
        let list;
        s.on('change', function(path, val) {
            list.push({path, val})
        });

        list = [];
        s.set('a.b.c', 33);
        assert.equal(list.length, 3);
        assert.equal(list[0].path, "a.b.c");
        assert.deepEqual(list[0].val, 33);

        assert.equal(list[1].path, "a.b");
        assert.deepEqual(list[1].val, {"c":33});

        assert.equal(list[2].path, "a");
        assert.deepEqual(list[2].val, {"b":{"c":33}});


        list = [];
        s.set('a.b', {c:12, d: 20});
        assert.equal(list.length, 2);
        assert.equal(list[0].path, "a.b.d");
        assert.deepEqual(list[0].val, 20);

        assert.equal(list[1].path, "a.b.c");
        assert.deepEqual(list[1].val, 12);


        list = [];
        s.set('a.b', null);
        assert.equal(list.length, 1);
        assert.equal(list[0].path, "a.b");
        assert.deepEqual(list[0].val, null);

        list = [];
        s.set('a.b', {c:12, d: 20});
        assert.equal(list.length, 3);
        assert.equal(list[0].path, "a.b.d");
        assert.deepEqual(list[0].val, 20);

        assert.equal(list[1].path, "a.b.c");
        assert.deepEqual(list[1].val, 12);

        assert.equal(list[2].path, "a.b");
        assert.deepEqual(list[2].val, {"c":12,"d":20});


        list = [];

        s.set('a.b', {x: {y:3}});
        assert.equal(list.length, 4);
        assert.equal(list[0].path, "a.b.d");
        assert.deepEqual(list[0].val, undefined);

        assert.equal(list[1].path, "a.b.c");
        assert.deepEqual(list[1].val, undefined);

        assert.equal(list[2].path, "a.b.x.y");
        assert.deepEqual(list[2].val, 3);

        assert.equal(list[3].path, "a.b.x");
        assert.deepEqual(list[3].val, {"y":3});





        //fixList(list)
    });
    it('should fire changes for even more complex values', function () {
        const s = new Store({});
        let list = [];
        s.on('change', function(path, val) {
            list.push({path, val})
        });
        let startVal;
        s.set('a.b', startVal = {c:12, d: {e:1, f: 2, g: [3, 4, {h: 5}]}});
        assert.deepEqual(s._props, {a:{b: startVal}})
        list = [];

        s.set('a.b', {c: 12, f: 22});
        assert.equal(list.length, 8);
        assert.equal(list[0].path, "a.b.d.g.2.h");
        assert.deepEqual(list[0].val, undefined);

        assert.equal(list[1].path, "a.b.d.g.2");
        assert.deepEqual(list[1].val, undefined);

        assert.equal(list[2].path, "a.b.d.g.1");
        assert.deepEqual(list[2].val, undefined);

        assert.equal(list[3].path, "a.b.d.g.0");
        assert.deepEqual(list[3].val, undefined);

        assert.equal(list[4].path, "a.b.d.g");
        assert.deepEqual(list[4].val, undefined);

        assert.equal(list[5].path, "a.b.d.f");
        assert.deepEqual(list[5].val, undefined);

        assert.equal(list[6].path, "a.b.d.e");
        assert.deepEqual(list[6].val, undefined);

        assert.equal(list[7].path, "a.b.f");
        assert.deepEqual(list[7].val, 22);



        console.log(JSON.stringify(s._props))
    })
});