package com.atlassian.stash.internal.user;

import com.atlassian.stash.internal.repository.InternalRepository;
import com.atlassian.bitbucket.permission.Permission;

import javax.annotation.Nonnull;
import javax.persistence.*;
import java.util.Objects;

@Entity
@Table(name = InternalRepositoryPermission.TABLE, indexes = {
        @Index(name = "idx_repo_permission_user", columnList = "user_id"),
        @Index(name = "idx_repo_permission_group", columnList = "group_name")
})
public class InternalRepositoryPermission extends InternalGrantedPermission {

    static final String TABLE = "sta_repo_permission";

    @JoinColumn(name = "repo_id")
    @ManyToOne(fetch = FetchType.LAZY)
    private final InternalRepository repository;

    // for hibernate
    @SuppressWarnings("unused")
    protected InternalRepositoryPermission() {
        super();
        repository = null;
    }

    @Override
    public void accept(@Nonnull InternalGrantedPermissionVisitor visitor) {
        visitor.visit(this);
    }

    private InternalRepositoryPermission(Long id, Permission permission, InternalRepository repository, String group,
                                         InternalApplicationUser user) {
        super(id, permission, group, user);
        this.repository = repository;
    }

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

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

            return Objects.equals(getPermission(), that.getPermission()) &&
                    Objects.equals(getGroup(), that.getGroup()) &&
                    Objects.equals(getId(), that.getId()) &&
                    Objects.equals(getRepository(), that.getRepository()) &&
                    Objects.equals(getUser(), that.getUser());
        }

        return false;
    }

    @Override
    public int hashCode() {
        return Objects.hash(getPermission(), getGroup(), getId(), getRepository(), getUser());
    }
    
    public static final class Builder extends AbstractBuilder<Builder> {
        
        private InternalRepository repository;

        public Builder() {
            super();
        }
        
        public Builder(InternalRepositoryPermission source) {
            super(source);
            repository = source.getRepository();
        }

        public InternalRepositoryPermission build() {
            return new InternalRepositoryPermission(id, permission, repository, group, user);
        }

        public Builder repository(InternalRepository repository) {
            this.repository = repository;
            return self();
        }

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

    }
}
