package com.atlassian.stash.internal.scm.git.porcelain;

import com.atlassian.bitbucket.repository.Repository;
import com.atlassian.bitbucket.scm.git.GitAgent;
import com.atlassian.bitbucket.user.Person;
import com.google.common.base.MoreObjects;
import com.google.common.base.Strings;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.File;

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

/**
 * @since 2.9
 */
public class FetchRequest extends AbstractTimedRequest {

    private final Person author;
    private final boolean forced;
    private final File remote;
    private final Repository repository;
    private final String source;
    private final String target;

    private FetchRequest(Builder builder) {
        super(builder);

        author = checkNotNull(builder.author, "author");
        forced = builder.forced;
        remote = checkNotNull(builder.remote, "remote");
        repository = checkNotNull(builder.repository, "repository");
        source = MoreObjects.firstNonNull(builder.source, GitAgent.HEAD); //Fetch the remote HEAD by default
        target = Strings.nullToEmpty(builder.target); //If no explicit target is provided, just update FETCH_HEAD
    }

    @Nonnull
    public String buildRefspec() {
        StringBuilder refspec = new StringBuilder();
        if (isForced()) {
            refspec.append("+"); //Leading + enables non-fast-forward updates
        }
        refspec.append(getSource())
                .append(":")
                .append(getTarget());

        return refspec.toString();
    }

    @Nonnull
    public Person getAuthor() {
        return author;
    }

    @Nonnull
    public File getRemote() {
        return remote;
    }

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

    @Nonnull
    public String getSource() {
        return source;
    }

    @Nonnull
    public String getTarget() {
        return target;
    }

    public boolean isForced() {
        return forced;
    }

    public static class Builder extends AbstractBuilder<Builder, FetchRequest> {

        private final Person author;
        private final File remote;
        private final Repository repository;

        private boolean forced;
        private String source;
        private String target;

        public Builder(@Nonnull Repository repository, @Nonnull File remote, @Nonnull Person author) {
            this.author = checkNotNull(author, "author");
            this.remote = checkNotNull(remote, "remote");
            this.repository = checkNotNull(repository, "repository");
        }

        public Builder(@Nonnull FetchRequest request) {
            super(request);

            author = request.getAuthor();
            forced = request.isForced();
            remote = request.getRemote();
            repository = request.getRepository();
            source = request.getSource();
            target = request.getTarget();
        }

        @Nonnull
        @Override
        public FetchRequest build() {
            return new FetchRequest(this);
        }

        @Nonnull
        public Builder forced(boolean value) {
            forced = value;

            return self();
        }

        @Nonnull
        public Builder source(@Nullable String value) {
            source = Strings.emptyToNull(value);

            return self();
        }

        @Nonnull
        public Builder target(@Nullable String value) {
            target = Strings.emptyToNull(value);

            return self();
        }

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