"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PayoutFunctionV0 = exports.PayoutFunction = void 0;
const bufio_1 = require("@node-dlc/bufio");
const MessageType_1 = require("../MessageType");
const util_1 = require("../util");
const PayoutCurvePiece_1 = require("./PayoutCurvePiece");
/**
 * PayoutFunction contains the payout curve definition for numeric outcome contracts.
 * Updated to match rust-dlc format exactly.
 */
class PayoutFunction {
    /**
     * Creates a PayoutFunction from JSON data
     * @param json JSON object representing a payout function
     */
    // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any
    static fromJSON(json) {
        const instance = new PayoutFunction();
        // Parse payout function pieces
        const pieces = json.payoutFunctionPieces || json.payout_function_pieces || [];
        instance.payoutFunctionPieces = pieces.map(
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        (pieceJson, index) => {
            const piece = {
                endPoint: {
                    eventOutcome: (0, util_1.toBigInt)(pieceJson.endPoint?.eventOutcome),
                    outcomePayout: (0, util_1.toBigInt)(pieceJson.endPoint?.outcomePayout),
                    extraPrecision: pieceJson.endPoint?.extraPrecision || 0,
                },
                payoutCurvePiece: PayoutCurvePiece_1.PayoutCurvePiece.fromJSON(pieceJson.payoutCurvePiece || pieceJson.payout_curve_piece),
            };
            // For HyperbolaPayoutCurvePiece, set the left and right end points
            if (piece.payoutCurvePiece instanceof PayoutCurvePiece_1.HyperbolaPayoutCurvePiece) {
                const hyperbola = piece.payoutCurvePiece;
                // Left end point is this piece's endPoint
                hyperbola.leftEndPoint = piece.endPoint;
                // Right end point is the next piece's endPoint, or lastEndpoint if this is the last piece
                if (index < pieces.length - 1) {
                    const nextPiece = pieces[index + 1];
                    hyperbola.rightEndPoint = {
                        eventOutcome: (0, util_1.toBigInt)(nextPiece.endPoint?.eventOutcome),
                        outcomePayout: (0, util_1.toBigInt)(nextPiece.endPoint?.outcomePayout),
                        extraPrecision: nextPiece.endPoint?.extraPrecision || 0,
                    };
                }
                else {
                    // Use lastEndpoint for the final piece
                    const lastEndpoint = json.lastEndpoint || json.last_endpoint || {};
                    hyperbola.rightEndPoint = {
                        eventOutcome: (0, util_1.toBigInt)(lastEndpoint.eventOutcome),
                        outcomePayout: (0, util_1.toBigInt)(lastEndpoint.outcomePayout),
                        extraPrecision: lastEndpoint.extraPrecision || 0,
                    };
                }
            }
            return piece;
        });
        // Parse last endpoint
        const lastEndpoint = json.lastEndpoint || json.last_endpoint;
        if (lastEndpoint) {
            instance.lastEndpoint = {
                eventOutcome: (0, util_1.toBigInt)(lastEndpoint.eventOutcome),
                outcomePayout: (0, util_1.toBigInt)(lastEndpoint.outcomePayout),
                extraPrecision: lastEndpoint.extraPrecision || 0,
            };
        }
        else {
            // Default last endpoint if not provided
            instance.lastEndpoint = {
                eventOutcome: BigInt(0),
                outcomePayout: BigInt(0),
                extraPrecision: 0,
            };
        }
        return instance;
    }
    /**
     * Deserializes a payout_function message
     * @param buf
     */
    static deserialize(buf) {
        const instance = new PayoutFunction();
        const reader = new bufio_1.BufferReader(buf);
        // Read payout function pieces (as vec)
        const numPieces = Number(reader.readBigSize());
        for (let i = 0; i < numPieces; i++) {
            // Read end_point first
            const eventOutcome = reader.readUInt64BE();
            const outcomePayout = reader.readUInt64BE();
            const extraPrecision = reader.readUInt16BE();
            // Read payout curve piece
            const payoutCurvePieceStartPos = reader.position;
            const payoutCurvePiece = PayoutCurvePiece_1.PayoutCurvePiece.deserialize(reader.buffer.subarray(reader.position));
            // Skip past the payout curve piece bytes
            const payoutCurvePieceSize = payoutCurvePiece.serialize().length;
            reader.position = payoutCurvePieceStartPos + payoutCurvePieceSize;
            instance.payoutFunctionPieces.push({
                endPoint: {
                    eventOutcome,
                    outcomePayout,
                    extraPrecision,
                },
                payoutCurvePiece,
            });
        }
        // Read last_endpoint
        instance.lastEndpoint = {
            eventOutcome: reader.readUInt64BE(),
            outcomePayout: reader.readUInt64BE(),
            extraPrecision: reader.readUInt16BE(),
        };
        return instance;
    }
    /**
     * Constructor that ensures proper initialization
     */
    constructor() {
        /**
         * The type for payout_function message. payout_function = 42790
         */
        this.type = PayoutFunction.type;
        this.payoutFunctionPieces = [];
        // Explicitly initialize arrays to handle file-linking issues
        this.payoutFunctionPieces = [];
    }
    /**
     * Converts payout_function to JSON
     */
    toJSON() {
        return {
            payoutFunctionPieces: this.payoutFunctionPieces.map((piece) => ({
                endPoint: {
                    eventOutcome: (0, util_1.bigIntToNumber)(piece.endPoint.eventOutcome),
                    outcomePayout: (0, util_1.bigIntToNumber)(piece.endPoint.outcomePayout),
                    extraPrecision: piece.endPoint.extraPrecision,
                },
                payoutCurvePiece: piece.payoutCurvePiece.toJSON(),
            })),
            lastEndpoint: {
                eventOutcome: (0, util_1.bigIntToNumber)(this.lastEndpoint.eventOutcome),
                outcomePayout: (0, util_1.bigIntToNumber)(this.lastEndpoint.outcomePayout),
                extraPrecision: this.lastEndpoint.extraPrecision,
            },
        };
    }
    /**
     * Serializes the payout_function message into a Buffer
     */
    serialize() {
        const writer = new bufio_1.BufferWriter();
        // Write payout_function_pieces as vec (length + elements)
        writer.writeBigSize(this.payoutFunctionPieces.length);
        for (const piece of this.payoutFunctionPieces) {
            // Write end_point first (matches rust order)
            writer.writeUInt64BE(piece.endPoint.eventOutcome);
            writer.writeUInt64BE(piece.endPoint.outcomePayout);
            writer.writeUInt16BE(piece.endPoint.extraPrecision);
            // Write payout_curve_piece second
            writer.writeBytes(piece.payoutCurvePiece.serialize());
        }
        // Write last_endpoint
        writer.writeUInt64BE(this.lastEndpoint.eventOutcome);
        writer.writeUInt64BE(this.lastEndpoint.outcomePayout);
        writer.writeUInt16BE(this.lastEndpoint.extraPrecision);
        return writer.toBuffer();
    }
}
exports.PayoutFunction = PayoutFunction;
PayoutFunction.type = MessageType_1.MessageType.PayoutFunction;
// Legacy support
exports.PayoutFunctionV0 = PayoutFunction;
//# sourceMappingURL=PayoutFunction.js.map