package com.atlassian.bitbucket.internal.mirroring.upstream.web;

import com.atlassian.bitbucket.internal.mirroring.rest.RestMirroringRequest;
import com.atlassian.bitbucket.internal.mirroring.upstream.SmartMirroringFeature;
import com.atlassian.bitbucket.internal.mirroring.upstream.rest.RestMirrorServer;
import com.atlassian.bitbucket.internal.mirroring.MirroringRequest;
import com.atlassian.bitbucket.mirroring.upstream.MirrorServer;
import com.atlassian.bitbucket.mirroring.upstream.MirrorService;
import com.atlassian.bitbucket.internal.mirroring.upstream.MirroringRequestSearchRequest;
import com.atlassian.bitbucket.internal.mirroring.upstream.MirroringRequestService;
import com.atlassian.bitbucket.util.Page;
import com.atlassian.bitbucket.util.PageRequest;
import com.atlassian.bitbucket.util.PageUtils;
import com.atlassian.soy.renderer.SoyException;
import com.atlassian.soy.renderer.SoyTemplateRenderer;
import com.google.common.collect.ImmutableMap;

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.bitbucket.internal.mirroring.upstream.web.MirrorWebConstants.TEMPLATE_MODULE_KEY;
import static com.atlassian.bitbucket.internal.mirroring.MirroringRequestState.PENDING;
import static com.google.common.base.Throwables.getRootCause;
import static com.google.common.base.Throwables.propagateIfInstanceOf;

public class MirrorsAdminServlet extends HttpServlet {

    private final SmartMirroringFeature mirroringFeature;
    private final MirrorService mirrorService;
    private final MirroringRequestService mirroringRequestService;
    private final SoyTemplateRenderer soyTemplateRenderer;

    public MirrorsAdminServlet(SmartMirroringFeature mirroringFeature, MirrorService mirrorService,
                               MirroringRequestService mirroringRequestService,
                               SoyTemplateRenderer soyTemplateRenderer) {

        this.mirroringFeature = mirroringFeature;
        this.mirrorService = mirrorService;
        this.mirroringRequestService = mirroringRequestService;
        this.soyTemplateRenderer = soyTemplateRenderer;
    }

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

        boolean available = mirroringFeature.isAvailable();
        ImmutableMap.Builder<String, Object> builder = ImmutableMap.builder();
        PageRequest request = PageUtils.newRequest(0, PageRequest.MAX_PAGE_LIMIT);
        if (available) {
            Page<MirroringRequest> pendingRequests = mirroringRequestService.findAll(
                    new MirroringRequestSearchRequest.Builder().state(PENDING).build(), request);
            Page<MirrorServer> mirrors = mirrorService.findAll(request);

            builder.put("mirrorRequests", pendingRequests.transform(RestMirroringRequest::new));
            builder.put("mirrors", mirrors.transform(RestMirrorServer::new));
        } else {
            // This is needed to make the soy happy.
            builder.put("mirrorRequests", PageUtils.createEmptyPage(request));
            builder.put("mirrors", PageUtils.createEmptyPage(request));
        }
        builder.put("available", available);

        render(resp, "bitbucket.admin.mirroringPage", builder.build());
    }

    private void render(HttpServletResponse resp, String templateName, Map<String, Object> data) throws IOException, ServletException {
        resp.setContentType("text/html;charset=UTF-8");
        try {
            soyTemplateRenderer.render(resp.getWriter(), TEMPLATE_MODULE_KEY, templateName, data);
        } catch (SoyException e) {
            propagateIfInstanceOf(getRootCause(e), IOException.class);
            throw new ServletException(e);
        }
    }
}
