"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.HyperbolaPayoutCurvePiece = exports.PolynomialPayoutCurvePiece = exports.PayoutCurvePiece = void 0;
const bufio_1 = require("@node-dlc/bufio");
const MessageType_1 = require("../MessageType");
const F64_1 = require("../serialize/F64");
const util_1 = require("../util");
class PayoutCurvePiece {
    static deserialize(buf) {
        const reader = new bufio_1.BufferReader(buf);
        const typeId = Number(reader.readBigSize());
        switch (typeId) {
            case MessageType_1.PayoutCurvePieceType.Polynomial:
                return PolynomialPayoutCurvePiece.deserialize(buf);
            case MessageType_1.PayoutCurvePieceType.Hyperbola:
                return HyperbolaPayoutCurvePiece.deserialize(buf);
            default:
                throw new Error(`Payout curve piece type must be Polynomial (0) or Hyperbola (1), got ${typeId}`);
        }
    }
    /**
     * Creates a PayoutCurvePiece from JSON data
     * @param json JSON object representing a payout curve piece
     */
    // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any
    static fromJSON(json) {
        if (!json) {
            throw new Error('payoutCurvePiece is required');
        }
        // Handle test vector format with nested types
        if (json.polynomialPayoutCurvePiece) {
            return PolynomialPayoutCurvePiece.fromJSON(json.polynomialPayoutCurvePiece);
        }
        else if (json.hyperbolaPayoutCurvePiece) {
            return HyperbolaPayoutCurvePiece.fromJSON(json.hyperbolaPayoutCurvePiece);
        }
        // Handle direct format
        else if (json.points !== undefined || json.payoutPoints !== undefined) {
            return PolynomialPayoutCurvePiece.fromJSON(json);
        }
        else if (json.usePositivePiece !== undefined) {
            return HyperbolaPayoutCurvePiece.fromJSON(json);
        }
        else {
            throw new Error('payoutCurvePiece must be either polynomial (with points) or hyperbola (with usePositivePiece)');
        }
    }
}
exports.PayoutCurvePiece = PayoutCurvePiece;
/**
 * PolynomialPayoutCurvePiece defines a polynomial curve piece for payout functions.
 * This corresponds to type 0 in the sibling sub-type format.
 */
class PolynomialPayoutCurvePiece extends PayoutCurvePiece {
    constructor() {
        super(...arguments);
        /**
         * The type for polynomial_payout_curve_piece message - Note: this is a sub-component, not a standalone wire message
         */
        this.type = MessageType_1.MessageType.PolynomialPayoutCurvePiece;
        /**
         * The payout curve piece type for new format
         */
        this.payoutCurvePieceType = MessageType_1.PayoutCurvePieceType.Polynomial;
        this.points = [];
    }
    /**
     * Creates a PolynomialPayoutCurvePiece from JSON data
     * @param json JSON object representing a polynomial payout curve piece
     */
    // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any
    static fromJSON(json) {
        const instance = new PolynomialPayoutCurvePiece();
        const points = json.payoutPoints || json.points || [];
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        instance.points = points.map((point) => ({
            eventOutcome: (0, util_1.toBigInt)(point.eventOutcome || point.event_outcome),
            outcomePayout: (0, util_1.toBigInt)(point.outcomePayout || point.outcome_payout),
            extraPrecision: point.extraPrecision || point.extra_precision || 0,
        }));
        return instance;
    }
    /**
     * Deserializes a polynomial_payout_curve_piece message
     * @param buf
     */
    static deserialize(buf) {
        const instance = new PolynomialPayoutCurvePiece();
        const reader = new bufio_1.BufferReader(buf);
        reader.readBigSize(); // read type (0)
        const numPts = Number(reader.readBigSize());
        for (let i = 0; i < numPts; i++) {
            const eventOutcome = reader.readUInt64BE();
            const outcomePayout = reader.readUInt64BE();
            const extraPrecision = reader.readUInt16BE();
            instance.points.push({
                eventOutcome,
                outcomePayout,
                extraPrecision,
            });
        }
        return instance;
    }
    /**
     * Converts polynomial_payout_curve_piece to JSON
     */
    toJSON() {
        return {
            polynomialPayoutCurvePiece: {
                payoutPoints: this.points.map((point) => {
                    return {
                        eventOutcome: (0, util_1.bigIntToNumber)(point.eventOutcome),
                        outcomePayout: (0, util_1.bigIntToNumber)(point.outcomePayout),
                        extraPrecision: Number(point.extraPrecision),
                    };
                }),
            },
        };
    }
    /**
     * Serializes the polynomial_payout_curve_piece message into a Buffer
     */
    serialize() {
        const writer = new bufio_1.BufferWriter();
        writer.writeBigSize(this.payoutCurvePieceType);
        writer.writeBigSize(this.points.length);
        for (const point of this.points) {
            writer.writeUInt64BE(point.eventOutcome);
            writer.writeUInt64BE(point.outcomePayout);
            writer.writeUInt16BE(point.extraPrecision);
        }
        return writer.toBuffer();
    }
}
exports.PolynomialPayoutCurvePiece = PolynomialPayoutCurvePiece;
PolynomialPayoutCurvePiece.payoutCurvePieceType = MessageType_1.PayoutCurvePieceType.Polynomial;
/**
 * HyperbolaPayoutCurvePiece defines a hyperbola curve piece for payout functions.
 * This corresponds to type 1 in the sibling sub-type format.
 * Updated to use F64 for precise f64 parameter handling.
 */
