// ***************************************************************************************************************************
// * 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.juneau.rest;

import static javax.servlet.http.HttpServletResponse.*;
import static org.apache.juneau.internal.IOUtils.*;
import static org.apache.juneau.internal.StringUtils.*;
import static org.apache.juneau.rest.Enablement.*;

import java.io.*;
import java.util.*;

import javax.servlet.*;
import javax.servlet.http.*;

import org.apache.juneau.http.StreamResource;
import org.apache.juneau.rest.RestContext.*;
import org.apache.juneau.rest.exception.*;
import org.apache.juneau.rest.util.*;

/**
 * Default implementation of {@link RestCallHandler}.
 *
 * <p>
 * Subclasses can override these methods to tailor how HTTP REST calls are handled.
 * <br>Subclasses MUST implement a public constructor that takes in a {@link RestContext} object.
 *
 * <ul class='seealso'>
 * 	<li class='jf'>{@link RestContext#REST_callHandler}
 * </ul>
 */
public class BasicRestCallHandler implements RestCallHandler {

	private final RestContext context;
	private final Map<String,RestCallRouter> restCallRouters;

	/**
	 * Constructor.
	 *
	 * @param context The resource context.
	 */
	public BasicRestCallHandler(RestContext context) {
		this.context = context;
		this.restCallRouters = context.getCallRouters();
	}

	@Override /* RestCallHandler */
	public RestCall createCall(HttpServletRequest req, HttpServletResponse res) {
		return new RestCall(req, res).logger(context.getCallLogger()).loggerConfig(context.getCallLoggerConfig());
	}

	@Override /* RestCallHandler */
	public RestRequest createRequest(RestCall call) throws ServletException {
		return new RestRequest(context, call.getRequest());
	}

	@Override /* RestCallHandler */
	public RestResponse createResponse(RestCall call) throws ServletException {
		return new RestResponse(context, call.getRestRequest(), call.getResponse());
	}

