"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.confirmAcceptance = exports.getHasConfirmedAcceptance = exports.isAlreadyCheckingAcceptance = exports.reset = exports.getEventEmitter = void 0;
const neverthrow_1 = require("neverthrow");
const events_1 = require("events");
const http = __importStar(require("../../../http"));
const utils_1 = require("../../../utils");
const Context_1 = require("../../Context");
const Utils_1 = require("../../Utils");
let alreadyCheckingAcceptance = false;
/** A flag that is set to true once this node has successfully confirmed it was
 * accepted into the network. */
let hasConfirmedAcceptance = false;
const eventEmitter = new events_1.EventEmitter();
function getEventEmitter() {
    return eventEmitter;
}
exports.getEventEmitter = getEventEmitter;
function reset() {
    hasConfirmedAcceptance = false;
}
exports.reset = reset;
function isAlreadyCheckingAcceptance() {
    return alreadyCheckingAcceptance;
}
exports.isAlreadyCheckingAcceptance = isAlreadyCheckingAcceptance;
function getHasConfirmedAcceptance() {
    return hasConfirmedAcceptance;
}
exports.getHasConfirmedAcceptance = getHasConfirmedAcceptance;
async function confirmAcceptance(offer) {
    let activeNodes;
    alreadyCheckingAcceptance = true;
    try {
        // ensure we even have nodes to check from
        const archiver = (0, Utils_1.getRandomAvailableArchiver)();
        const activeNodesResult = await (0, Utils_1.getActiveNodesFromArchiver)(archiver);
        if (activeNodesResult.isErr()) {
            return (0, neverthrow_1.err)(new Error(`couldn't get active nodes: ${activeNodesResult.error}`));
        }
        activeNodes = activeNodesResult.value.nodeList;
        if (activeNodes.length === 0) {
            // disable this flag since we're returning
            alreadyCheckingAcceptance = false;
            return (0, neverthrow_1.err)(new Error('no active nodes provided'));
        }
        // verify the signature of the offer
        if (!Context_1.crypto.verify(offer, offer.activeNodePublicKey)) {
            // disable this flag since we're returning
            alreadyCheckingAcceptance = false;
            return (0, neverthrow_1.err)(new Error('acceptance offer signature invalid'));
        }
    }
    catch (e) {
        // disable this flag since we're returning
        alreadyCheckingAcceptance = false;
        return (0, neverthrow_1.err)(new Error(`error while checking acceptance: ${e}`));
    }
    // now, we need to query for the cycle record from a node to confirm that we were,
    // in fact, accepted during the cycle
    const randomNode = (0, utils_1.getRandom)(activeNodes, 1)[0];
    let cycle;
    try {
        cycle = await getCycleFromNode(randomNode, offer.cycleMarker);
    }
    catch (e) {
        // disable this flag since we're returning
        alreadyCheckingAcceptance = false;
        return (0, neverthrow_1.err)(new Error(`error getting cycle from node ${randomNode.ip}:${randomNode.port}: ${e}`));
    }
    // check to see that we were included in the cycle
    const ourPublicKey = Context_1.crypto.getPublicKey();
    const included = cycle.joinedConsensors.some((joinedConsensor) => joinedConsensor.publicKey === ourPublicKey);
    // disable this flag since we're done
    alreadyCheckingAcceptance = false;
    // falling back to `hasConfirmedAcceptance` so that it is not wrongly set to
    // `false` in case of a strange race condition
    hasConfirmedAcceptance = hasConfirmedAcceptance || included;
    return (0, neverthrow_1.ok)(included);
}
exports.confirmAcceptance = confirmAcceptance;
async function getCycleFromNode(node, cycleMarker) {
    const url = `http://${node.ip}:${node.port}/cycle-by-marker?marker=${cycleMarker}`;
    const cycle = await http.get(url);
    return cycle;
}
//# sourceMappingURL=acceptance.js.map