package com.atlassian.stash.internal.validation;

import com.atlassian.bitbucket.i18n.I18nService;
import com.atlassian.bitbucket.permission.Permission;
import com.atlassian.bitbucket.repository.Repository;
import com.atlassian.bitbucket.repository.RepositoryService;
import com.atlassian.bitbucket.user.SecurityService;
import com.atlassian.stash.internal.repository.InternalRepository;
import org.springframework.beans.factory.annotation.Autowired;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

public class RepositoryUniquenessValidator  implements ConstraintValidator<RepositoryUniqueness, InternalRepository> {

    private I18nService i18nService;
    private String message;
    private RepositoryService repositoryService;
    private SecurityService securityService;

    @Override
    public void initialize(RepositoryUniqueness annotation) {
        message = annotation.message();
    }

    @Override
    public boolean isValid(final InternalRepository value, ConstraintValidatorContext context) {
        if (value == null || repositoryService == null || securityService == null) {
            return true;
        }
        if (value.getProject() == null || value.getSlug() == null) {
            return false;
        }

        Repository found = securityService.withPermission(Permission.REPO_READ, "validate repository uniqueness")
                .call(() -> repositoryService.getBySlug(value.getProject().getKey(), value.getSlug()));
        if (found == null || found.getId() == value.getId()) {
            return true;
        }

        context.disableDefaultConstraintViolation();

        ConstraintValidatorContext.ConstraintViolationBuilder builder =
                context.buildConstraintViolationWithTemplate(formatMessage(found));
        builder.addNode("name");
        builder.addConstraintViolation();

        return false;
    }

    @Autowired
    public void setI18nService(I18nService i18nService) {
        this.i18nService = i18nService;
    }

    @Autowired
    public void setRepositoryService(RepositoryService repositoryService) {
        this.repositoryService = repositoryService;
    }

    @Autowired
    public void setSecurityService(SecurityService securityService) {
        this.securityService = securityService;
    }

    private String formatMessage(Repository found) {
        return i18nService.getMessage(message, found.getName(), found.getProject().getName());
    }
}
