package com.atlassian.bitbucket.mesh.git;

import com.atlassian.bitbucket.mesh.git.exception.LfsByteRangeNotSatisfiableException;
import com.atlassian.bitbucket.mesh.git.exception.ObjectNotFoundException;
import com.atlassian.bitbucket.mesh.io.IoSupplier;
import com.atlassian.bitbucket.mesh.repository.Repository;

import javax.annotation.Nonnull;
import java.io.InputStream;

public interface LfsManager {

    /**
     * Check if the store has sufficient free space to store an a set of objects totalling the given size.
     *
     * @param repository    the repository, used to determine where LFS content would be stored
     * @param size          the size, in bytes, of the object(s) to be stored
     * @return true if the object(s) can be stored, or false if insufficient free space exists
     */
    boolean canStore(@Nonnull Repository repository, long size);

    /**
     * Check if the object exists in the store for the specified repository.
     *
     * @param repository the repository to search for the object in
     * @param oid        the object id
     * @return true if the object exists, otherwise false
     */
    boolean objectExists(@Nonnull Repository repository, @Nonnull String oid);

    /**
     * Obtain an {@link IoSupplier} from which the object can be read.
     *
     * @param repository    the repository the object exists in
     * @param oid           the object id
     * @return an {@link IoSupplier} from which the object can be read
     * @throws ObjectNotFoundException if the object cannot be found in the given repository
     */
    @Nonnull
    IoSupplier<InputStream> readObject(@Nonnull Repository repository, @Nonnull String oid);

    /**
     * Obtain an {@link IoSupplier} object from which the object can be read.
     *
     * @param repository    the repository the object exists in
     * @param oid           the object id
     * @param start         the start of the byte range to read (inclusive)
     * @param end           the end of the byte range to read (inclusive)
     * @return an {@link IoSupplier} from which the object can be read
     * @throws ObjectNotFoundException if the object cannot be found in the given repository
     * @throws LfsByteRangeNotSatisfiableException if the range request was not satisfiable for the requested object
     */
    @Nonnull
    IoSupplier<InputStream> readObject(@Nonnull Repository repository, @Nonnull String oid, long start, long end);

    /**
     * Obtain an {@link LfsObjectWriter} from which the object can be written to.
     *
     * @param repository    the repository the object will be written to
     * @param oid           the object id
     * @return an {@link LfsObjectWriter} object from which the object can be written to
     */
    @Nonnull
    LfsObjectWriter writeObject(@Nonnull Repository repository, @Nonnull String oid);
}
