"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ContractDescriptorV1 = exports.ContractDescriptorV0 = exports.NumericalDescriptor = exports.EnumeratedDescriptor = exports.ContractDescriptor = void 0;
const bufio_1 = require("@node-dlc/bufio");
const MessageType_1 = require("../MessageType");
const PayoutFunction_1 = require("./PayoutFunction");
const RoundingIntervals_1 = require("./RoundingIntervals");
class ContractDescriptor {
    static deserialize(buf) {
        const reader = new bufio_1.BufferReader(buf);
        const typeId = Number(reader.readBigSize());
        switch (typeId) {
            case MessageType_1.ContractDescriptorType.Enumerated:
                return EnumeratedDescriptor.deserialize(buf);
            case MessageType_1.ContractDescriptorType.NumericOutcome:
                return NumericalDescriptor.deserialize(buf);
            default:
                throw new Error(`Contract descriptor type must be Enumerated (0) or NumericOutcome (1), got ${typeId}`);
        }
    }
    /**
     * Creates a ContractDescriptor from JSON data (e.g., from test vectors)
     * @param json JSON object representing a contract descriptor
     */
    // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any
    static fromJSON(json) {
        if (!json) {
            throw new Error('contractDescriptor is required');
        }
        // Handle enumerated contract descriptor
        if (json.enumeratedContractDescriptor ||
            json.enumerated_contract_descriptor) {
            return EnumeratedDescriptor.fromJSON(json.enumeratedContractDescriptor ||
                json.enumerated_contract_descriptor);
        }
        // Handle numeric outcome contract descriptor
        else if (json.numericOutcomeContractDescriptor ||
            json.numeric_outcome_contract_descriptor) {
            return NumericalDescriptor.fromJSON(json.numericOutcomeContractDescriptor ||
                json.numeric_outcome_contract_descriptor);
        }
        else {
            throw new Error('contractDescriptor must have either enumeratedContractDescriptor or numericOutcomeContractDescriptor');
        }
    }
}
exports.ContractDescriptor = ContractDescriptor;
/**
 * EnumeratedContractDescriptor contains information about a contract's outcomes
 * and their corresponding payouts (for enumerated outcomes).
 * This corresponds to the previous ContractDescriptorV0.
 */
class EnumeratedDescriptor extends ContractDescriptor {
    constructor() {
        super(...arguments);
        /**
         * The type for enumerated_contract_descriptor message - using MessageType for IDlcMessage compatibility
         */
        this.type = MessageType_1.MessageType.ContractDescriptorV0; // For IDlcMessage compatibility
        /**
         * The contract descriptor type for new format
         */
        this.contractDescriptorType = MessageType_1.ContractDescriptorType.Enumerated;
        this.outcomes = [];
    }
    /**
     * Creates an EnumeratedContractDescriptor from JSON data
     * @param json JSON object representing an enumerated contract descriptor
     */
    // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any
    static fromJSON(json) {
        const instance = new EnumeratedDescriptor();
        const payouts = json.payouts || [];
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        instance.outcomes = payouts.map((payout) => ({
            outcome: payout.outcome,
            localPayout: BigInt(payout.offerPayout || 0), // Use canonical offerPayout field
        }));
        return instance;
    }
    /**
     * Deserializes an enumerated_contract_descriptor message
     * @param buf
     */
    static deserialize(buf) {
        const instance = new EnumeratedDescriptor();
        const reader = new bufio_1.BufferReader(buf);
        reader.readBigSize(); // read type (0)
        const numOutcomes = Number(reader.readBigSize());
        for (let i = 0; i < numOutcomes; i++) {
            const outcomeLen = Number(reader.readBigSize());
            const outcome = reader.readBytes(outcomeLen).toString();
            const localPayout = reader.readUInt64BE();
            instance.outcomes.push({
                outcome,
                localPayout,
            });
        }
        return instance;
    }
    /**
     * Converts enumerated_contract_descriptor to JSON
     */
    toJSON() {
        // Return enum variant format for Rust compatibility
        return {
            enumeratedContractDescriptor: {
                payouts: this.outcomes.map((outcome) => ({
                    outcome: outcome.outcome,
                    offerPayout: Number(outcome.localPayout), // Use offerPayout to match Rust
                })),
            },
        };
    }
    /**
     * Serializes the enumerated_contract_descriptor message into a Buffer
     */
    serialize() {
        const writer = new bufio_1.BufferWriter();
        writer.writeBigSize(this.contractDescriptorType);
        writer.writeBigSize(this.outcomes.length);
        for (const outcome of this.outcomes) {
            writer.writeBigSize(outcome.outcome.length);
            writer.writeBytes(Buffer.from(outcome.outcome));
            writer.writeUInt64BE(outcome.localPayout);
        }
        return writer.toBuffer();
    }
}
exports.EnumeratedDescriptor = EnumeratedDescriptor;
EnumeratedDescriptor.contractDescriptorType = MessageType_1.ContractDescriptorType.Enumerated;
/**
 * NumericOutcomeContractDescriptor contains information about a contract's outcomes
 * and their corresponding payouts (for numeric outcomes).
 * This corresponds to the previous ContractDescriptorV1.
 */
