package com.atlassian.stash.internal.build.hook;

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.build.hook.RequiredBuildsHelper.MAX_BUILDS;

public class RequiredBuildsRestFragment implements RestFragment {

    private static final String REQUIRED_BUILDS_KEY = "requiredSuccessfulBuilds";

    private final RequiredBuildsHelper helper;
    private final I18nService i18nService;

    public RequiredBuildsRestFragment(RequiredBuildsHelper 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_BUILDS_KEY, i18nService.getMessage("bitbucket.build.required.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_BUILDS_KEY);

            if (property.isPresent()) {
                if (property.get() instanceof Number) {
                    int buildCount = ((Number) property.get()).intValue();
                    if (buildCount < 0) {
                        return new RestErrorMessage(REQUIRED_BUILDS_KEY,
                                i18nService.getMessage("bitbucket.build.required.count.negativeNumber"));
                    } else if (buildCount > MAX_BUILDS) {
                        return new RestErrorMessage(REQUIRED_BUILDS_KEY,
                                i18nService.getMessage("bitbucket.build.required.count.tooLarge", MAX_BUILDS));
                    }
                } else {
                    return new RestErrorMessage(REQUIRED_BUILDS_KEY,
                            i18nService.getMessage("bitbucket.build.required.count.notANumber"));
                }
            }
        }

        return ImmutableMap.of();
    }

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

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

        return doGet(repository);
    }
}