/*******************************************************************************
 * Copyright (c) 2014, 2019 Raymond Augé and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     Raymond Augé <raymond.auge@liferay.com> - Bug 436698
 ******************************************************************************/

package org.eclipse.equinox.http.servlet.internal.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collections;
import java.util.List;
import javax.servlet.*;
import javax.servlet.http.*;
import org.eclipse.equinox.http.servlet.internal.context.ContextController;
import org.eclipse.equinox.http.servlet.internal.context.DispatchTargets;
import org.eclipse.equinox.http.servlet.internal.registration.EndpointRegistration;
import org.eclipse.equinox.http.servlet.internal.registration.FilterRegistration;
import org.eclipse.equinox.http.servlet.internal.util.HttpStatus;

/**
 * @author Raymond Augé
 */
public class ResponseStateHandler {

	public ResponseStateHandler(
		HttpServletRequest request, HttpServletResponse response,
		DispatchTargets dispatchTargets) {

		this.request = request;
		this.response = response;
		this.dispatchTargets = dispatchTargets;
	}

	public void processRequest() throws IOException, ServletException {
		List<ServletRequestListener> servletRequestListeners = getServletRequestListener();
		EndpointRegistration<?> endpoint = dispatchTargets.getServletRegistration();
		List<FilterRegistration> filters = dispatchTargets.getMatchingFilterRegistrations();

		endpoint.addReference();

		for (FilterRegistration filterRegistration : filters) {
			filterRegistration.addReference();
		}

		ServletRequestEvent servletRequestEvent = null;

		try {
			if ((dispatchTargets.getDispatcherType() == DispatcherType.REQUEST) && !servletRequestListeners.isEmpty()) {
				servletRequestEvent = new ServletRequestEvent(endpoint.getServletContext(), request);
				for (ServletRequestListener servletRequestListener : servletRequestListeners) {
					servletRequestListener.requestInitialized(servletRequestEvent);
				}
			}

			if (endpoint.getServletContextHelper().handleSecurity(request, response)) {
				try {
					if (filters.isEmpty()) {
						endpoint.service(request, response);
					}
					else {
						Collections.sort(filters);

						FilterChain chain = new FilterChainImpl(
							filters, endpoint, dispatchTargets.getDispatcherType());

						chain.doFilter(request, response);
					}
				}
				finally {
					endpoint.getServletContextHelper().finishSecurity(request, response);
				}
			}
		}
		catch (Exception e) {
			if (!(e instanceof IOException) &&
				!(e instanceof RuntimeException) &&
				!(e instanceof ServletException)) {

				e = new ServletException(e);
			}

			setException(e);

			if (dispatchTargets.getDispatcherType() != DispatcherType.ERROR &&
				dispatchTargets.getDispatcherType() != DispatcherType.REQUEST) {

				throwException(e);
			}
		}
		finally {
			endpoint.removeReference();

			for (FilterRegistration filterRegistration : filters) {
				filterRegistration.removeReference();
			}

			if ((exception != null) && dispatchTargets.getDispatcherType() == DispatcherType.ERROR) {
				// This was the error handler throwing an error.
				// We have to handle this with a custom error page of our own.

				PrintWriter writer = response.getWriter();

				Integer status = (Integer)request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
				String message = (String)request.getAttribute(RequestDispatcher.ERROR_MESSAGE);

				if (message == null) {
					message = exception.getMessage();
				}

				request.getServletContext().log(message, exception);

				final HttpStatus httpStatus = HttpStatus.of(status);

				writer.println("<!DOCTYPE html>"); //$NON-NLS-1$
				writer.println("<html lang=\"en\"><head>"); //$NON-NLS-1$
				writer.println("<meta charset=\"utf-8\" />"); //$NON-NLS-1$
				writer.println("<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />"); //$NON-NLS-1$
				writer.println("<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />"); //$NON-NLS-1$
				writer.print("<title>"); //$NON-NLS-1$
				writer.print(httpStatus.value());
				writer.print(" - "); //$NON-NLS-1$
				writer.print(httpStatus.description());
				writer.println("</title></head>"); //$NON-NLS-1$
				writer.print("<body><div><h1>"); //$NON-NLS-1$
				writer.print(httpStatus.value());
				writer.print(" <small>"); //$NON-NLS-1$
				writer.print(httpStatus.description());
				writer.println("</small></h1>"); //$NON-NLS-1$
				writer.print("<p>"); //$NON-NLS-1$
				writer.print(message);
				writer.println("</p></div></body></html>"); //$NON-NLS-1$
			}

			if (dispatchTargets.getDispatcherType() == DispatcherType.FORWARD) {
				response.flushBuffer();

				HttpServletResponseWrapperImpl responseWrapper = HttpServletResponseWrapperImpl.findHttpRuntimeResponse(response);

				if (responseWrapper != null) {
					responseWrapper.setCompleted(true);
				}
				else {
					try (PrintWriter writer = response.getWriter()) {
						// just force a close
					}
					catch (IllegalStateException ise1) {
						try (ServletOutputStream outputStream = response.getOutputStream()) {
							// just force a close
						}
						catch (IllegalStateException | IOException ise2) {
							// ignore
						}
					}
					catch (IOException ioe) {
						// ignore
					}
				}
			}

			if (dispatchTargets.getDispatcherType() == DispatcherType.REQUEST) {
				handleErrors();

				for (ServletRequestListener servletRequestListener : servletRequestListeners) {
					servletRequestListener.requestDestroyed(servletRequestEvent);
				}
			}
		}
	}

