import * as __WEBPACK_EXTERNAL_MODULE__tachybase_schema__ from "@tachybase/schema";
import * as __WEBPACK_EXTERNAL_MODULE__tachybase_sdk__ from "@tachybase/sdk";
function _define_property(obj, key, value) {
    if (key in obj) Object.defineProperty(obj, key, {
        value: value,
        enumerable: true,
        configurable: true,
        writable: true
    });
    else obj[key] = value;
    return obj;
}
class WebSocketClient {
    getURL() {
        var _options_apiClient;
        if (!this.app) return;
        const options = this.app.getOptions();
        const apiBaseURL = null == options ? void 0 : null === (_options_apiClient = options.apiClient) || void 0 === _options_apiClient ? void 0 : _options_apiClient['baseURL'];
        if (!apiBaseURL) return;
        const subApp = (0, __WEBPACK_EXTERNAL_MODULE__tachybase_sdk__.getSubAppName)(this.app.getPublicPath());
        const queryString = subApp ? "?__appName=".concat(subApp) : "?__hostname=".concat(window.location.hostname);
        const wsPath = this.options.basename || '/ws';
        if (this.options.url) {
            const url = new URL(this.options.url);
            if ('localhost' === url.hostname) {
                const protocol = 'https:' === location.protocol ? 'wss' : 'ws';
                return "".concat(protocol, "://").concat(location.hostname, ":").concat(url.port).concat(wsPath).concat(queryString);
            }
            return "".concat(this.options.url).concat(queryString);
        }
        try {
            const url = new URL(apiBaseURL);
            return "".concat('https:' === url.protocol ? 'wss' : 'ws', "://").concat(url.host).concat(wsPath).concat(queryString);
        } catch (error) {
            return "".concat('https:' === location.protocol ? 'wss' : 'ws', "://").concat(location.host).concat(wsPath).concat(queryString);
        }
    }
    get reconnectAttempts() {
        var _this_options;
        return (null === (_this_options = this.options) || void 0 === _this_options ? void 0 : _this_options.reconnectAttempts) || 30;
    }
    get reconnectInterval() {
        var _this_options;
        return (null === (_this_options = this.options) || void 0 === _this_options ? void 0 : _this_options.reconnectInterval) || 1000;
    }
    get pingInterval() {
        var _this_options;
        return (null === (_this_options = this.options) || void 0 === _this_options ? void 0 : _this_options.pingInterval) || 30000;
    }
    get readyState() {
        if (!this._ws) return -1;
        return this._ws.readyState;
    }
    connect() {
        if (!this.enabled) return;
        if (0 === this._reconnectTimes) console.log('[tachybase-ws]: connecting...');
        if (this._reconnectTimes >= this.reconnectAttempts) return;
        if (this.readyState === WebSocket.OPEN) return;
        this._reconnectTimes++;
        const ws = new WebSocket(this.getURL(), this.options.protocols);
        let pingIntervalTimer;
        ws.onopen = ()=>{
            console.log('[tachybase-ws]: connected.');
            this.serverDown = false;
            if (this._ws) this.removeAllListeners();
            this._reconnectTimes = 0;
            this._ws = ws;
            for (const { type, listener, options } of this.events)this._ws.addEventListener(type, listener, options);
            pingIntervalTimer = setInterval(()=>this.send('ping'), this.pingInterval);
            this.connected = true;
        };
        ws.onerror = async ()=>{
            console.log('onerror', this.readyState, this._reconnectTimes);
        };
        ws.onclose = async (event)=>{
            setTimeout(()=>this.connect(), this.reconnectInterval);
            console.log('onclose', this.readyState, this._reconnectTimes, this.serverDown);
            this.connected = false;
            clearInterval(pingIntervalTimer);
            if (this._reconnectTimes >= Math.min(this.reconnectAttempts, 5)) {
                this.serverDown = true;
                this.emit('serverDown', event);
            }
        };
    }
    reconnect() {
        this._reconnectTimes = 0;
        this.connect();
    }
    close() {
        if (!this._ws) return;
        this._reconnectTimes = this.reconnectAttempts;
        return this._ws.close();
    }
    send(data) {
        if (!this._ws) return;
        return this._ws.send(data);
    }
    on(type, listener, options) {
        this.events.push({
            type,
            listener,
            options
        });
        if (!this._ws) return;
        this._ws.addEventListener(type, listener, options);
    }
    emit(type, args) {
        for (const event of this.events)if (event.type === type) event.listener(args);
    }
    off(type, listener, options) {
        let index = 0;
        for (const event of this.events){
            if (event.type === type && event.listener === listener) {
                this.events.splice(index, 1);
                break;
            }
            index++;
        }
        if (!this._ws) return;
        this._ws.removeEventListener(type, listener, options);
    }
    removeAllListeners() {
        if (!this._ws) return;
        for (const { type, listener, options } of this.events)this._ws.removeEventListener(type, listener, options);
    }
    constructor(options, app){
        _define_property(this, "app", void 0);
        _define_property(this, "_ws", void 0);
        _define_property(this, "_reconnectTimes", void 0);
        _define_property(this, "events", void 0);
        _define_property(this, "options", void 0);
        _define_property(this, "enabled", void 0);
        _define_property(this, "connected", void 0);
        _define_property(this, "serverDown", void 0);
        _define_property(this, "lastMessage", void 0);
        this.app = app;
        this._reconnectTimes = 0;
        this.events = [];
        this.connected = false;
        this.serverDown = false;
        this.lastMessage = {};
        if (!options) {
            this.enabled = false;
            return;
        }
        this.options = true === options ? {} : options;
        this.enabled = true;
        (0, __WEBPACK_EXTERNAL_MODULE__tachybase_schema__.define)(this, {
            serverDown: __WEBPACK_EXTERNAL_MODULE__tachybase_schema__.observable.ref,
            connected: __WEBPACK_EXTERNAL_MODULE__tachybase_schema__.observable.ref,
            lastMessage: __WEBPACK_EXTERNAL_MODULE__tachybase_schema__.observable.ref
        });
    }
}
export { WebSocketClient };
