package com.atlassian.stash.internal.user;

import com.atlassian.stash.internal.project.InternalProject;
import com.atlassian.bitbucket.permission.Permission;

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

@Entity
@Table(name = InternalProjectPermission.TABLE, indexes = {
        @Index(name = "idx_project_permission_user", columnList = "user_id"),
        @Index(name = "idx_project_permission_group", columnList = "group_name")
})
public class InternalProjectPermission extends InternalGrantedPermission {

    static final String TABLE = "sta_project_permission";

    @ManyToOne(fetch = FetchType.LAZY)
    private final InternalProject project;
    
    @SuppressWarnings("unused") // for hibernate
    protected InternalProjectPermission() {
        super();
        project = null;
    }

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

    private InternalProjectPermission(Long id, Permission permission, InternalProject project, String group,
                                      InternalApplicationUser user) {
        super(id, permission, group, user);
        this.project = project;
    }

    @Nonnull
    public InternalProject getProject() {
        return project;
    }

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

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

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

        public Builder() {
            super();
        }
        
        public Builder(InternalProjectPermission source) {
            super(source);
            project = source.getProject();
        }

        public InternalProjectPermission build() {
            return new InternalProjectPermission(id, permission, project, group, user);
        }

        public Builder project(InternalProject project) {
            this.project = project;

            return this;
        }

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

    }
}
