/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.sling.servlets.resolver.internal.defaults;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;

import javax.json.Json;
import javax.json.stream.JsonGenerator;
import javax.servlet.GenericServlet;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.sling.api.SlingConstants;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.request.header.MediaRangeList;
import org.apache.sling.api.request.RequestProgressTracker;
import org.apache.sling.api.request.ResponseUtil;
import org.osgi.framework.Constants;
import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The <code>DefaultErrorHandlerServlet</code>
 *
 * This is the default error handler servlet registered at the end of the
 * global search path
 */
@SuppressWarnings("serial")
@Component(service = Servlet.class,
    property = {
            Constants.SERVICE_VENDOR + "=The Apache Software Foundation",
            "sling.servlet.paths=sling/servlet/errorhandler/default",
            "sling.servlet.prefix=-1"
    })
public class DefaultErrorHandlerServlet extends GenericServlet {
    private static final String JSON_CONTENT_TYPE = "application/json";
    private static final String HTML_CONTENT_TYPE = "text/html";

    /** default log */
    private final transient Logger log = LoggerFactory.getLogger(DefaultErrorHandlerServlet.class);

    @Override
    public void service(ServletRequest req, ServletResponse res)
            throws IOException {

        // get settings
        Integer scObject = (Integer) req.getAttribute(SlingConstants.ERROR_STATUS);
        String statusMessage = (String) req.getAttribute(SlingConstants.ERROR_MESSAGE);
        String requestUri = (String) req.getAttribute(SlingConstants.ERROR_REQUEST_URI);
        String servletName = (String) req.getAttribute(SlingConstants.ERROR_SERVLET_NAME);

        // ensure values
        int statusCode = (scObject != null)
                ? scObject.intValue()
                : HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
        if (statusMessage == null) {
            statusMessage = statusToString(statusCode);
        }

        //properly consider the 'Accept' header conditions to decide whether to send json or html back
        if (req instanceof HttpServletRequest &&
                JSON_CONTENT_TYPE.equals(new MediaRangeList((HttpServletRequest)req).prefer(HTML_CONTENT_TYPE, JSON_CONTENT_TYPE))) {
            renderJson(req, res, statusMessage, requestUri, servletName, statusCode);
        } else {
            //default to HTML rendering
            renderHtml(req, res, statusMessage, requestUri, servletName, statusCode);
        }
    }

    /**
     * Render the error as html
     */
    protected void renderHtml(ServletRequest req, ServletResponse res, String statusMessage, String requestUri,
            String servletName, int statusCode) throws IOException {
        // start the response message
        final PrintWriter pw = sendIntro((HttpServletResponse) res, statusCode,
            statusMessage, requestUri, servletName);

        // write the exception message
        final PrintWriter escapingWriter = new PrintWriter(
            ResponseUtil.getXmlEscapingWriter(pw));

        // dump the stack trace
        if (req.getAttribute(SlingConstants.ERROR_EXCEPTION) instanceof Throwable) {
            final Throwable throwable = (Throwable) req.getAttribute(SlingConstants.ERROR_EXCEPTION);
            pw.println("<h3>Exception:</h3>");
            pw.println("<pre>");
            pw.flush();
            printStackTrace(escapingWriter, throwable);
            escapingWriter.flush();
            pw.println("</pre>");
        }

        // dump the request progress tracker
        if (req instanceof SlingHttpServletRequest) {
            final RequestProgressTracker tracker = ((SlingHttpServletRequest) req).getRequestProgressTracker();
            pw.println("<h3>Request Progress:</h3>");
            pw.println("<pre>");
            pw.flush();
            tracker.dump(escapingWriter);
            escapingWriter.flush();
            pw.println("</pre>");
        }

        // conclude the response message
        sendEpilogue(pw);
    }

