import {expect} from "chai"
import {WebConnect} from "../../../../../source/data/datasource/server/webconnect.mjs";
import {initWebSocket} from "../../../../util/websocket.mjs";

describe('Websocket', function () {

    let ds = undefined
    const testUrl = "ws://mock.local"

    before(function (done) {
        initWebSocket().then(() => {
            done()
        }).catch((e) => {
            done(e)
        })
    });

    afterEach(function (done) {
        if (ds) {
            ds.close()
        }

        // workaround: without this, the node test will not exit 
        for (const sym of Object.getOwnPropertySymbols(ds)) {
            if (sym.toString() === 'Symbol(connection)') {
                const connection = ds[sym]
                for (const sym2 of Object.getOwnPropertySymbols(connection)) {
                    if (sym2.toString() === 'Symbol(connection)') {
                        const socket = connection[sym2]?.socket;
                        if (socket) {
                            if (typeof socket?.terminate === 'function') {
                                socket?.['terminate']()
                            }
                        }
                    }
                }
            }
        }

        done()
    });

    it('should get clone', function () {

        ds = new WebConnect(testUrl)
        const clone = ds.getClone()
        expect(clone).to.be.an.instanceof(WebConnect)

    })

    it('should transform data', function (done) {

        let writeCallbackCalled = false
        let readCallbackCalled = false

        ds = new WebConnect({
            url: testUrl,
            write: {
                mapping: {
                    transformer: "call:onWrite",
                    callbacks: {
                        onWrite: (data) => {
                            writeCallbackCalled = true
                            return data
                        }
                    }
                },
                sheathing: {
                    object: {
                        demo: 1,
                        data: {
                            xyz: undefined
                        }
                    },
                    path: "data.xyz",
                },
            },
            read: {
                mapping: {
                    transformer: "call:onRead",
                    callbacks: {
                        onRead: (data) => {
                            readCallbackCalled = true
                            return data
                        }
                    }
                },
                path: 'data.xyz',
            }
        })

        ds.connect().then(() => {
            ds.set({
                envelop: {
                    message: "Hello World"
                }
            })

            ds.write().then(() => {

                ds.set({})
                expect(ds.get()).to.be.deep.equal({});

                setTimeout(() => {


                    ds.read().then(() => {
                        expect(ds.get()).to.be.deep.equal({envelop:{message: "Hello World"}});
                        expect(writeCallbackCalled).to.be.true
                        expect(readCallbackCalled).to.be.true
                        done()
                    }).catch((e) => {
                        done(e)
                    })
                }, 200)

            }).catch((err) => {
                done(new Error(err));
            })


        }).catch((e) => {
            done(e)
        })


    })

    it('should connect', function (done) {
        ds = new WebConnect({
            url: testUrl,
            reconnect: {
                enabled: false
            }
        });
        ds.connect().then(() => {
            done()
        }).catch((e) => {
            done(e)
        })


    })

    it('should send a message', function (done) {
        
        this.timeout(10000)
        
        ds = new WebConnect({
            url: testUrl,
            reconnect: {
                enabled: false
            }
        });
        
        ds.connect().then(() => {
            ds.set({
                envelop: {
                    message: "Hello World"
                }
            })

            ds.write().then(() => {

                ds.set({})
                expect(ds.get()).to.be.deep.equal({});

                setTimeout(() => {

                    ds.read().then(() => {
                    expect(ds.get()).to.be.deep.equal({envelop:{message: "Hello World"}});
                    done()
                }).catch((e) => {
                    done(e)
                })
                },500)
                

            }).catch((err) => {
                done(new Error(err));
            })


        }).catch((e) => {
            done(e)
        })


    });

});
