package com.atlassian.bitbucket.comment;

import com.atlassian.bitbucket.util.BuilderSupport;
import org.apache.commons.lang3.StringUtils;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Optional;

import static com.google.common.base.Preconditions.checkArgument;
import static java.util.Objects.requireNonNull;
import static java.util.Optional.ofNullable;

/**
 * A base class for adding file level comments in a diff
 *
 * @since 4.7
 */
public class AbstractAddFileCommentRequest {

    private final String path;
    private final String srcPath;
    private final String text;

    protected AbstractAddFileCommentRequest(AbstractBuilder<?, ?> builder) {
        checkArgument(StringUtils.isNotBlank(builder.path), "path");
        checkArgument(StringUtils.isNotBlank(builder.text), "text");

        path = StringUtils.trim(builder.path);
        srcPath = StringUtils.trimToNull(builder.srcPath);
        text = builder.text;
    }

    /**
     * @return the path of the file to comment on
     */
    @Nonnull
    public String getPath() {
        return path;
    }

    /**
     * @return the path the file to comment on used to have, for copies and moves
     */
    @Nonnull
    public Optional<String> getSrcPath() {
        return ofNullable(srcPath);
    }

    /**
     * @return the comment text
     */
    @Nonnull
    public String getText() {
        return text;
    }

    protected abstract static class AbstractBuilder<B extends AbstractAddFileCommentRequest.AbstractBuilder<B, R>,
            R extends AbstractAddFileCommentRequest> extends BuilderSupport {

        private String path;
        private String srcPath;
        private String text;

        protected AbstractBuilder() {
        }

        protected AbstractBuilder(@Nonnull AbstractAddFileCommentRequest request) {
            path = requireNonNull(request, "request").path;
            srcPath = request.srcPath;
            text = request.text;
        }

        @Nonnull
        public abstract R build();

        @Nonnull
        public B path(@Nonnull String value) {
            path = value;

            return self();
        }

        @Nonnull
        public B srcPath(@Nullable String value) {
            srcPath = value;

            return self();
        }

        @Nonnull
        public B text(@Nonnull String value) {
            text = value;

            return self();
        }

        @Nonnull
        protected abstract B self();
    }
}
