package com.atlassian.bitbucket.idx;

import com.atlassian.bitbucket.commit.Commit;
import com.atlassian.bitbucket.repository.Repository;

import javax.annotation.Nonnull;

/**
 * Describes an indexer to be notified when commits are added to or removed from a repository.
 * <p>
 * {@code CommitIndexer} implementations <i>must</i> be thread-safe, because the same instance will be used for
 * multiple indexing operations in parallel. Any state that needs to be stored during an indexing run should be
 * stored in the provided {@link IndexingContext}.
 * <p>
 * <b>Note</b>: The same {@link IndexingContext} is shared between all {@code CommitIndexer}s that are enabled for
 * a given repository. Implementations should be careful of what they store in it and what names they use for
 * properties they add to manage memory consumption and avoid collisions with other indexers.
 */
public interface CommitIndexer {

    /**
     * @return the ID for the indexer, used by the system to keep track of which commits this indexer has seen
     */
    @Nonnull
    String getId();

    /**
     * @param repository the repository
     * @return {@code true} if the indexer should index commits for the specified {@code repository}; otherwise,
     *         {@code false}
     */
    boolean isEnabledForRepository(@Nonnull Repository repository);

    /**
     * Called after the last commit has been processed to allow the indexer to perform any cleanup it needs.
     *
     * @param context the indexing context
     */
    void onAfterIndexing(@Nonnull IndexingContext context);

    /**
     * Called before the first commit is processed to allow the indexer to perform any setup it needs.
     *
     * @param context the indexing context
     */
    void onBeforeIndexing(@Nonnull IndexingContext context);

    /**
     * Called for each new commit that is added to the repository.
     * <p>
     * <b>Important:</b> This method will only be called once for a commit during an indexing run, but may be called
     * multiple times for the same commit across different indexing runs. When new {@code CommitIndexer}s are enabled,
     * all of the commits that have been added since the last time <i>any</i> {@code CommitIndexer} ran will be passed
     * to <i>all</i> indexers.
     *
     * @param commit  the added commit
     * @param context the indexing context
     */
    void onCommitAdded(@Nonnull Commit commit, @Nonnull IndexingContext context);

    /**
     * Called for each existing commit that is removed from the repository.
     * <p>
     * <b>Important:</b> This method will only be called once for a commit during an indexing run, but may be called
     * multiple times for the same commit across different indexing runs. When new {@code CommitIndexer}s are enabled,
     * all of the commits that have been removed since the last time <i>any</i> {@code CommitIndexer} ran will be passed
     * to <i>all</i> indexers.
     *
     * @param commit  the removed commit
     * @param context the indexing context
     */
    void onCommitRemoved(@Nonnull Commit commit, @Nonnull IndexingContext context);
}
