package com.atlassian.bitbucket.scm;

import com.atlassian.bitbucket.repository.Repository;
import com.google.common.collect.ImmutableSet;

import javax.annotation.Nonnull;
import java.util.Set;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;

public class DeleteCommandParameters extends AbstractCommandParameters {

    private final Set<Integer> forkIds;
    private final boolean lastInHierarchy;

    private DeleteCommandParameters(Set<Integer> forkIds, boolean lastInHierarchy) {
        this.forkIds = checkNotNull(forkIds, "forkIds");
        this.lastInHierarchy = lastInHierarchy;

        if (lastInHierarchy) {
            checkArgument(forkIds.isEmpty(), "A repository cannot have forks and be the last in its hierarchy");
        }
    }

    /**
     * Provides the {@link Repository#getId() IDs} of all repositories that were forked from the repository being
     * deleted <i>which have not, themselves, been deleted</i>. As the repository has already been deleted from the
     * database, the host application must provide these IDs because it is no longer possible to query for them.
     * <p>
     * The returned set will always be empty for the {@link #isLastInHierarchy() last repository in a hierarchy}.
     *
     * @return a set containing 0 or more fork IDs
     */
    @Nonnull
    public Set<Integer> getForkIds() {
        return forkIds;
    }

    /**
     * Retrieves a flag indicating whether the deleted repository has {@link #getForkIds() forks}.
     * <p>
     * If {@link #isLastInHierarchy()} is {@code true}, this will always be {@code false}.
     *
     * @return {@code true} if the {@link #getForkIds() fork ID} set is not empty; otherwise, {@code false}
     */
    public boolean hasForks() {
        return !forkIds.isEmpty();
    }

    /**
     * Retrieves a flag indicating whether this repository was the last in its {@link Repository#getHierarchyId()
     * hierarchy}, allowing the SCM to perform any additional cleanup that is necessary when an entire hierarchy
     * is deleted.
     *
     * @return {@code true} if this repository is the last in its hierarchy; otherwise, {@code false} if at least
     *         one repository remains in the hierarchy
     */
    public boolean isLastInHierarchy() {
        return lastInHierarchy;
    }

    public static class Builder {

        private ImmutableSet.Builder<Integer> forkIds;
        private boolean lastInHierarchy;

        public Builder() {
            forkIds = ImmutableSet.builder();
        }

        public DeleteCommandParameters build() {
            return new DeleteCommandParameters(forkIds.build(), lastInHierarchy);
        }

        public Builder forkIds(@Nonnull Iterable<Integer> value) {
            forkIds.addAll(value);

            return this;
        }

        public Builder lastInHierarchy() {
            lastInHierarchy = true;

            return this;
        }
    }
}