class HyperbolaPayoutCurvePiece extends PayoutCurvePiece {
    /**
     * Helper function to safely parse F64 values from JSON
     * Handles both number and string inputs for maximum precision
     */
    // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any
    static parseF64Value(value) {
        // Check for basic null/undefined
        if (value === null || value === undefined) {
            return null;
        }
        try {
            if (typeof value === 'string') {
                // Parse string directly to preserve precision
                try {
                    return F64_1.F64.fromString(value);
                }
                catch (error) {
                    // If fromString fails, try parsing as number
                    const numValue = parseFloat(value);
                    if (!isNaN(numValue) && isFinite(numValue)) {
                        return F64_1.F64.fromNumber(numValue);
                    }
                }
            }
            else if (typeof value === 'number') {
                // Parse number - handle special cases
                if (!isFinite(value)) {
                    return null; // Reject NaN, Infinity, -Infinity
                }
                return F64_1.F64.fromNumber(value);
            }
            // Try to convert other types to number as fallback
            const numValue = Number(value);
            if (!isNaN(numValue) && isFinite(numValue)) {
                return F64_1.F64.fromNumber(numValue);
            }
            return null;
        }
        catch (error) {
            return null;
        }
    }
    /**
     * Creates a HyperbolaPayoutCurvePiece from JSON data
     * @param json JSON object representing a hyperbola payout curve piece
     */
    // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any
    static fromJSON(json) {
        if (!json || typeof json !== 'object')
            return null;
        // Handle both wrapped format and direct format
        let data = json.hyperbolaPayoutCurvePiece || json.hyperbola_payout_curve_piece;
        // If no wrapper found, assume direct format if it has the expected properties
        if (!data &&
            (json.usePositivePiece !== undefined ||
                json.use_positive_piece !== undefined)) {
            data = json;
        }
        if (!data)
            return null;
        try {
            const usePositivePiece = data.usePositivePiece || data.use_positive_piece || false;
            // Parse each F64 value with null check
            const translateOutcome = this.parseF64Value(data.translateOutcome !== undefined
                ? data.translateOutcome
                : data.translate_outcome);
            const translatePayout = this.parseF64Value(data.translatePayout !== undefined
                ? data.translatePayout
                : data.translate_payout);
            const a = this.parseF64Value(data.a);
            const b = this.parseF64Value(data.b);
            const c = this.parseF64Value(data.c);
            const d = this.parseF64Value(data.d);
            // Check that all required values were parsed successfully
            if (!translateOutcome || !translatePayout || !a || !b || !c || !d) {
                throw new Error('Failed to parse one or more F64 values');
            }
            return new HyperbolaPayoutCurvePiece(usePositivePiece, translateOutcome, translatePayout, a, b, c, d);
        }
        catch (error) {
            return null;
        }
    }
    /**
     * Deserializes a hyperbola_payout_curve_piece message
     * @param buf
     */
    static deserialize(buf) {
        const instance = new HyperbolaPayoutCurvePiece();
        const reader = new bufio_1.BufferReader(buf);
        reader.readBigSize(); // read type (1)
        instance.usePositivePiece = reader.readUInt8() === 1;
        // Read f64 values using F64 for precise handling - read raw 8-byte buffers
        instance.translateOutcome = F64_1.F64.deserialize(reader.readBytes(8));
        instance.translatePayout = F64_1.F64.deserialize(reader.readBytes(8));
        instance.a = F64_1.F64.deserialize(reader.readBytes(8));
        instance.b = F64_1.F64.deserialize(reader.readBytes(8));
        instance.c = F64_1.F64.deserialize(reader.readBytes(8));
        instance.d = F64_1.F64.deserialize(reader.readBytes(8));
        // Note: leftEndPoint and rightEndPoint are not part of the serialization
        // They will be set by PayoutFunction when creating from JSON
        instance.leftEndPoint = {
            eventOutcome: BigInt(0),
            outcomePayout: BigInt(0),
            extraPrecision: 0,
        };
        instance.rightEndPoint = {
            eventOutcome: BigInt(0),
            outcomePayout: BigInt(0),
            extraPrecision: 0,
        };
        return instance;
    }
    constructor(usePositivePiece = false, translateOutcome, translatePayout, a, b, c, d) {
        super();
        /**
         * The type for hyperbola_payout_curve_piece message - Note: this is a sub-component, not a standalone wire message
         */
        this.type = MessageType_1.MessageType.HyperbolaPayoutCurvePiece;
        this.payoutCurvePieceType = HyperbolaPayoutCurvePiece.payoutCurvePieceType;
        this.usePositivePiece = usePositivePiece;
        // Convert string inputs to F64 objects, or use existing F64 objects
        this.translateOutcome = translateOutcome
            ? typeof translateOutcome === 'string'
                ? F64_1.F64.fromString(translateOutcome)
                : translateOutcome
            : F64_1.F64.fromNumber(0);
        this.translatePayout = translatePayout
            ? typeof translatePayout === 'string'
                ? F64_1.F64.fromString(translatePayout)
                : translatePayout
            : F64_1.F64.fromNumber(0);
        this.a = a
            ? typeof a === 'string'
                ? F64_1.F64.fromString(a)
                : a
            : F64_1.F64.fromNumber(0);
        this.b = b
            ? typeof b === 'string'
                ? F64_1.F64.fromString(b)
                : b
            : F64_1.F64.fromNumber(0);
        this.c = c
            ? typeof c === 'string'
                ? F64_1.F64.fromString(c)
                : c
            : F64_1.F64.fromNumber(0);
        this.d = d
            ? typeof d === 'string'
                ? F64_1.F64.fromString(d)
                : d
            : F64_1.F64.fromNumber(0);
    }
    /**
     * Converts hyperbola_payout_curve_piece to JSON
     * Uses F64.toJSONValue() which preserves precision by using strings for very large numbers
     */
    toJSON() {
        return {
            hyperbolaPayoutCurvePiece: {
                usePositivePiece: this.usePositivePiece,
                translateOutcome: this.translateOutcome.toJSONValue(),
                translatePayout: this.translatePayout.toJSONValue(),
                a: this.a.toJSONValue(),
                b: this.b.toJSONValue(),
                c: this.c.toJSONValue(),
                d: this.d.toJSONValue(),
            },
        };
    }
    /**
     * Serializes the hyperbola_payout_curve_piece message into a Buffer
     */
    serialize() {
        const writer = new bufio_1.BufferWriter();
        writer.writeBigSize(this.payoutCurvePieceType);
        writer.writeUInt8(this.usePositivePiece ? 1 : 0);
        // Write f64 values using F64 for precise handling - write raw 8-byte buffers
        writer.writeBytes(this.translateOutcome.serialize());
        writer.writeBytes(this.translatePayout.serialize());
        writer.writeBytes(this.a.serialize());
        writer.writeBytes(this.b.serialize());
        writer.writeBytes(this.c.serialize());
        writer.writeBytes(this.d.serialize());
        return writer.toBuffer();
    }
}
exports.HyperbolaPayoutCurvePiece = HyperbolaPayoutCurvePiece;
HyperbolaPayoutCurvePiece.payoutCurvePieceType = MessageType_1.PayoutCurvePieceType.Hyperbola;
//# sourceMappingURL=PayoutCurvePiece.js.map