	public void setException(Exception exception) {
		this.exception = exception;
	}

	private List<ServletRequestListener> getServletRequestListener() {
		return dispatchTargets.getContextController().getEventListeners().get(ServletRequestListener.class);
	}

	private void handleErrors() throws IOException, ServletException {
		if (exception != null) {
			handleException();
		}
		else {
			handleResponseCode();
		}
	}

	private void handleException() throws IOException, ServletException {
		if (!(response instanceof HttpServletResponseWrapper)) {
			throw new IllegalStateException("Response isn't a wrapper"); //$NON-NLS-1$
		}

		HttpServletResponseWrapperImpl responseWrapper = HttpServletResponseWrapperImpl.findHttpRuntimeResponse(response);

		if (responseWrapper == null) {
			throw new IllegalStateException("Can't locate response impl"); //$NON-NLS-1$
		}

		HttpServletResponse wrappedResponse = (HttpServletResponse)responseWrapper.getResponse();

		if (wrappedResponse.isCommitted()) {
			throwException(exception);
		}

		ContextController contextController = dispatchTargets.getContextController();
		Class<?> clazz = exception.getClass();
		final String originalClassName = clazz.getName();
		String className = originalClassName;

		DispatchTargets errorDispatchTargets;

		do {
			errorDispatchTargets = contextController.getDispatchTargets(
				className, null, null, null, null, null, Match.ERROR, null);

			if (errorDispatchTargets != null) {
				break;
			}

			clazz = clazz.getSuperclass();
			className = clazz.getName();
		}
		while (Exception.class.isAssignableFrom(clazz));

		if (errorDispatchTargets == null) {
			throwException(exception);
		}

		HttpServletRequestWrapperImpl httpRuntimeRequest = HttpServletRequestWrapperImpl.findHttpRuntimeRequest(request);

		try {
			errorDispatchTargets.setDispatcherType(DispatcherType.ERROR);

			httpRuntimeRequest.push(errorDispatchTargets);

			HttpServletRequest wrapperRequest = new HttpServletRequestWrapper(request) {

				@Override
				public Object getAttribute(String attributeName) {
					if (getDispatcherType() == DispatcherType.ERROR) {
						if (attributeName.equals(RequestDispatcher.ERROR_EXCEPTION)) {
							return exception;
						} else if (attributeName.equals(RequestDispatcher.ERROR_EXCEPTION_TYPE)) {
							return originalClassName;
						} else if (attributeName.equals(RequestDispatcher.ERROR_MESSAGE)) {
							return exception.getMessage();
						} else if (attributeName.equals(RequestDispatcher.ERROR_REQUEST_URI)) {
							return request.getRequestURI();
						} else if (attributeName.equals(RequestDispatcher.ERROR_SERVLET_NAME)) {
							return dispatchTargets.getServletRegistration().getName();
						} else if (attributeName.equals(RequestDispatcher.ERROR_STATUS_CODE)) {
							return HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
						}
					}
					return super.getAttribute(attributeName);
				}

				@Override
				public DispatcherType getDispatcherType() {
					return DispatcherType.ERROR;
				}

			};

			HttpServletResponseWrapper wrapperResponse =
				new HttpServletResponseWrapperImpl(wrappedResponse);

			ResponseStateHandler responseStateHandler = new ResponseStateHandler(
				wrapperRequest, wrapperResponse, errorDispatchTargets);

			responseStateHandler.processRequest();

			wrappedResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
		}
		finally {
			httpRuntimeRequest.pop();
		}
	}

