package com.atlassian.bitbucket.mesh.git.worktree;

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

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.time.Duration;
import java.util.Objects;
import java.util.Set;

import static java.util.Objects.requireNonNull;

public class CreateWorkTreeParameters extends AbstractParameters {

    private final Set<Repository> alternates;
    private final String branch;
    private final String commit;
    private final Duration expiry;
    private final boolean pristine;
    private final Repository repository;

    private CreateWorkTreeParameters(Builder builder) {
        super(builder);
        alternates = builder.alternates.build();
        branch = builder.branch;
        commit = builder.commit;
        expiry = requireNonNull(builder.expiry);
        pristine = builder.pristine;
        repository = builder.repository;
    }

    @Nonnull
    public Set<Repository> getAlternates() {
        return alternates;
    }

    @Nullable
    public String getBranch() {
        return branch;
    }

    @Nullable
    public String getCommit() {
        return commit;
    }

    @Nonnull
    public Duration getExpiry() {
        return expiry;
    }

    @Nonnull
    public Repository getRepository() {
        return repository;
    }

    public boolean isPristine() {
        return pristine;
    }

    public static class Builder extends AbstractParameters.AbstractBuilder<CreateWorkTreeParameters.Builder, CreateWorkTreeParameters> {

        private final ImmutableSet.Builder<Repository> alternates = ImmutableSet.builder();
        private final String commit;
        private final Duration expiry;
        private final Repository repository;

        private String branch;
        private boolean pristine;

        public Builder(@Nonnull Repository repository, @Nullable String commit, @Nonnull Duration expiry) {
            this.repository = requireNonNull(repository, "repository");
            this.commit = commit;
            this.expiry = requireNonNull(expiry, "expiry");
        }

        public Builder(@Nonnull CreateWorkTreeParameters parameters) {
            super(requireNonNull(parameters, "parameters"));

            alternates.addAll(parameters.getAlternates());
            branch = parameters.getBranch();
            commit = parameters.getCommit();
            expiry = parameters.getExpiry();
            pristine = parameters.isPristine();
            repository = parameters.getRepository();
        }

        @Nonnull
        public Builder alternate(@Nonnull Repository value) {
            alternates.add(requireNonNull(value, "alternate"));

            return self();
        }

        @Nonnull
        public Builder alternates(@Nullable Iterable<Repository> values) {
            addIf(Objects::nonNull, alternates, values);

            return self();
        }

        @Nonnull
        public Builder alternates(@Nullable Repository value, @Nullable Repository... values) {
            addIf(Objects::nonNull, alternates, value, values);

            return self();
        }

        @Nonnull
        public Builder branch(@Nullable String value) {
            branch = value;

            return self();
        }

        @Nonnull
        @Override
        public CreateWorkTreeParameters build() {
            return new CreateWorkTreeParameters(this);
        }
        
        /**
         * @param value {@code true} to request a pristine working copy; otherwise, {@code false} to allow unstaged
         *              changes
         * @return {@code this}
         */
        @Nonnull
        public Builder pristine(boolean value) {
            pristine = value;

            return self();
        }

        @Nonnull
        @Override
        protected Builder self() {
            return this;
        }
    }
}
