package com.atlassian.bitbucket.internal.scm.git.lfs.fragments;

import com.atlassian.bitbucket.internal.scm.git.lfs.GitLfsService;
import com.atlassian.bitbucket.internal.scm.git.lfs.settings.GitLfsSettingsService;
import com.atlassian.bitbucket.repository.Repository;
import com.atlassian.bitbucket.ui.ContextualFormFragment;
import com.atlassian.bitbucket.ui.ValidationErrors;
import com.atlassian.bitbucket.view.TemplateRenderingException;
import com.atlassian.soy.renderer.SoyException;
import com.atlassian.soy.renderer.SoyTemplateRenderer;

import java.io.IOException;
import java.util.Collection;
import java.util.Map;

import static com.atlassian.bitbucket.internal.scm.git.lfs.GitLfsConstants.PLUGIN_KEY;

public class GitLfsRepoSettingsFormFragment implements ContextualFormFragment {

    private static final String MODULE_KEY = PLUGIN_KEY + ":lfs-admin-soy-templates";
    private static final String FRAGMENT_TEMPLATE = "bitbucket.scm.git.lfs.repo.settings.fragment";

    /**
     * Is used to disable the per repo administration if LFS is not enabled on the instance
     */
    private static final String SOY_FIELD_GLOBAL_ENABLED = "lfsGlobalEnabled";

    /**
     * The enabled/disabled checkbox param in the Soy template
     */
    private static final String SOY_FIELD_REPO_ENABLED = "lfsRepoEnabled";

    private final GitLfsService gitLfsService;
    private final GitLfsSettingsService gitLfsSettingsService;
    private final SoyTemplateRenderer soyTemplateRenderer;

    public GitLfsRepoSettingsFormFragment(GitLfsService gitLfsService,
                                          GitLfsSettingsService gitLfsSettingsService,
                                          SoyTemplateRenderer soyTemplateRenderer) {
        this.gitLfsService = gitLfsService;
        this.gitLfsSettingsService = gitLfsSettingsService;
        this.soyTemplateRenderer = soyTemplateRenderer;
    }

    /**
     * Render form
     */
    @Override
    public void doView(Appendable appendable, Map<String, Object> context) throws IOException {
        context.put(SOY_FIELD_GLOBAL_ENABLED, gitLfsSettingsService.isEnabled());
        Repository repository = (Repository) context.get("repository");
        context.put(SOY_FIELD_REPO_ENABLED, gitLfsService.isEnabled(repository));
        renderView(appendable, context);
    }

    /**
     * Validate the fields supplied by this form fragment.
     */
    @Override
    public void validate(Map<String, String[]> requestParams, ValidationErrors errors, Map<String, Object> context) {
    }

    /**
     * Render form after a validation error has occurred.
     */
    @Override
    public void doError(Appendable appendable, Map<String, String[]> requestParams, Map<String,
            Collection<String>> fieldErrors, Map<String, Object> context) throws IOException {
        context.put(SOY_FIELD_GLOBAL_ENABLED, gitLfsSettingsService.isEnabled());
        context.put(SOY_FIELD_REPO_ENABLED, isCheckBoxEnabled(requestParams));
        renderView(appendable, context);
    }

    /**
     * Store the fields supplied by this form and perform any other actions.
     */
    @Override
    public void execute(Map<String, String[]> requestParams, Map<String, Object> context) {
        Repository repository = (Repository) context.get("repository");
        if (isCheckBoxEnabled(requestParams)) {
            gitLfsService.enable(repository);
        } else {
            gitLfsService.disable(repository);
        }
    }

    /**
     * Render form helper
     */
    private void renderView(Appendable appendable, Map<String, Object> context) {
        try {
            soyTemplateRenderer.render(appendable, MODULE_KEY, FRAGMENT_TEMPLATE, context);
        } catch (SoyException e) {
            throw new TemplateRenderingException("Failed to render " + FRAGMENT_TEMPLATE, e);
        }
    }

    /**
     * Gets the status of the "lfsEnabled" checkbox
     */
    private static boolean isCheckBoxEnabled(Map<String, String[]> requestParams) {
        String[] values = requestParams.get(SOY_FIELD_REPO_ENABLED);
        return values != null && values[0].equalsIgnoreCase("on");
    }
}
