package com.atlassian.stash.internal.pull;

import com.atlassian.bitbucket.validation.annotation.RequiredString;

import javax.annotation.Nonnull;
import javax.persistence.Column;
import javax.persistence.Embeddable;
import java.util.Objects;

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

/**
 * Describes a single commit, either added or removed, included in a {@link InternalPullRequestRescopeActivity rescope
 * activity}.
 * <p>
 * Because this class is {@code Embeddable}, it does not define the ID of the rescope activity to which it belongs.
 * That ID is provided by the {@code JoinColumn} entry on the {@code CollectionTable} mapping that embeds the commits.
 *
 * @since 2.5
 */
@Embeddable
public class InternalPullRequestRescopeCommit {

    @Column(name = "action", nullable = false)
    @org.hibernate.annotations.Type(type = "com.atlassian.hibernate.extras.type.GenericEnumUserType", parameters = {
            @org.hibernate.annotations.Parameter(name = "enumClass", value = "com.atlassian.stash.internal.pull.PullRequestRescopeCommitAction")
    })
    private final PullRequestRescopeCommitAction action;

    @Column(name = "changeset_id", nullable = false, length = 40)
    @RequiredString(size = 40)
    private final String commitId;

    protected InternalPullRequestRescopeCommit() {
        action = null;
        commitId = null;
    }

    private InternalPullRequestRescopeCommit(String commitId, PullRequestRescopeCommitAction action) {
        this.action = action;
        this.commitId = commitId;
    }

    @Override
    public boolean equals(Object o) {
        if (o == this) {
            return true;
        }
        if (o instanceof InternalPullRequestRescopeCommit) {
            InternalPullRequestRescopeCommit c = (InternalPullRequestRescopeCommit) o;

            //The combination of activity+commit ID is the primary key for rescope commits, so the _action_ does
            //not factor into equals/hashCode; two commits with the same ID are the same commit
            return Objects.equals(getCommitId(), c.getCommitId());
        }
        return false;
    }

    @Nonnull
    public PullRequestRescopeCommitAction getAction() {
        return action;
    }

    @Nonnull
    public String getCommitId() {
        return commitId;
    }

    @Override
    public int hashCode() {
        //The combination of activity+commit ID is the primary key for rescope commits, so the _action_ does
        //not factor into equals/hashCode; two commits with the same ID are the same commit
        return Objects.hashCode(getCommitId());
    }

    public static class Builder {

        private PullRequestRescopeCommitAction action;
        private String commitId;

        public Builder() {
        }

        @Nonnull
        public Builder action(@Nonnull PullRequestRescopeCommitAction value) {
            action = checkNotNull(value, "action");

            return this;
        }

        @Nonnull
        public InternalPullRequestRescopeCommit build() {
            return new InternalPullRequestRescopeCommit(commitId, action);
        }

        @Nonnull
        public Builder commitId(@Nonnull String value) {
            commitId = checkNotNull(value, "commitId");

            return this;
        }
    }
}
