"use strict";
var __extends = (this && this.__extends) || (function () {
    var extendStatics = Object.setPrototypeOf ||
        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
var socketIo = require("socket.io");
var socketLib_1 = require("./socketLib");
exports.resolve = Promise.resolve.bind(Promise);
/** This is your main boot function for the server */
function run(config) {
    var server = new Server(config.app, config.serverImplementation, function (serverInstance) {
        return serverInstance.sendAllToSocket(config.clientContract);
    });
    // Provide the server push messages
    var cast = server.setupAllCast(config.cast);
    return { server: server, cast: cast };
}
exports.run = run;
var Server = /** @class */ (function () {
    function Server(app, serverImplementation, clientCreator) {
        this.app = app;
        this.io = socketIo(app
        // polling is more available on hosts (e.g. azure) but it causes more socket hangups in socketIO
        /* ,{transports:['polling']} */
        );
        this.io.on('connection', function (socket) {
            var serverInstance = new ServerInstance(socket, serverImplementation);
            serverInstance.client = clientCreator(serverInstance);
        });
    }
    /**
     * Mutates the original in place plus returns the mutated version
     * Each member of `instance` must be a typed event
     */
    Server.prototype.setupAllCast = function (instance) {
        var _this = this;
        var toRet = instance;
        Object.keys(toRet).forEach(function (name) {
            // Override the actual emit function with one that sends it on to the server
            var evt = new socketLib_1.TypedEvent();
            toRet[name] = evt;
            evt.on(function (data) {
                var castMessage = {
                    message: name,
                    data: data
                };
                // console.log('EMIT TO ALL : ', name)
                _this.io.sockets.emit(socketLib_1.anycastMessageName, castMessage);
            });
        });
        return toRet;
    };
    return Server;
}());
exports.Server = Server;
var ServerInstance = /** @class */ (function (_super) {
    __extends(ServerInstance, _super);
    function ServerInstance(socket, responderModule) {
        var _this = _super.call(this) || this;
        _this.socket = socket;
        _this.getSocket = function () { return _this.socket; };
        _this.registerAllFunctionsExportedFromAsResponders(responderModule);
        _super.prototype.startListening.call(_this);
        return _this;
    }
    return ServerInstance;
}(socketLib_1.RequesterResponder));
exports.ServerInstance = ServerInstance;
