package com.atlassian.stash.internal.repository.sync.web;

import com.atlassian.soy.renderer.SoyException;
import com.atlassian.soy.renderer.SoyTemplateRenderer;
import com.atlassian.stash.internal.repository.sync.DefaultRefSyncService;
import com.atlassian.stash.internal.repository.sync.InternalRefSyncService;
import com.atlassian.bitbucket.repository.Repository;
import com.atlassian.bitbucket.repository.RepositoryService;
import com.atlassian.bitbucket.repository.sync.RefSyncStatus;
import com.atlassian.bitbucket.permission.Permission;
import com.atlassian.bitbucket.permission.PermissionValidationService;
import com.google.common.base.Strings;
import com.google.common.collect.Maps;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;

import static com.atlassian.stash.internal.repository.sync.ui.RefSyncResources.RESOURCE_KEY;
import static com.atlassian.stash.internal.repository.sync.ui.RefSyncResources.TEMPLATE_SETTINGS;

/**
 * @since 2.6
 */
public class RefSyncServlet extends HttpServlet {

    private final RepositoryService repositoryService;
    private final SoyTemplateRenderer soyTemplateRenderer;
    private final InternalRefSyncService syncService;
    private final PermissionValidationService validationService;

    public RefSyncServlet(RepositoryService repositoryService, SoyTemplateRenderer soyTemplateRenderer,
                          InternalRefSyncService syncService, PermissionValidationService validationService) {
        this.repositoryService = repositoryService;
        this.soyTemplateRenderer = soyTemplateRenderer;
        this.syncService = syncService;
        this.validationService = validationService;
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String pathInfo = req.getPathInfo();
        if (Strings.isNullOrEmpty(pathInfo) || pathInfo.equals("/")) {
            resp.sendError(HttpServletResponse.SC_NOT_FOUND);
            return;
        }

        String[] pathParts = pathInfo.substring(1).split("/");
        if (pathParts.length != 2) {
            resp.sendError(HttpServletResponse.SC_NOT_FOUND);
            return;
        }

        Repository repository = repositoryService.getBySlug(pathParts[0], pathParts[1]);
        if (repository == null) {
            resp.sendError(HttpServletResponse.SC_NOT_FOUND);
            return;
        }
        validationService.validateForRepository(repository, Permission.REPO_ADMIN);

        Map<String, Object> context = Maps.newHashMap();
        context.put("repository", repository);
        context.put("upstream", repository.getOrigin());
        context.put("owner", repository.getProject().accept(DefaultRefSyncService.TO_OWNER));

        RefSyncStatus status = syncService.getStatus(repository);
        if (status == null) {
            context.put("syncingAvailable", syncService.isAvailable(repository));
        } else {
            context.put("syncingAvailable", status.isAvailable());
            context.put("syncStatus", status);
        }

        render(resp, RESOURCE_KEY, TEMPLATE_SETTINGS, context);
    }

    private void render(HttpServletResponse resp, String resourceKey, String template, Map<String, Object> context)
            throws IOException, ServletException {
        resp.setContentType("text/html;charset=UTF-8");

        try {
            soyTemplateRenderer.render(resp.getWriter(), resourceKey, template, context);
        } catch (SoyException e) {
            Throwable cause = e.getCause();
            if (cause instanceof IOException) {
                throw (IOException) cause;
            }
            throw new ServletException(e);
        }
    }
}