	/**
	 * The main service method.
	 *
	 * <p>
	 * Subclasses can optionally override this method if they want to tailor the behavior of requests.
	 *
	 * @param r1 The incoming HTTP servlet request object.
	 * @param r2 The incoming HTTP servlet response object.
	 * @throws ServletException General servlet exception.
	 * @throws IOException Thrown by underlying stream.
	 */
	@Override /* RestCallHandler */
	public void service(HttpServletRequest r1, HttpServletResponse r2) throws ServletException, IOException {

		RestCall call = createCall(r1, r2);

		try {
			context.checkForInitException();

			// If the resource path contains variables (e.g. @RestResource(path="/f/{a}/{b}"), then we want to resolve
			// those variables and push the servletPath to include the resolved variables.  The new pathInfo will be
			// the remainder after the new servletPath.
			// Only do this for the top-level resource because the logic for child resources are processed next.
			if (context.pathPattern.hasVars() && context.getParentContext() == null) {
				String sp = call.getServletPath();
				String pi = call.getPathInfoUndecoded();
				UrlPathInfo upi2 = new UrlPathInfo(pi == null ? sp : sp + pi);
				UrlPathPatternMatch uppm = context.pathPattern.match(upi2);
				if (uppm != null && ! uppm.hasEmptyVars()) {
					RequestPath.addPathVars(call.getRequest(), uppm.getVars());
					call.request(
						new OverrideableHttpServletRequest(call.getRequest())
							.pathInfo(nullIfEmpty(urlDecode(uppm.getSuffix())))
							.servletPath(uppm.getPrefix())
					);
				} else {
					call.debug(isDebug(call)).status(SC_NOT_FOUND).finish();
					return;
				}
			}

			// If this resource has child resources, try to recursively call them.
			String pi = call.getPathInfoUndecoded();
			if (context.hasChildResources() && pi != null && ! pi.equals("/")) {
				for (RestContext rc : context.getChildResources().values()) {
					UrlPathPattern upp = rc.pathPattern;
					UrlPathPatternMatch uppm = upp.match(call.getUrlPathInfo());
					if (uppm != null) {
						if (! uppm.hasEmptyVars()) {
							RequestPath.addPathVars(call.getRequest(), uppm.getVars());
							HttpServletRequest childRequest = new OverrideableHttpServletRequest(call.getRequest())
								.pathInfo(nullIfEmpty(urlDecode(uppm.getSuffix())))
								.servletPath(call.getServletPath() + uppm.getPrefix());
							rc.getCallHandler().service(childRequest, call.getResponse());
						} else {
							call.debug(isDebug(call)).status(SC_NOT_FOUND).finish();
						}
						return;
					}
				}
			}

			call.debug(isDebug(call));

			context.startCall(call);

			call.restRequest(createRequest(call));
			call.restResponse(createResponse(call));

			context.setRequest(call.getRestRequest());
			context.setResponse(call.getRestResponse());

			StreamResource r = null;
			if (call.getPathInfoUndecoded() != null) {
				String p = call.getPathInfoUndecoded().substring(1);
				if (context.isStaticFile(p)) {
					StaticFile sf = context.resolveStaticFile(p);
					r = sf.resource;
					call.responseMeta(sf.meta);
				} else if (p.equals("favicon.ico")) {
					call.output(null);
				}
			}

			if (r != null) {
				call.status(SC_OK);
				call.output(r);
			} else {

				// If the specified method has been defined in a subclass, invoke it.
				int rc = 0;
				String m = call.getMethod();
				if (restCallRouters.containsKey(m)) {
					rc = restCallRouters.get(m).invoke(call);
				} else if (restCallRouters.containsKey("*")) {
					rc = restCallRouters.get("*").invoke(call);
				}

				// Should be 405 if the URL pattern matched but HTTP method did not.
				if (rc == 0)
					for (RestCallRouter rcc : restCallRouters.values())
						if (rcc.matches(call))
							rc = SC_METHOD_NOT_ALLOWED;

				// Should be 404 if URL pattern didn't match.
				if (rc == 0)
					rc = SC_NOT_FOUND;

				// If not invoked above, see if it's an OPTIONs request
				if (rc != SC_OK)
					handleNotFound(call.status(rc));

				if (call.getStatus() == 0)
					call.status(rc);
			}

			if (call.hasOutput()) {
				// Now serialize the output if there was any.
				// Some subclasses may write to the OutputStream or Writer directly.
				handleResponse(call);
			}


		} catch (Throwable e) {
			handleError(call, convertThrowable(e));
		} finally {
			context.clearState();
		}

		call.finish();
		context.finishCall(call);
	}

	private boolean isDebug(RestCall call) {
		Enablement e = context.getDebug();
		if (e == TRUE)
			return true;
		if (e == FALSE)
			return false;
		return "true".equalsIgnoreCase(call.getRequest().getHeader("X-Debug"));
	}

	/**
	 * The main method for serializing POJOs passed in through the {@link RestResponse#setOutput(Object)} method or
	 * returned by the Java method.
	 *
	 * <p>
	 * Subclasses may override this method if they wish to modify the way the output is rendered or support other output
	 * formats.
	 *
	 * <p>
	 * The default implementation simply iterates through the response handlers on this resource
	 * looking for the first one whose {@link ResponseHandler#handle(RestRequest,RestResponse)} method returns
	 * <jk>true</jk>.
	 *
	 * @param call The HTTP call.
	 * @throws IOException Thrown by underlying stream.
	 * @throws RestException Non-200 response.
	 */
	@Override /* RestCallHandler */
	public void handleResponse(RestCall call) throws IOException, RestException, NotImplemented {

		RestRequest req = call.getRestRequest();
		RestResponse res = call.getRestResponse();

		// Loop until we find the correct handler for the POJO.
		for (ResponseHandler h : context.getResponseHandlers())
			if (h.handle(req, res))
				return;

		Object output = res.getOutput();
		throw new NotImplemented("No response handlers found to process output of type '"+(output == null ? null : output.getClass().getName())+"'");
	}

