"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SegmentBook = void 0;
const helpers_1 = require("../utils/helpers");
const gmpPayload_1 = require("../guardian/gmpPayload");
const logger_1 = require("../utils/logger");
class SegmentBook {
    static async getSegmentBetween(segmentBookContract, timestamp) {
        let segmentDescriptorResult = null;
        try {
            const segmentCount = await segmentBookContract.segmentCount();
            for (let segmentIndex = 0; segmentIndex < segmentCount; segmentIndex++) {
                const segmentDescriptor = await segmentBookContract.segmentDescriptors(segmentIndex);
                if (segmentDescriptor.segmentStartTime.lte(timestamp) && segmentDescriptor.segmentEndTime.gte(timestamp)) {
                    segmentDescriptorResult = segmentDescriptor;
                    break;
                }
            }
        }
        catch (error) {
            console.error({ error: error.message }, `🔴 Error while getting segment between`);
        }
        return segmentDescriptorResult;
    }
    static async lookupSegmentForAccount(segmentBookContract, forAccount) {
        try {
            const settledUntil = await segmentBookContract.settledUntilForAccount(forAccount);
            if (settledUntil.gt(0)) {
                const segmentDescriptor = await this.getSegmentBetween(segmentBookContract, settledUntil);
                if (segmentDescriptor !== null) {
                    return segmentDescriptor;
                }
            }
        }
        catch (error) {
            console.error({ error: error.message }, `🔴 Error while looking up segment for account`);
        }
        return null;
    }
    static async lookupSegmentWithBatchForAccount(segmentBookContract, forAccount) {
        try {
            const settledUntil = await segmentBookContract.settledUntilForAccount(forAccount);
            if (settledUntil.gt(0)) {
                const segmentDescriptor = await this.getSegmentBetween(segmentBookContract, settledUntil);
                if (segmentDescriptor !== null) {
                    const segmentIndex = segmentDescriptor[4];
                    const executorHintArray = await segmentBookContract.executorHint(segmentIndex);
                    if (!executorHintArray.includes(forAccount)) {
                        logger_1.logger.warn({ forAccount, executorHintArray }, `🔴 Account not in executor hint array`);
                        return null;
                    }
                    const batchHashesArray = await segmentBookContract.segmentBatchHashes(segmentIndex);
                    if (batchHashesArray.length === 0) {
                        logger_1.logger.warn({ forAccount, batchHashesArray }, `🔴 No batch hashes found for segment`);
                        return null;
                    }
                    // Populate batch hashes to batch payloads
                    const batchPayloads = await Promise.all(batchHashesArray.map(async (batchHash) => await segmentBookContract.batchPayloads(batchHash)));
                    return [segmentDescriptor, batchHashesArray, batchPayloads];
                }
            }
        }
        catch (error) {
            console.error({ error: error.message }, `🔴 Error while looking up segment for account`);
        }
        return null;
    }
    static async listUnAppliedBatches(segmentBookContract, forAccount, encodedNetworkId, limit) {
        try {
            const batchDescriptors = await segmentBookContract.listUnappliedBatches(forAccount, encodedNetworkId, limit);
            const batchHashes = batchDescriptors.map((batchDescriptor) => batchDescriptor[0]);
            const batchPayloads = await Promise.all(batchHashes.map((batchHash) => segmentBookContract.batchPayloads(batchHash)));
            return {
                batchDescriptors,
                batchPayloads,
                batchHashes,
            };
        }
        catch (error) {
            console.error({ error: error.message, encodedNetworkId, limit, forAccount, segmentBookContract: segmentBookContract.address }, `🔴 Error while listing next un-applied batches`);
            return {
                batchDescriptors: [],
                batchPayloads: [],
                batchHashes: [],
            };
        }
    }
    static sortConfirmationsByOrderTimestamp(confirmations) {
        return confirmations.sort((a, b) => {
            return a[1].lt(b[1]) ? -1 : a[1].gt(b[1]) ? 1 : 0;
        });
    }
    static createBatchPayloadsOfConfirmations(index, confirmations, currentCommitteeRoot) {
        const perNetworkGMPPayloadMap = this.createGMPPayloadsOfConfirmations(confirmations);
        for (const [networkId, gmpPayload] of perNetworkGMPPayloadMap) {
            const decodedNetworkId = (0, helpers_1.decodeNetworkId)(networkId);
            const currentCommitteeRootHash = currentCommitteeRoot[decodedNetworkId];
            if (!currentCommitteeRootHash) {
                console.error({ networkId, currentCommitteeRoot, decodedNetworkId }, `🔴 Error while creating batch out of confirmations: missing currentCommitteeRootHash`);
                continue;
            }
            const batch = gmpPayload_1.GmpPayload.createBatchPreamble(false, currentCommitteeRootHash, currentCommitteeRootHash, gmpPayload, index);
            perNetworkGMPPayloadMap.set(networkId, batch);
        }
        return perNetworkGMPPayloadMap;
    }
    static createGMPPayloadsOfConfirmations(confirmations) {
        const perNetworkGMPPayloadMap = new Map();
        try {
            if (confirmations.length > 0) {
                // Create a batch here
                for (const confirmation of confirmations) {
                    const [_height, _orderTimestamp, _bidAmount, _bidAsset, bidWinner, _executor, _executedTxHash, _createdTxHash, orderId, source,] = confirmation;
                    const GMPMessage = `00${orderId.slice(2)}${bidWinner.slice(2)}`;
                    const currentGMPPayload = perNetworkGMPPayloadMap.get(source) || '0x';
                    perNetworkGMPPayloadMap.set(source, currentGMPPayload + GMPMessage);
                }
            }
        }
        catch (error) {
            console.error({ error: error.message, confirmations }, `🔴 Error while creating batch out of confirmations`);
        }
        return perNetworkGMPPayloadMap;
    }
}
exports.SegmentBook = SegmentBook;
//# sourceMappingURL=segmentBook.js.map