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

import com.atlassian.bitbucket.mesh.git.AbstractParameters;
import com.atlassian.bitbucket.mesh.git.ref.Branch;
import com.atlassian.bitbucket.mesh.repository.Repository;
import com.atlassian.bitbucket.mesh.rpc.v1.RpcGitTimeouts;
import com.atlassian.bitbucket.mesh.util.Person;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.time.Instant;
import java.time.temporal.ChronoField;

import static java.util.Objects.requireNonNull;
import static org.apache.commons.lang3.StringUtils.trimToNull;

public class EditFileParameters extends AbstractParameters {

    private final Person author;
    private final Branch branch;
    private final Person committer;
    private final String message;
    private final String path;
    private final String sourceCommitId;
    private final Repository repository;
    private final String targetBranch;
    private final Instant timestamp;

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

        author = requireNonNull(builder.author, "author");
        branch = builder.branch;
        committer = requireNonNull(builder.committer, "committer");
        message = requireNonNull(builder.message, "message");
        path = requireNonNull(builder.path, "path");
        repository = builder.repository;
        sourceCommitId = builder.sourceCommitId;
        targetBranch = requireNonNull(builder.targetBranch, "targetBranch");
        timestamp = (builder.timestamp == null ? Instant.now() : builder.timestamp)
                .with(ChronoField.NANO_OF_SECOND, 0L); //Truncate nanoseconds, if any
    }

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

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

    @Nonnull
    public Person getCommitter() {
        return committer;
    }

    @Nonnull
    public String getMessage() {
        return message;
    }

    @Nonnull
    public String getPath() {
        return path;
    }

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

    @Nullable
    public String getSourceCommitId() {
        return sourceCommitId;
    }

    @Nonnull
    public String getTargetBranch() {
        return targetBranch;
    }

    @Nonnull
    public Instant getTimestamp() {
        return timestamp;
    }

    @Override
    public String toString() {
        return repository + ": Edit " + path;
    }

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

        private final Repository repository;

        private Person author;
        private Branch branch;
        private Person committer;
        private String message;
        private String path;
        private String sourceCommitId;
        private String targetBranch;
        private Instant timestamp;

        public Builder(@Nonnull Repository repository, @Nonnull RpcGitTimeouts timeouts) {
            super(timeouts);

            this.repository = requireNonNull(repository, "repository");
        }

        @Nonnull
        public Builder author(@Nonnull Person value) {
            author = requireNonNull(value, "author");

            return self();
        }

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

            return self();
        }

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

        @Nonnull
        public Builder committer(@Nonnull Person value) {
            committer = requireNonNull(value, "committer");

            return self();
        }

        @Nonnull
        public Builder message(@Nonnull String value) {
            message = requireNonNull(value, "message");

            return self();
        }

        @Nonnull
        public Builder path(@Nonnull String value) {
            path = requireNonNull(value, "path");

            return self();
        }

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

            return self();
        }

        @Nonnull
        public Builder targetBranch(@Nonnull String value) {
            targetBranch = requireNonNull(value, "targetRef");

            return self();
        }

        @Nonnull
        public Builder timestamp(@Nullable Instant value) {
            timestamp = value;

            return self();
        }

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