    /**
     * Render the error as json
     */
    protected void renderJson(ServletRequest req, ServletResponse res, String statusMessage, String requestUri,
            String servletName, int statusCode) throws IOException {
        HttpServletResponse response = (HttpServletResponse)res;
        if (!response.isCommitted()) {
            response.reset();
            response.setStatus(statusCode);
            response.setContentType(JSON_CONTENT_TYPE);
            response.setCharacterEncoding("UTF-8");
        } else {
            // Response already committed: don't change status, but report
            // the error inline and warn about that
            log.warn("Response already committed, unable to change status, output might not be well formed");
        }

        // send the error as JSON
        try (JsonGenerator jsonGenerator = Json.createGenerator(res.getWriter())) {
            jsonGenerator.writeStartObject();
            jsonGenerator.write("status", statusCode);

            String msg = (String)req.getAttribute(SlingConstants.ERROR_MESSAGE);
            if (msg != null && !msg.isEmpty()) {
                jsonGenerator.write("message", statusMessage);
            }

            if (requestUri != null && !requestUri.isEmpty()) {
                jsonGenerator.write("requestUri", requestUri);
            }

            if (servletName != null && !servletName.isEmpty()) {
                jsonGenerator.write("servletName", servletName);
            }

            // SLING-10615 - for backward compatibility check for either a
            // String or Class value
            Object exceptionTypeObj = req.getAttribute(SlingConstants.ERROR_EXCEPTION_TYPE);
            String exceptionType = null;
            if (exceptionTypeObj instanceof String) {
                exceptionType = (String)exceptionTypeObj;
            } else if (exceptionTypeObj instanceof Class) {
                exceptionType = ((Class<?>)exceptionTypeObj).getName();
            }
            if (exceptionType != null && !exceptionType.isEmpty()) {
                jsonGenerator.write("exceptionType", exceptionType);
            }

            // dump the stack trace
            if (req.getAttribute(SlingConstants.ERROR_EXCEPTION) instanceof Throwable) {
                final Throwable throwable = (Throwable) req.getAttribute(SlingConstants.ERROR_EXCEPTION);
                try (StringWriter sw = new StringWriter();
                        PrintWriter pw = new PrintWriter(sw)) {
                    printStackTrace(pw, throwable);
                    jsonGenerator.write("exception", sw.toString());
                }
            }

            // dump the request progress tracker
            if (req instanceof SlingHttpServletRequest) {
                // dump the request progress tracker
                final RequestProgressTracker tracker = ((SlingHttpServletRequest)req).getRequestProgressTracker();
                StringWriter strWriter = new StringWriter();
                try (PrintWriter progressWriter = new PrintWriter(strWriter)) {
                    tracker.dump(progressWriter);
                }
                jsonGenerator.write("requestProgress", strWriter.toString());
            }

            jsonGenerator.writeEnd();
        }
    }

    /**
     * Print the stack trace for the root exception if the throwable is a
     * {@link ServletException}. If this does not contain an exception,
     * the throwable itself is printed.
     */
    private void printStackTrace(PrintWriter pw, Throwable t) {
        // nothing to do, if there is no exception
        if (t == null) {
            return;
        }

        // unpack a servlet exception
        if (t instanceof ServletException) {
            ServletException se = (ServletException) t;
            while (se.getRootCause() != null) {
                t = se.getRootCause();
                if (t instanceof ServletException) {
                    se = (ServletException) t;
                } else {
                    break;
                }
            }
        }

        // dump stack, including causes
        t.printStackTrace(pw);
    }

