package com.atlassian.stash.internal.web.startup;

import com.atlassian.johnson.spring.lifecycle.LifecycleState;
import com.atlassian.johnson.spring.lifecycle.LifecycleUtils;
import com.atlassian.stash.internal.johnson.JohnsonUtils;
import com.atlassian.stash.internal.lifecycle.StartupManager;
import com.atlassian.stash.internal.lifecycle.StartupUtils;
import com.atlassian.stash.internal.rest.RestProgress;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableMap;
import org.codehaus.jackson.JsonEncoding;
import org.codehaus.jackson.JsonFactory;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.map.MappingJsonFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;

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.net.URI;
import java.net.URLDecoder;

/**
 * @since 3.2
 */
public class StartupServlet extends HttpServlet {

    private static final JsonFactory JSON = new MappingJsonFactory();

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        StartupManager startupManager = getStartupManager();

        if (MediaType.APPLICATION_JSON_VALUE.equals(request.getHeader(HttpHeaders.ACCEPT))) {
            //startup.jsp polls for progress by requesting JSON. To facilitate that usage, even if startup is
            //complete, always return progress information rather than redirecting
            response.setStatus(HttpServletResponse.SC_OK);
            response.setHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE + ";charset=UTF-8");

            try (JsonGenerator jsonGenerator = JSON.createJsonGenerator(response.getOutputStream(), JsonEncoding.UTF8)) {
                jsonGenerator.writeObject(ImmutableMap.of(
                        "progress", new RestProgress(startupManager.getProgress()),
                        "state", getCurrentState()));
            }
        } else if (startupManager.isStarting()) {
            request.getRequestDispatcher("/startup.jsp").forward(request, response);
        } else {
            // We cannot know for sure base URL in startup, so change next to relative URL
            response.sendRedirect(JohnsonUtils.getRedirectUrl(request, request.getContextPath()));
        }
    }

    @VisibleForTesting
    protected LifecycleState getCurrentState() {
        return LifecycleUtils.getCurrentState(getServletContext());
    }

    @VisibleForTesting
    protected StartupManager getStartupManager() {
        return StartupUtils.getStartupManager(getServletContext());
    }

}
