"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.HotWebSocketServerClient = void 0;
const uuid_1 = require("uuid");
const HotWebSocketServer_1 = require("./HotWebSocketServer");
/**
 * The server-side websocket connection to the client.
 */
class HotWebSocketServerClient {
    constructor(webSocketServer, socket) {
        this.webSocketServer = webSocketServer;
        this.socket = socket;
        this.persistentData = {};
        this.authorizedValue = null;
    }
    /**
     * This client's id.
     */
    getId() {
        return (this.socket.id);
    }
    /**
     * Get the client's ip.
     */
    getIP() {
        const incomingIP = HotWebSocketServer_1.HotWebSocketServer.getIPFromSocket(this.socket);
        return (incomingIP);
    }
    /**
     * Tag a client. This is useful when trying to send messages to groups of clients.
     */
    tag(tag) {
        this.webSocketServer.tagClient(this, tag);
    }
    /**
     * Listen for a client event.
     */
    on(event, callback, uuid = null) {
        this.socket.on(event, function (uuid2, data) {
            if (data.uuid != null) {
                if (uuid2 != null) {
                    if (data.uuid === uuid2)
                        callback(data.data, data.uuid);
                }
                else
                    callback(data.data, data.uuid);
            }
            else
                callback(data, uuid2);
        }.bind(this, uuid));
    }
    /**
     * Listen for a client event without any intervention.
     */
    onRaw(event, callback) {
        this.socket.on(event, callback);
    }
    /**
     * Stop listening for a client event.
     */
    off(event) {
        this.socket.off(event, null);
    }
    /**
     * Listen for a client event once.
     */
    once(event, callback, uuid = null) {
        this.socket.once(event, function (uuid2, data) {
            if (data.uuid != null) {
                if (uuid2 != null) {
                    if (data.uuid === uuid2)
                        callback(data.data, data.uuid);
                }
                else
                    callback(data.data, data.uuid);
            }
            else
                callback(data, uuid2);
        }.bind(this, uuid));
    }
    /**
     * Listen for a client event once without any intervention.
     */
    onceRaw(event, callback) {
        this.socket.once(event, callback);
    }
    /**
     * Send an event to the client. You can optionally receive a response from the client.
     */
    send(event, data, uuid = null) {
        if (this.socket == null)
            throw new Error(`Client socket is null. Unable to send event ${event}`);
        if (this.socket.connected === false)
            throw new Error(`Client socket is not connected. Unable to send event ${event}`);
        if (uuid == null)
            uuid = (0, uuid_1.v4)();
        this.socket.emit(event, { uuid: uuid, data: data });
        return (uuid);
    }
    /**
     * Send an event to the client, and wait for a response. Every time
     * data is received from this event, the callback will be called.
     */
    sendOn(event_1, data_1, callback_1) {
        return __awaiter(this, arguments, void 0, function* (event, data, callback, uuid = null) {
            let result = yield new Promise((resolve, reject) => {
                if (uuid == null)
                    uuid = (0, uuid_1.v4)();
                this.on(event, function (uuid2, data) {
                    callback(data, uuid2);
                    resolve(data);
                }.bind(this, uuid), uuid);
                this.send(event, data, uuid);
            });
            return (result);
        });
    }
    /**
     * Send an event to the client, and wait for a response once.
     */
    sendOnce(event_1, data_1) {
        return __awaiter(this, arguments, void 0, function* (event, data, uuid = null) {
            let result = yield new Promise((resolve, reject) => {
                if (uuid == null)
                    uuid = (0, uuid_1.v4)();
                this.once(event, function (uuid2, data) {
                    resolve(data);
                }.bind(this, uuid), uuid);
                this.send(event, data, uuid);
            });
            return (result);
        });
    }
    /**
     * Disconnect the client.
     */
    disconnect(removeFromServer = true) {
        if (removeFromServer === true)
            this.webSocketServer.disconnect(this.getId(), false);
        if (this.socket.connected === true) {
            this.socket.disconnect(true);
            this.webSocketServer.logger.verbose(() => `Websocket Disconnected ${this.getId()}`);
        }
    }
}
exports.HotWebSocketServerClient = HotWebSocketServerClient;
//# sourceMappingURL=HotWebSocketServerClient.js.map