package com.atlassian.bitbucket.mesh.git.hosting;

import com.atlassian.bitbucket.mesh.repository.Repository;
import com.atlassian.bitbucket.mesh.rpc.v1.RpcStreamChunk;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

/**
 * Component that may be interested in parsing, and possibly manipulating, the stdin of a
 * {@code git receive-pack} operation
 */
public interface GitReceivePackListener {

    /**
     * Method invoked by the system when a {@code receive-pack} operation is detected, before any stdin input is
     * processed. Implementers should return a non-null {@link GitReceivePackFilter} if they want to receive
     * callbacks for each stdin {@link RpcStreamChunk} received for this operation.
     * <p>
     * The returned filter will receive {@link GitReceivePackFilter#onPacketLine packet line chunks} until
     * if signals that is in done by returning {@code false} from {@link GitReceivePackFilter#wantsPacketLines},
     * or stdin runs out of packet lines.
     * <p>
     * The returned filter will receive {@link GitReceivePackFilter#onPack(RpcStreamChunk)}  pack chunks} until
     * if signals that is in done by returning {@code false} from {@link GitReceivePackFilter#wantsPack()},
     * or stdin runs out of packs.
     * <p>
     * In the receive-pack protocol, the pack section follows the packet lines. As a result, the first call to
     * {@link GitReceivePackFilter#onPack(RpcStreamChunk)} implicitly signals the end of the packet lines section.
     * <p>
     * The returned filter can <em>manipulate</em> stdin by returning an altered {@link RpcStreamChunk} from either
     * callback method. When returning an altered git packet line chunk, special care needs to be taken to also update
     * the packet line prefix (first for bytes the contain the packet line length in hex).
     *
     * @param repository the repository
     * @return the {@link GitReceivePackFilter} listener to send stdin chunks to, or {@code null} if no stdin
     *         chunks need to be processed
     */
    @Nullable
    GitReceivePackFilter createFilter(@Nonnull Repository repository);
}