    /**
     * Sets the response status and content type header and starts the the
     * response HTML text with the header, and an introductory phrase.
     */
    private PrintWriter sendIntro(final HttpServletResponse response,
            final int statusCode,
            final String statusMessageIn,
            final String requestUri,
            final String servletName)
    throws IOException {

        final String statusMessage = ResponseUtil.escapeXml(statusMessageIn);

        // set the status code and content type in the response
        final PrintWriter pw;
        if (!response.isCommitted()) {

            response.reset();
            response.setStatus(statusCode);
            response.setContentType(HTML_CONTENT_TYPE);
            response.setCharacterEncoding("UTF-8");

            pw = response.getWriter();
            pw.println("<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">");
            pw.println("<html>");
            pw.println("<head>");
            pw.print("<title>");
            pw.print(statusCode);
            pw.print(" ");
            pw.print(statusMessage);
            pw.println("</title>");
            pw.println("</head>");
            pw.println("<body>");

        } else {

            // Response already committed: don't change status or write HTML prolog, but report
            // the error inline and warn about that
            log.warn("Response already committed, unable to change status, output might not be well formed");
            pw = response.getWriter();

        }

        pw.print("<h1>");
        pw.print(statusMessage);
        pw.print(" (");
        pw.print(statusCode);
        pw.println(")</h1>");
        pw.print("<p>The requested URL ");
        pw.print(ResponseUtil.escapeXml(requestUri));
        pw.print(" resulted in an error");

        if (servletName != null) {
            pw.print(" in ");
            pw.print(ResponseUtil.escapeXml(servletName));
        }

        pw.println(".</p>");

        return pw;
    }

    /**
     * Ends the response sending with an apache-style server line and closes the
     * body and html tags of the HTML response text.
     */
    private void sendEpilogue(final PrintWriter pw) {
        pw.println("<hr>");
        pw.print("<address>");
        pw.print(ResponseUtil.escapeXml(getServletContext().getServerInfo()));
        pw.println("</address>");
        pw.println("</body>");
        pw.println("</html>");
    }

    public static String statusToString(int statusCode) {
        switch (statusCode) { // NOSONAR
            case 100:
                return "Continue";
            case 101:
                return "Switching Protocols";
            case 102:
                return "Processing (WebDAV)";
            case 200:
                return "OK";
            case 201:
                return "Created";
            case 202:
                return "Accepted";
            case 203:
                return "Non-Authoritative Information";
            case 204:
                return "No Content";
            case 205:
                return "Reset Content";
            case 206:
                return "Partial Content";
            case 207:
                return "Multi-Status (WebDAV)";
            case 300:
                return "Multiple Choices";
            case 301:
                return "Moved Permanently";
            case 302:
                return "Found";
            case 303:
                return "See Other";
            case 304:
                return "Not Modified";
            case 305:
                return "Use Proxy";
            case 307:
                return "Temporary Redirect";
            case 400:
                return "Bad Request";
            case 401:
                return "Unauthorized";
            case 402:
                return "Payment Required";
            case 403:
                return "Forbidden";
            case 404:
                return "Not Found";
            case 405:
                return "Method Not Allowed";
            case 406:
                return "Not Acceptable";
            case 407:
                return "Proxy Authentication Required";
            case 408:
                return "Request Time-out";
            case 409:
                return "Conflict";
            case 410:
                return "Gone";
            case 411:
                return "Length Required";
            case 412:
                return "Precondition Failed";
            case 413:
                return "Request Entity Too Large";
            case 414:
                return "Request-URI Too Large";
            case 415:
                return "Unsupported Media Type";
            case 416:
                return "Requested range not satisfiable";
            case 417:
                return "Expectation Failed";
            case 422:
                return "Unprocessable Entity (WebDAV)";
            case 423:
                return "Locked (WebDAV)";
            case 424:
                return "Failed Dependency (WebDAV)";
            case 500:
                return "Internal Server Error";
            case 501:
                return "Not Implemented";
            case 502:
                return "Bad Gateway";
            case 503:
                return "Service Unavailable";
            case 504:
                return "Gateway Time-out";
            case 505:
                return "HTTP Version not supported";
            case 507:
                return "Insufficient Storage (WebDAV)";
            case 510:
                return "Not Extended";
            default:
                return String.valueOf(statusCode);
        }
    }
}
