package com.atlassian.bitbucket.internal.mirroring.upstream;

import com.atlassian.bitbucket.internal.mirroring.MirroringRequest;
import com.atlassian.bitbucket.mirroring.upstream.*;
import com.atlassian.bitbucket.util.Page;
import com.atlassian.bitbucket.util.PageRequest;

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

/**
 * A service for managing requests to act as a mirror
 */
public interface MirroringRequestService {

    /**
     * Accepts a {@link MirroringRequest}
     *
     * @return the accepted {@link MirrorServer}
     * @throws MirrorAlreadyRegisteredException if a mirror for the given
     *                                          {@link MirroringRequest#getMirrorId() mirror id} is already registered
     */
    @Nonnull
    MirrorServer accept(@Nonnull MirroringRequest request);

    /**
     * Deletes a {@link MirroringRequest}
     */
    void delete(@Nonnull MirroringRequest request);

    /**
     * Finds all {@link MirroringRequest MirroringRequests} within the bounds of the page request.
     */
    @Nonnull
    Page<MirroringRequest> findAll(@Nonnull PageRequest pageRequest);

    /**
     * Finds all {@link MirroringRequest MirroringRequests} that match the search within the bounds of the page request.
     */
    @Nonnull
    Page<MirroringRequest> findAll(@Nonnull MirroringRequestSearchRequest searchRequest, @Nonnull PageRequest pageRequest);

    /**
     * @return a {@link MirroringRequest} with the specified {@link MirroringRequest#getId() id} or null if no such request exists
     */
    @Nullable
    MirroringRequest getById(int id);

    /**
     * Registers a new {@link MirroringRequest}
     *
     * @throws MirrorAlreadyRegisteredException if a mirror with the specified
     *                                          {@link MirroringRequest#getMirrorId() mirror id} is already registered
     * @throws ConflictingMirroringRequestException if the supplied request conflicts with an existing request for the
     *                                              same {@link MirroringRequest#getMirrorId() mirror id}
     * @throws MirroringRequestLimitExceededException if there are too many pending mirroring requests - this prevents
     * mirroring requests from becoming a DoS vector
     *
     */
    @Nonnull
    MirroringRequest register(@Nonnull MirroringRequest request);

    /**
     * Rejects a {@link MirroringRequest}
     *
     * @throws IllegalMirroringRequestStateException if the request is already accepted
     */
    @Nonnull
    MirroringRequest reject(@Nonnull MirroringRequest request);

}