import { Common, VMath } from "v-eris";
export var SocketState;
(function (SocketState) {
    SocketState[SocketState["Failed"] = 0] = "Failed";
    SocketState[SocketState["Closed"] = 1] = "Closed";
    SocketState[SocketState["Connecting"] = 2] = "Connecting";
    SocketState[SocketState["Awaiting"] = 3] = "Awaiting";
    SocketState[SocketState["Ready"] = 4] = "Ready";
})(SocketState || (SocketState = {}));
;
var Socket = /** @class */ (function () {
    function Socket() {
        this.state = SocketState.Closed;
        this.pingInterval = null;
        this.initParams = {
            url: location.host,
            proto: window.location.protocol == "https:" ? "wss" : "ws",
            secure: window.location.protocol == "https:",
        };
        this.pingIntervalValue = 8000;
        this.pingIntervalDelay = 4000;
        this.connection = null;
        this.pinged = false;
        this.listeners = {
            connect: function () { },
            disconnect: function () { },
            message: function () { },
            create: function () { },
            destroy: function () { },
        };
    }
    ;
    Socket.prototype.stopPinging = function () {
        clearInterval(this.pingInterval);
        this.pingInterval = null;
    };
    ;
    Socket.prototype.startPinging = function (interval) {
        var _this = this;
        clearInterval(this.pingInterval);
        this.pingIntervalValue = interval;
        this.pingInterval = setInterval(function () {
            if (!_this.connection) {
                clearInterval(_this.pingInterval);
                return;
            }
            ;
            if (_this.pinged) {
                _this.pinged = false;
                return;
            }
            ;
            console.log("Timeouted: " + _this.initParams.url);
            _this.tryReconnect();
        }, this.pingIntervalValue);
    };
    ;
    Socket.prototype.connect = function (url, secure) {
        var _this = this;
        this.initParams.url = url === undefined ? this.initParams.url : url;
        this.initParams.secure = secure === undefined ? this.initParams.secure : secure;
        this.initParams.proto = this.initParams.secure ? "wss" : "ws";
        this.disconnect();
        this.state = SocketState.Connecting;
        this.connection = new WebSocket(this.initParams.proto + "://" + this.initParams.url);
        this.startPinging(16000);
        this.pinged = false;
        this.connection.onopen = function () {
            _this.state = SocketState.Awaiting;
        };
        this.connection.onclose = function () {
            _this.state = SocketState.Closed;
            //this.disconnect();
        };
        this.connection.onerror = function () {
            _this.state = SocketState.Failed;
            _this.tryReconnect();
        };
        this.connection.onmessage = function (event) {
            var connectionIndex = event.data.indexOf("connect:");
            if (connectionIndex == 0) {
                _this.state = SocketState.Ready;
                var p = VMath.clamp(Common.uint(event.data.substr(8)) + _this.pingIntervalDelay, 1000, 30000);
                _this.startPinging(p);
                console.log("Connected: " + _this.initParams.proto + "://" + _this.initParams.url);
                _this.listeners.connect();
                return;
            }
            ;
            if (event.data == "ping") {
                _this.pinged = true;
                _this.send("pong");
                return;
            }
            ;
            var data = null;
            try {
                data = JSON.parse(event.data);
            }
            catch (e) {
                data = { type: "broken", value: data };
            }
            ;
            _this.listeners.message(data);
        };
    };
    ;
    Socket.prototype.tryReconnect = function () {
        console.log("Reconnecting: " + this.initParams.proto + "://" + this.initParams.url);
        this.connect();
    };
    ;
    Socket.prototype.reconnect = function () {
        this.disconnect();
        this.connect();
    };
    ;
    Socket.prototype.disconnect = function () {
        if (!this.connection)
            return;
        this.stopPinging();
        this.state = SocketState.Closed;
        console.log("Disconnected: " + this.initParams.proto + "://" + this.initParams.url);
        try {
            this.connection.close();
        }
        catch (e) { }
        ;
    };
    ;
    Socket.prototype.destroy = function () {
        this.disconnect();
    };
    ;
    Socket.prototype.on = function (name, fn) {
        if (!this.listeners[name])
            return;
        this.listeners[name] = fn;
    };
    ;
    Socket.prototype.send = function (message) {
        if (!this.connection || this.state != SocketState.Ready)
            return;
        try {
            message = typeof message == "string" ? message : JSON.stringify(message);
        }
        catch (e) {
            message = "{}";
        }
        ;
        this.connection.send(message);
    };
    ;
    return Socket;
}());
export { Socket };
;
//# sourceMappingURL=socket.js.map