package com.atlassian.bitbucket.internal.branch.model.dao;

import com.atlassian.bitbucket.internal.branch.model.configuration.BranchModelConfiguration;
import com.atlassian.bitbucket.internal.branch.model.configuration.BranchModelConfigurationRequest;
import com.atlassian.bitbucket.repository.Repository;

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

/**
 * Data access object for {@link AoBranchModelConfiguration} entities.
 *
 * @since 2.8
 */
public interface BranchModelDao {

    /**
     * Create branch model mapped to {@code repository} with data specified by the {@code request}. The created
     * branch model will be in enabled state by default.
     *
     * @param repository repository to associate branch model with. This must be an existing repository.
     * @param request request specifying data for the new branch model configuration
     * @return {@link BranchModelConfiguration} representing the newly created entity
     * @throws NullPointerException if any of the arguments is {@code null}
     * @throws IllegalArgumentException if repository does not exist (i.e. {@code repository.getId()} returns
     * {@code null})
     */
    @Nonnull
    PersistentBranchModelConfiguration create(@Nonnull Repository repository,
                                              @Nonnull BranchModelConfigurationRequest request);

    /**
     * Delete any existing branch model entity associated with {@code repository}.
     *
     * @param repository repository
     */
    void deleteByRepository(@Nonnull Repository repository);

    /**
     * Get an instance of {@link BranchModelConfiguration} representing branch model configuration of {@code repository}.
     *
     * @param repository repository, must not be {@code null} and must be an existing repository.
     * @return branch model configuration instance, or {@code null}, if no branch model is associated with
     * {@code repository}.
     * @throws NullPointerException if {@code repository} is {@code null}
     * @throws IllegalArgumentException if repository does not exist (i.e. {@code repository.getId()} returns
     * {@code null})
     */
    @Nullable
    PersistentBranchModelConfiguration getByRepository(@Nonnull Repository repository);


    /**
     * Set state of the branch model associated with {@code repository} to enabled. There must be an existing branch
     * model entity associated with {@code repository} already. Otherwise clients need to
     * {@link #create(Repository, BranchModelConfigurationRequest) create the branch model} first.
     *
     * @return {@code true}, if the state was actually changed, {@code false} otherwise
     * @throws NullPointerException if {@code repository} is {@code null}
     * @throws IllegalArgumentException if repository does not exist (i.e. {@code repository.getId()} returns
     * {@code null}), or the branch model for that {@code repository} does not exist (i.e.
     * {@link #getByRepository(Repository)} returns {@code null} for that {@code repository}).
     */
    boolean setEnabled(@Nonnull Repository repository, boolean enabled);

    /**
     * Update branch model configuration of {@code repository} according to the {@code updateRequest}. There must be an
     * existing branch model entity associated with {@code repository} already. Otherwise clients should use
     * {@link #create(Repository, BranchModelConfigurationRequest)}.
     *
     * @param repository repository
     * @param updateRequest update request
     * @throws NullPointerException if {@code repository} is {@code null}
     * @throws IllegalArgumentException if repository does not exist (i.e. {@code repository.getId()} returns
     * {@code null}), or the branch model for that {@code repository} does not exist (i.e.
     * {@link #getByRepository(Repository)} returns {@code null} for that {@code repository}).
     */
    void update(@Nonnull Repository repository, @Nonnull BranchModelConfigurationRequest updateRequest);
}
