import { waitForEvent } from '../../js/async/promise.js';

export const createController = (messenger, { group='test', pub=[], sub=[], clientId='xyz', sessionId='abc' } = {}) => ({

    setup: {
        group,
        pub,
        sub,
        clientId,
        sessionId
    },

    promises: {
        get opened() { return messenger._promises.get('opened'); },
        get closed() { return messenger._promises.get('closed'); },
    },
    get connection() { return messenger._backend; },
    get controller() { return messenger._backend && WebSocket.controllers.get(messenger._backend); },
    channels: {
        get pub() { return messenger._channels.pub; },
        get sub() { return messenger._channels.sub; },
        set pub(channels) { messenger._channels.pub = [...channels]; },
        set sub(channels) { messenger._channels.sub = [...channels]; }
    },
    get queue() { return messenger._queue; },
    get subscribers() { return messenger._subscribers; },
    async waitForConnection() {
        while (!this.connection) {
            await waitForEvent(WebSocket, 'create');
        }
        return this.connection;
    },
    async waitForNewConnection() {
        let evt;
        do {
            evt = await waitForEvent(WebSocket, 'create');
        } while (evt.instance !== this.connection);
        return this.connection;
    },
    async openConnection() {
        await this.waitForConnection();
        this.controller.open();
    },
    async sendHello() {
        sub = ['user.'+clientId, 'ses.'+sessionId, ...sub];
        await this.sendJSON({
            type: 'ctl',
            name: 'hello',
            payload: { group, pub, sub }
        });
    },
    async closeConnection(code) {
        await this.waitForConnection();
        this.controller.close(code);
    },
    async sendJSON(payload, channelSpec='[0]') {
        await this.waitForConnection();
        // Simulate message id
        const timestamp = Math.floor(Date.now() / 1000);
        const msg = [
            `id: ${timestamp}:${channelSpec}`,
            'content-type: text/json',
            '',
            JSON.stringify(payload)
        ].join("\n");
        // Pass the message
        this.controller.message(msg);
    },
    setState(state) {
        messenger._state = state;
    },
    changeState(state) {
        messenger.state = state;
    }
});

export default createController;