{%- import "cloudevents.jinja.include" as cloudEvents -%}
{%- import "util.jinja.include" as util -%}
{%- set data_module_name = data_project_name | strip_invalid_identifier_characters %}
// This code was generated by the xRegistry tool.
// Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.

import * as rhea from 'rhea';

/**
 * Context object for AMQP message processing.
 * 
 * Provides methods to accept, reject, or release a message back to the broker.
 * Each message must be settled exactly once using one of the settlement methods.
 * 
 * @example
 * ```typescript
 * async function handler(cloudEvent: CloudEvent, data: PrintJobStartedData, context: MessageContext) {
 *     try {
 *         await processMessage(data);
 *         context.accept(); // Successful processing
 *     } catch (error) {
 *         if (isValidationError(error)) {
 *             context.reject(); // Permanent failure, don't retry
 *         } else {
 *             context.release(); // Temporary failure, allow retry
 *         }
 *     }
 * }
 * ```
 */
export class MessageContext {
    private _settled: boolean = false;
    
    /**
     * Creates a new MessageContext.
     * 
     * @param eventContext - The rhea EventContext for message settlement
     * @internal
     */
    constructor(private readonly eventContext: rhea.EventContext) {}
    
    /**
     * Accepts the message, indicating successful processing.
     * 
     * Once a message is accepted, it will be removed from the queue
     * and will not be redelivered.
     * 
     * @throws {Error} If the message has already been settled
     */
    accept(): void {
        if (this._settled) {
            throw new Error('Message has already been settled');
        }
        this.eventContext.delivery?.accept();
        this._settled = true;
    }
    
    /**
     * Rejects the message, indicating permanent failure.
     * 
     * Rejected messages are typically moved to a dead-letter queue
     * or discarded, depending on broker configuration. Use this for
     * validation errors or other permanent failures.
     * 
     * @throws {Error} If the message has already been settled
     */
    reject(): void {
        if (this._settled) {
            throw new Error('Message has already been settled');
        }
        this.eventContext.delivery?.reject();
        this._settled = true;
    }
    
    /**
     * Releases the message back to the sender for redelivery.
     * 
     * Released messages will be requeued and may be redelivered to
     * this or another consumer. Use this for transient failures like
     * temporary network issues or resource unavailability.
     * 
     * @throws {Error} If the message has already been settled
     */
    release(): void {
        if (this._settled) {
            throw new Error('Message has already been settled');
        }
        this.eventContext.delivery?.release();
        this._settled = true;
    }
    
    /**
     * Modifies the message delivery state.
     * 
     * This advanced settlement option allows fine-grained control over
     * message redelivery behavior.
     * 
     * @param deliveryFailed - Indicates if delivery failed
     * @param undeliverableHere - Indicates if the message is undeliverable at this receiver
     * @throws {Error} If the message has already been settled
     */
    modify(deliveryFailed: boolean, undeliverableHere: boolean = false): void {
        if (this._settled) {
            throw new Error('Message has already been settled');
        }
        this.eventContext.delivery?.modified({
            delivery_failed: deliveryFailed,
            undeliverable_here: undeliverableHere
        });
        this._settled = true;
    }
    
    /**
     * Checks if the message has been settled.
     * 
     * @returns true if the message has been accepted, rejected, released, or modified
     */
    get isSettled(): boolean {
        return this._settled;
    }
}
