import {defineStore} from 'pinia';
import {store} from '@/store';
import * as SockJS from 'sockjs-client/dist/sockjs.min';
import {RxStomp, RxStompState} from '@stomp/rx-stomp';
import {getToken} from '@/utils/auth';
import {map} from 'rxjs';


interface WebSocketState {
    status: 'open' | 'connecting' | 'closing' | 'closed',
    rxStomp: RxStomp;
}

export const useWebSocketStore = defineStore({
    id: 'app-websocket',
    state: (): WebSocketState => ({
        status: 'closed',
        rxStomp: new RxStomp(),
    }),
    getters: {
        isConnected(state) {
            return state.status === 'open';
        }
    },
    actions: {
        init() {
            this.rxStomp.configure({
                debug: (msg: string): void => {
                    console.log(new Date(), msg);
                },
            });
            this.rxStomp.connectionState$.subscribe(state => {
                switch (state) {
                    case RxStompState.CONNECTING:
                        this.status = 'connecting';
                        return;
                    case RxStompState.OPEN:
                        this.status = 'open';
                        return;
                    case RxStompState.CLOSING:
                        this.status = 'closing';
                        return;
                    case RxStompState.CLOSED:
                        this.status = 'closed';
                        return;
                }
            });
            this.updateCredentials();
            this.rxStomp.activate();
        },
        updateCredentials() {
            this.rxStomp.configure({
                webSocketFactory: () => {
                    return new SockJS(this.buildUrl());
                },
            });
        },
        buildUrl(): string {
            // building absolute path so that websocket doesn't fail when deploying with a context path
            const loc = window.location;
            const baseHref = document.querySelector('base')?.getAttribute('href');
            const url = '//' + loc.host + (baseHref ?? '/') + 'websocket/tracker';
            const authToken = getToken();
            if (authToken) {
                return `${url}?access_token=${authToken}`;
            }
            return url;
        },
        subscribe(url, observer) {
            this.rxStomp
                .watch(url)
                .pipe(map(imessage => JSON.parse(imessage.body)))
                .subscribe(observer);
        },
        publish(url, message) {
            this.rxStomp.publish({destination: url, body: JSON.stringify(message)});
        }
    }
});

export function useWebSocketStoreWithOut() {
    return useWebSocketStore(store);
}