	private void handleResponseCode() throws IOException, ServletException {
		if (!(response instanceof HttpServletResponseWrapper)) {
			throw new IllegalStateException("Response isn't a wrapper"); //$NON-NLS-1$
		}

		final HttpServletResponseWrapperImpl responseWrapper = HttpServletResponseWrapperImpl.findHttpRuntimeResponse(response);

		if (responseWrapper == null) {
			throw new IllegalStateException("Can't locate response impl"); //$NON-NLS-1$
		}

		final int status = responseWrapper.getStatus();

		if (status < HttpServletResponse.SC_BAD_REQUEST) {
			return;
		}

		if (status == -1) {
			// There's nothing more we can do here.
			return;
		}

		HttpServletResponse wrappedResponse = (HttpServletResponse)responseWrapper.getResponse();

		if (wrappedResponse.isCommitted()) {
			// the response is committed already, but we need to propagate the error code anyway
			wrappedResponse.sendError(status, responseWrapper.getMessage());
			// There's nothing more we can do here.
			return;
		}

		ContextController contextController = dispatchTargets.getContextController();

		DispatchTargets errorDispatchTargets = contextController.getDispatchTargets(
			String.valueOf(status), null, null, null, null, null, Match.ERROR, null);

		if (errorDispatchTargets == null) {
			wrappedResponse.sendError(status, responseWrapper.getMessage());

			return;
		}

		HttpServletRequestWrapperImpl httpRuntimeRequest = HttpServletRequestWrapperImpl.findHttpRuntimeRequest(request);

		try {
			errorDispatchTargets.setDispatcherType(DispatcherType.ERROR);

			httpRuntimeRequest.push(errorDispatchTargets);

			HttpServletRequest wrapperRequest = new HttpServletRequestWrapper(request) {

				@Override
				public Object getAttribute(String attributeName) {
					if (getDispatcherType() == DispatcherType.ERROR) {
						if (attributeName.equals(RequestDispatcher.ERROR_MESSAGE)) {
							return responseWrapper.getMessage();
						} else if (attributeName.equals(RequestDispatcher.ERROR_REQUEST_URI)) {
							return request.getRequestURI();
						} else if (attributeName.equals(RequestDispatcher.ERROR_SERVLET_NAME)) {
							return dispatchTargets.getServletRegistration().getName();
						} else if (attributeName.equals(RequestDispatcher.ERROR_STATUS_CODE)) {
							return status;
						}
					}
					return super.getAttribute(attributeName);
				}

				@Override
				public DispatcherType getDispatcherType() {
					return DispatcherType.ERROR;
				}

			};

			HttpServletResponseWrapper wrapperResponse =
				new HttpServletResponseWrapperImpl(wrappedResponse);

			ResponseStateHandler responseStateHandler = new ResponseStateHandler(
				wrapperRequest, wrapperResponse, errorDispatchTargets);

			wrappedResponse.setStatus(status);

			responseStateHandler.processRequest();
		}
		finally {
			httpRuntimeRequest.pop();
		}
	}

	private void throwException(Exception e)
		throws IOException, ServletException {

		if (e instanceof RuntimeException) {
			throw (RuntimeException)e;
		}
		else if (e instanceof IOException) {
			throw (IOException)e;
		}
		else if (e instanceof ServletException) {
			throw (ServletException)e;
		}
	}

	DispatchTargets dispatchTargets;
	Exception exception;
	HttpServletRequest request;
	HttpServletResponse response;

}
