"use strict";

import {expect} from "chai"
import {buildMap} from "../../../source/data/buildmap.mjs";


describe('buildMap', function () {

    let convertMapResult = function (r) {
        if (r instanceof Map) {
            r = Object.fromEntries(r);
            if (r instanceof Array) {
                r = r.map((e) => {
                    return convertMapResult(e);
                })
            } else if (typeof r === "object") {
                for (const [k, o] of Object.entries(r)) {
                    r[k] = convertMapResult(o);
                }
            }
        }

        return r;
    }

    describe('build Map with callback', function () {
        it('definition should return map with sub and parent keys', function () {

            let obj = {
                "data": [
                    {
                        "id": 10,
                        "name": "Cassandra",
                        "enrichment": {
                            variants: [
                                {
                                    sku: 1, label: "XXS", price: [
                                        {vk: '12.12 €'},
                                        {vk: '12.12 €'}
                                    ]
                                },
                                {
                                    sku: 2, label: "XS", price: [
                                        {vk: '22.12 €'},
                                        {vk: '22.12 €'}
                                    ]
                                },
                                {
                                    sku: 3, label: "S", price: [
                                        {vk: '32.12 €'},
                                        {vk: '32.12 €'}
                                    ]
                                },
                                {
                                    sku: 4, label: "L", price: [
                                        {vk: '42.12 €'},
                                        {vk: '42.12 €'}
                                    ]
                                }
                            ]

                        }
                    },
                    {
                        "id": 20,
                        "name": "Yessey!",
                        "enrichment": {
                            variants: [
                                {
                                    sku: 1, label: "XXS", price: [
                                        {vk: '12.12 €'},
                                        {vk: '12.12 €'}
                                    ]
                                },
                                {
                                    sku: 2, label: "XS", price: [
                                        {vk: '22.12 €'},
                                        {vk: '22.12 €'}
                                    ]
                                },
                                {
                                    sku: 3, label: "S", price: [
                                        {vk: '32.12 €'},
                                        {vk: '32.12 €'}
                                    ]
                                },
                                {
                                    sku: 4, label: "L", price: [
                                        {vk: '42.12 €'},
                                        {vk: '42.12 €'}
                                    ]
                                }
                            ]

                        }
                    }
                ]
            };

            let callback = function (subject) {
                let m = new Map;

                for (const [i, b] of Object.entries(subject.data)) {

                    let key1 = i;

                    for (const [j, c] of Object.entries(b.enrichment.variants)) {
                        let key2 = j;

                        for (const [k, d] of Object.entries(c.price)) {

                            let key3 = k;

                            d.name = b.name;
                            d.label = c.label;
                            d.id = [key1, key2, key3].join('.');

                            m.set(d.id, d);
                        }

                    }
                }
                return m;
            }

            let map = buildMap(obj, callback, '${name} ${label}', '${id}')
            let i = convertMapResult(map);

            expect(JSON.stringify(i)).to.be.equal('{"0.0.0":"Cassandra XXS","0.0.1":"Cassandra XXS","0.1.0":"Cassandra XS","0.1.1":"Cassandra XS","0.2.0":"Cassandra S","0.2.1":"Cassandra S","0.3.0":"Cassandra L","0.3.1":"Cassandra L","1.0.0":"Yessey! XXS","1.0.1":"Yessey! XXS","1.1.0":"Yessey! XS","1.1.1":"Yessey! XS","1.2.0":"Yessey! S","1.2.1":"Yessey! S","1.3.0":"Yessey! L","1.3.1":"Yessey! L"}');

        })
    })

    describe('build submap with *', function () {
        it('definition should return {"10":"Cassandra 10","20":"Yessey! 20"}', function () {

            let obj = {
                "data": [
                    {
                        "id": 10,
                        "name": "Cassandra"
                    },
                    {
                        "id": 20,
                        "name": "Yessey!",
                    }
                ]
            };

            let map = buildMap(obj, 'data.*', '${name} ${id}', '${id}')
            let i = convertMapResult(map);
            expect(JSON.stringify(i)).to.be.equal('{"10":"Cassandra 10","20":"Yessey! 20"}');

        })
    })


    describe('build submap with **', function () {
        it('definition should return Map', function () {

            let obj = {
                "data": [
                    {
                        "id": 10,
                        "name": "Cassandra",
                        "enrichment": {
                            variants: [
                                {
                                    sku: 1, label: "XXS",
                                    price: [
                                        {vk: '12.12 €', id: 1},
                                        {vk: '12.12 €', id: 2}
                                    ]
                                },
                                {
                                    sku: 2, label: "XS",
                                    price: [
                                        {vk: '22.12 €', id: 3},
                                        {vk: '22.12 €', id: 4}
                                    ]
                                },
                                {
                                    sku: 3, label: "S",
                                    price: [
                                        {vk: '32.12 €', id: 5},
                                        {vk: '32.12 €', id: 6}
                                    ]
                                },
                                {
                                    sku: 4, label: "L",
                                    price: [
                                        {vk: '42.12 €', id: 7},
                                        {vk: '42.12 €', id: 8}
                                    ]
                                }
                            ]

                        }
                    },
                    {
                        "id": 20,
                        "name": "Yessey!",
                        "enrichment": {
                            variants: [
                                {
                                    sku: 1, label: "XXS",
                                    price: [
                                        {vk: '12.12 €', id: 9},
                                        {vk: '12.12 €', id: 10}
                                    ]
                                },
                                {
                                    sku: 2, label: "XS",
                                    price: [
                                        {vk: '22.12 €', id: 11},
                                        {vk: '22.12 €', id: 12}
                                    ]
                                },
                                {
                                    sku: 3, label: "S",
                                    price: [
                                        {vk: '32.12 €', id: 13},
                                        {vk: '32.12 €', id: 14}
                                    ]
                                },
                                {
                                    sku: 4,
                                    label: "L",
                                    price: [
                                        {vk: '42.12 €', id: 15},
                                        {vk: '42.12 €', id: 16},
                                        {vk: '44.12 €', id: 17}
                                    ]
                                }
                            ]

                        }
                    }
                ]
            };

            let map = buildMap(obj, 'data.*.enrichment.variants.*.price.*', '${vk} ${^.label} ${^.^.name}', '${^.^.sku}')
            let i = convertMapResult(map);
            expect(JSON.stringify(i)).to.be.equal('{"data.0.enrichment.variants.0.price.0":"12.12 € XXS Cassandra","data.0.enrichment.variants.0.price.1":"12.12 € XXS Cassandra","data.0.enrichment.variants.1.price.0":"22.12 € XS Cassandra","data.0.enrichment.variants.1.price.1":"22.12 € XS Cassandra","data.0.enrichment.variants.2.price.0":"32.12 € S Cassandra","data.0.enrichment.variants.2.price.1":"32.12 € S Cassandra","data.0.enrichment.variants.3.price.0":"42.12 € L Cassandra","data.0.enrichment.variants.3.price.1":"42.12 € L Cassandra","data.1.enrichment.variants.0.price.0":"12.12 € XXS Yessey!","data.1.enrichment.variants.0.price.1":"12.12 € XXS Yessey!","data.1.enrichment.variants.1.price.0":"22.12 € XS Yessey!","data.1.enrichment.variants.1.price.1":"22.12 € XS Yessey!","data.1.enrichment.variants.2.price.0":"32.12 € S Yessey!","data.1.enrichment.variants.2.price.1":"32.12 € S Yessey!","data.1.enrichment.variants.3.price.0":"42.12 € L Yessey!","data.1.enrichment.variants.3.price.1":"42.12 € L Yessey!","data.1.enrichment.variants.3.price.2":"44.12 € L Yessey!"}');

        })
    })

    describe('examplecode', function () {

        it('should execute example code', function () {

            let obj = {
                "data": [
                    {
                        "id": 10,
                        "name": "Cassandra",
                        "address": {
                            "street": "493-4105 Vulputate Street",
                            "city": "Saumur",
                            "zip": "52628"
                        }
                    },
                    {
                        "id": 20,
                        "name": "Holly",
                        "address": {
                            "street": "1762 Eget Rd.",
                            "city": "Schwalbach",
                            "zip": "952340"
                        }
                    },
                    {
                        "id": 30,
                        "name": "Guy",
                        "address": {
                            "street": "957-388 Sollicitudin Avenue",
                            "city": "Panchià",
                            "zip": "420729"
                        }
                    }
                ]
            };

            let map;
            map = buildMap(obj, 'data.*', '${name} (${address.zip} ${address.city})', 'id')
            expect(map).to.be.instanceOf(Map);

            map = buildMap(obj, 'data.*', '${name} (${address.zip} ${address.city})')
            expect(map).to.be.instanceOf(Map);

            map = buildMap(obj, 'data.*', '${name} (${address.zip} ${address.city})', 'id', function (value, key) {
                return (value['id'] >= 20) ? true : false
            })
            expect(map).to.be.instanceOf(Map);
        });

    })

    describe('buildmap()', function () {

        let obj1 = {
            dataset: {
                "10082": {
                    name: "Test 1",
                    address: "Here 1"
                },
                "10084": {
                    name: "Test 2",
                    address: "Here 2"
                }
            }
        };

        it('should return Map Instance.', function () {
            expect(buildMap({}, '')).to.be.instanceOf(Map);
        });


        [
            [obj1, 'dataset.*', 'address', '{"dataset.10082":"Here 1","dataset.10084":"Here 2"}'],
            [obj1, 'x', undefined, '{}'],
            [obj1, 'dataset.*', 'name', '{"dataset.10082":"Test 1","dataset.10084":"Test 2"}'],
        ].forEach(function (data) {

            let a = data.shift()
            let b = data.shift()
            let c = data.shift()
            let d = data.shift()

            it('buildMap(' + JSON.stringify(a) + ',' + JSON.stringify(b) + ',' + JSON.stringify(c) + ') should return ' + JSON.stringify(d) + ' ', function () {
                let t = buildMap(a, b, c);
                let m = JSON.stringify(convertMapResult(t));
                expect(m).to.be.equal(d);
            });
        });

    });
});
