package com.atlassian.stash.internal.plugin.hooks.approvers;

import com.atlassian.bitbucket.i18n.I18nService;
import com.atlassian.bitbucket.repository.Repository;
import com.atlassian.bitbucket.rest.RestErrorMessage;
import com.atlassian.bitbucket.rest.fragment.RestFragment;
import com.atlassian.bitbucket.rest.fragment.RestFragmentContext;
import com.google.common.collect.ImmutableMap;

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

import static com.atlassian.stash.internal.plugin.hooks.approvers.RequiredApproversHelper.MAX_APPROVERS;

public class RequiredApproversRestFragment implements RestFragment {

    private static final String REQUIRED_APPROVERS_KEY = "requiredApprovers";

    private final RequiredApproversHelper helper;
    private final I18nService i18nService;

    public RequiredApproversRestFragment(RequiredApproversHelper helper, I18nService i18nService) {
        this.helper = helper;
        this.i18nService = i18nService;
    }

    @Nonnull
    @Override
    public Map<String, Object> execute(@Nonnull RestFragmentContext fragmentContext,
                                       @Nonnull Map<String, Object> requestContext) {
        Repository repository = (Repository) requestContext.get("repository");

        if (fragmentContext.getMethod().equals("GET")) {
            return doGet(repository);
        } else if (fragmentContext.getMethod().equals("POST")) {
            return doPost(fragmentContext, repository);
        }

        return ImmutableMap.of(REQUIRED_APPROVERS_KEY, i18nService.getMessage("bitbucket.requiredApprovers.rest.method.unsupported",
                fragmentContext.getMethod()));
    }

    @Nonnull
    @Override
    public Map<String, Object> validate(@Nonnull RestFragmentContext fragmentContext,
                                        @Nonnull Map<String, Object> requestContext) {
        if (fragmentContext.getMethod().equals("POST")) {
            Optional<Object> property = fragmentContext.getBodyProperty(REQUIRED_APPROVERS_KEY);

            if (property.isPresent()) {
                if (property.get() instanceof Number) {
                    int approversCount = ((Number) property.get()).intValue();
                    if (approversCount < 0) {
                        return new RestErrorMessage(REQUIRED_APPROVERS_KEY,
                                i18nService.getMessage("bitbucket.requiredApprovers.count.negativeNumber"));
                    } else if (approversCount > MAX_APPROVERS) {
                        return new RestErrorMessage(REQUIRED_APPROVERS_KEY,
                                i18nService.getMessage("bitbucket.requiredApprovers.count.tooLarge", MAX_APPROVERS));
                    }
                } else {
                    return new RestErrorMessage(REQUIRED_APPROVERS_KEY,
                            i18nService.getMessage("bitbucket.requiredApprovers.count.notANumber"));
                }
            }
        }

        return ImmutableMap.of();
    }

    private Map<String, Object> doGet(Repository repository) {
        return ImmutableMap.of(REQUIRED_APPROVERS_KEY, helper.getRequiredApproversCount(repository));
    }

    private Map<String, Object> doPost(RestFragmentContext fragmentContext, Repository repository) {
        fragmentContext.getBodyProperty(REQUIRED_APPROVERS_KEY).ifPresent(
                n -> helper.saveRequiredApproversCount(repository, ((Number) n).intValue())
        );

        return doGet(repository);
    }
}
