package com.atlassian.bitbucket.mesh.config;

import com.atlassian.bitbucket.mesh.annotation.ManagedByControlPlane;
import com.atlassian.bitbucket.mesh.repository.ManagedRepository;
import com.atlassian.bitbucket.mesh.repository.Repository;
import com.atlassian.bitbucket.mesh.repository.SharedObjectsRepository;

import javax.annotation.Nonnull;
import java.time.Duration;

/**
 * Git garbage collection configuration
 */
public interface GcConfig {

    /**
     * @return the minimum time to wait after an garbage collection triggering event occurs before performing garbage
     *         collection
     */
    @ManagedByControlPlane
    @Nonnull
    Duration getDelay();

    /**
     * @return how often a vacuuming operation is a _full_ vacuum runs
     */
    @ManagedByControlPlane
    @Nonnull
    Duration getFullVacuumInterval();

    /**
     * @return the maximum number of incremental commit-graphs that are supported before triggering a complete rewrite
     *         a the commit-graph
     */
    @ManagedByControlPlane
    int getFullCommitGraphThreshold();

    /**
     * @return how long gc.log entries are retained
     */
    @ManagedByControlPlane
    @Nonnull
    Duration getLogRetention();

    /**
     * @return the maximum number of times garbage collection should be attempted in case of an error for a repository
     *         before giving up and logging an error
     */
    @ManagedByControlPlane
    int getMaxAttempts();

    /**
     * @return the minimum time between two pack-refs runs for a repository
     */
    @ManagedByControlPlane
    @Nonnull
    Duration getPackRefsInterval();

    /**
     * @return the maximum time a pack-refs operation is allowed to run before timing out
     */
    @ManagedByControlPlane
    @Nonnull
    Duration getPackRefsTimeout();

    /**
     * Returns the {@code gc.pruneExpire} setting for the provided {@code repository}. For repositories of type
     * {@link SharedObjectsRepository}, this is equivalent to calling {@link #getPruneExpireSharedObjects()}. For
     * {@link ManagedRepository managed repositories}, it's is equivalent to calling {@link #getPruneExpireDefault()}.
     *
     * @param repository the repository to calculate the expiry time for
     * @return the gc.pruneExpire setting
     */
    @Nonnull
    Duration getPruneExpire(@Nonnull Repository repository);

    /**
     * @return the gc.pruneExpire setting to use for repositories in which the setting is not defined
     */
    @ManagedByControlPlane
    @Nonnull
    Duration getPruneExpireDefault();

    /**
     * @return the gc.pruneExpire setting to use for shared-objects repositories
     */
    @ManagedByControlPlane
    @Nonnull
    Duration getPruneExpireSharedObjects();

    /**
     * @return the minimum time between two repack runs for a repository
     */
    @ManagedByControlPlane
    @Nonnull
    Duration getRepackInterval();

    /**
     * @return the maximum number of loose files that are allowed to exist in a repository before repacking is
     *         triggered
     */
    @ManagedByControlPlane
    int getRepackThresholdLoose();

    /**
     * @return the maximum cumulative size of loose files that are allowed to exist in a repository before
     *         triggering {@code git repack} after the next ref change
     */
    @ManagedByControlPlane
    long getRepackThresholdLooseSize();

    /**
     * @return the maximum number of pack files that are allowed to exist in a repository before repacking is triggered
     */
    @ManagedByControlPlane
    int getRepackThresholdPack();

    /**
     * @return the maximum time a repack operation is allowed to run before timing out
     */
    @ManagedByControlPlane
    @Nonnull
    Duration getRepackTimeout();

    /**
     * @return the maximum number of threads the system will use to perform garbage collection in Git repositories
     */
    @ManagedByControlPlane
    int getThreads();

    /**
     * @return the minimum time between two vacuuming runs for a hierarchy
     */
    @ManagedByControlPlane
    @Nonnull
    Duration getVacuumInterval();

    /**
     * @return whether vacuuming of reflogs should convert entries for {@code stash-refs} to {@code dark-refs}
     * @since 2.0.14, 2.1.8, 2.2.0
     */
    @ManagedByControlPlane
    boolean isConvertStashRefs();
}
