/*
 * Copyright Debezium Authors.
 *
 * Licensed under the Apache Software License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
 */

package io.debezium.connector.postgresql.connection;

import java.nio.ByteBuffer;
import java.sql.SQLException;
import java.util.function.Function;

import org.postgresql.replication.fluent.logical.ChainedLogicalStreamBuilder;

import io.debezium.connector.postgresql.TypeRegistry;
import io.debezium.connector.postgresql.connection.ReplicationStream.ReplicationMessageProcessor;

/**
 * A class that is able to deserialize/decode binary representation of a batch of replication messages generated by
 * logical decoding plugin. Clients provide a callback code for processing.
 *
 * @author Jiri Pechanec
 *
 */
public interface MessageDecoder {

    /**
     * Process a message upon arrival from logical decoder
     *
     * @param buffer - binary representation of replication message
     * @param processor - message processing on arrival
     * @param typeRegistry - registry with known types
     */
    void processMessage(ByteBuffer buffer, ReplicationMessageProcessor processor, TypeRegistry typeRegistry) throws SQLException, InterruptedException;

    /**
     * Allows MessageDecoder to configure options with which the replication stream is started.
     * See PostgreSQL command START_REPLICATION SLOT for more details.
     *
     * @param builder
     * @return the builder instance
     */
    ChainedLogicalStreamBuilder defaultOptions(ChainedLogicalStreamBuilder builder, Function<Integer, Boolean> hasMinimumServerVersion);

    /**
     * A callback into the decoder allowing it to decide whether the supplied message should be processed
     * by the decoder or whether it can be skipped.
     *
     * @param buffer the replication stream buffer
     * @param lastReceivedLsn the last LSN reported by the replication stream
     * @param startLsn the starting LSN reported by the streaming producer
     * @param walPosition wal position from which the streaming should resume
     * @return {@code true} if the incoming message should be skipped, {@code false} otherwise
     */
    boolean shouldMessageBeSkipped(ByteBuffer buffer, Lsn lastReceivedLsn, Lsn startLsn, WalPositionLocator walPosition);

    /**
     * Closes this decoder, freeing and/or closing all resources it may potentially hold.
     */
    void close();
}