	/**
	 * Method that can be subclassed to allow uncaught throwables to be treated as other types of throwables.
	 *
	 * <p>
	 * The default implementation looks at the throwable class name to determine whether it can be converted to another type:
	 *
	 * <ul>
	 * 	<li><js>"*AccessDenied*"</js> - Converted to {@link Unauthorized}.
	 * 	<li><js>"*Empty*"</js>,<js>"*NotFound*"</js> - Converted to {@link NotFound}.
	 * </ul>
	 *
	 * @param t The thrown object.
	 * @return The converted thrown object.
	 */
	@Override
	public Throwable convertThrowable(Throwable t) {
		if (t instanceof RestException)
			return t;
		String n = t.getClass().getName();
		if (n.contains("AccessDenied"))
			return new Unauthorized(t);
		if (n.contains("Empty") || n.contains("NotFound"))
			return new NotFound(t);
		return t;
	}

	/**
	 * Handle the case where a matching method was not found.
	 *
	 * <p>
	 * Subclasses can override this method to provide a 2nd-chance for specifying a response.
	 * The default implementation will simply throw an exception with an appropriate message.
	 *
	 * @param call The HTTP call.
	 */
	@Override /* RestCallHandler */
	public void handleNotFound(RestCall call) throws Exception {
		String pathInfo = call.getPathInfo();
		String methodUC = call.getMethod();
		int rc = call.getStatus();
		String onPath = pathInfo == null ? " on no pathInfo"  : String.format(" on path '%s'", pathInfo);
		if (rc == SC_NOT_FOUND)
			throw new NotFound("Method ''{0}'' not found on resource with matching pattern{1}.", methodUC, onPath);
		else if (rc == SC_PRECONDITION_FAILED)
			throw new PreconditionFailed("Method ''{0}'' not found on resource{1} with matching matcher.", methodUC, onPath);
		else if (rc == SC_METHOD_NOT_ALLOWED)
			throw new MethodNotAllowed("Method ''{0}'' not found on resource.", methodUC);
		else
			throw new ServletException("Invalid method response: " + rc);
	}

	/**
	 * Method for handling response errors.
	 *
	 * <p>
	 * Subclasses can override this method to provide their own custom error response handling.
	 *
	 * @param call The rest call.
	 * @param e The exception that occurred.
	 * @throws IOException Can be thrown if a problem occurred trying to write to the output stream.
	 */
	@Override /* RestCallHandler */
	@SuppressWarnings("deprecation")
	public synchronized void handleError(RestCall call, Throwable e) throws IOException {

		call.exception(e);

		int occurrence = context == null ? 0 : context.getStackTraceOccurrence(e);
		RestException e2 = (e instanceof RestException ? (RestException)e : new RestException(e, 500)).setOccurrence(occurrence);

		HttpServletRequest req = call.getRequest();
		HttpServletResponse res = call.getResponse();

		Throwable t = e2.getRootCause();
		if (t != null) {
			res.setHeader("Exception-Name", t.getClass().getName());
			res.setHeader("Exception-Message", t.getMessage());
		}

		try {
			res.setContentType("text/plain");
			res.setHeader("Content-Encoding", "identity");
			res.setStatus(e2.getStatus());

			PrintWriter w = null;
			try {
				w = res.getWriter();
			} catch (IllegalStateException x) {
				w = new PrintWriter(new OutputStreamWriter(res.getOutputStream(), UTF8));
			}

			try (PrintWriter w2 = w) {
				String httpMessage = RestUtils.getHttpResponseText(e2.getStatus());
				if (httpMessage != null)
					w2.append("HTTP ").append(String.valueOf(e2.getStatus())).append(": ").append(httpMessage).append("\n\n");
				if (context != null && context.isRenderResponseStackTraces())
					e.printStackTrace(w2);
				else
					w2.append(e2.getFullStackMessage(true));
			}

		} catch (Exception e1) {
			req.setAttribute("Exception", e1);
		}
	}

	/**
	 * Returns the session objects for the specified request.
	 *
	 * <p>
	 * The default implementation simply returns a single map containing <c>{'req':req}</c>.
	 *
	 * @param req The REST request.
	 * @return The session objects for that request.
	 */
	@Override /* RestCallHandler */
	public Map<String,Object> getSessionObjects(RestRequest req, RestResponse res) {
		Map<String,Object> m = new HashMap<>();
		m.put("req", req);
		m.put("res", res);
		return m;
	}
}