class NumericalDescriptor extends ContractDescriptor {
    constructor() {
        super(...arguments);
        /**
         * The type for numeric_outcome_contract_descriptor message - using MessageType for IDlcMessage compatibility
         */
        this.type = MessageType_1.MessageType.ContractDescriptorV1; // For IDlcMessage compatibility
        /**
         * The contract descriptor type for new format
         */
        this.contractDescriptorType = MessageType_1.ContractDescriptorType.NumericOutcome;
    }
    /**
     * Creates a NumericOutcomeContractDescriptor from JSON data
     * @param json JSON object representing a numeric outcome contract descriptor
     */
    // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any
    static fromJSON(json) {
        const instance = new NumericalDescriptor();
        instance.numDigits = json.numDigits || json.num_digits || 0;
        // Parse payout function using proper fromJSON method
        instance.payoutFunction = PayoutFunction_1.PayoutFunction.fromJSON(json.payoutFunction || json.payout_function);
        // Parse rounding intervals using proper fromJSON method
        instance.roundingIntervals = RoundingIntervals_1.RoundingIntervals.fromJSON(json.roundingIntervals || json.rounding_intervals);
        return instance;
    }
    /**
     * Deserializes a numeric_outcome_contract_descriptor message
     * @param buf
     */
    static deserialize(buf) {
        const instance = new NumericalDescriptor();
        const reader = new bufio_1.BufferReader(buf);
        reader.readBigSize(); // read type (1)
        instance.numDigits = reader.readUInt16BE();
        // Parse payout function - need to calculate its size to avoid consuming all bytes
        const payoutFunctionStartPos = reader.position;
        const tempPayoutFunction = PayoutFunction_1.PayoutFunction.deserialize(reader.buffer.subarray(reader.position));
        instance.payoutFunction = tempPayoutFunction;
        // Skip past the payout function bytes
        const payoutFunctionSize = tempPayoutFunction.serialize().length;
        reader.position = payoutFunctionStartPos + payoutFunctionSize;
        // Parse remaining bytes as rounding intervals
        instance.roundingIntervals = RoundingIntervals_1.RoundingIntervals.deserialize(reader.buffer.subarray(reader.position));
        return instance;
    }
    /**
     * Validates correctness of all fields in the message
     * https://github.com/discreetlogcontracts/dlcspecs/blob/master/Messaging.md#the-contract_descriptor-type
     * @throws Will throw an error if validation fails
     */
    validate() {
        this.roundingIntervals.validate();
    }
    /**
     * Converts numeric_outcome_contract_descriptor to JSON
     */
    toJSON() {
        // Return enum variant format for Rust compatibility
        return {
            numericOutcomeContractDescriptor: {
                numDigits: this.numDigits,
                payoutFunction: this.payoutFunction.toJSON(),
                roundingIntervals: this.roundingIntervals.toJSON(),
            },
        };
    }
    /**
     * Serializes the numeric_outcome_contract_descriptor message into a Buffer
     */
    serialize() {
        const writer = new bufio_1.BufferWriter();
        writer.writeBigSize(this.contractDescriptorType);
        writer.writeUInt16BE(this.numDigits);
        writer.writeBytes(this.payoutFunction.serialize());
        writer.writeBytes(this.roundingIntervals.serialize());
        return writer.toBuffer();
    }
}
exports.NumericalDescriptor = NumericalDescriptor;
NumericalDescriptor.contractDescriptorType = MessageType_1.ContractDescriptorType.NumericOutcome;
// Legacy support - keeping old class names as aliases
exports.ContractDescriptorV0 = EnumeratedDescriptor;
exports.ContractDescriptorV1 = NumericalDescriptor;
//# sourceMappingURL=ContractDescriptor.js.map