// Copyright 2011 Google Inc. All Rights Reserved.
//
// Licensed 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 adaptorlib;

import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpsServer;

import java.io.IOException;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.GZIPOutputStream;

abstract class AbstractHandler implements HttpHandler {
  /**
   * Attribute of {@link HttpExchange} that is {@code true} if the HTTP headers
   * have already been sent for the exchange, and unset otherwise.
   */
  public static final String ATTR_HEADERS_SENT
      = AbstractHandler.class.getName() + ".headers-sent";

  private static final Logger log
      = Logger.getLogger(AbstractHandler.class.getName());
  // DateFormats are relatively expensive to create, and cannot be used from
  // multiple threads
  protected static ThreadLocal<DateFormat> dateFormat
      = new ThreadLocal<DateFormat>() {
        @Override
        protected DateFormat initialValue() {
          return new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz");
        }
      };
  /**
   * When thread-local value is not {@code null}, signals that {@link #handle}
   * should abort immediately with an error. This is a hack required because the
   * HttpServer can't handle the Executor rejecting execution of a runnable.
   */
  public static final ThreadLocal<Object> abortImmediately
      = new ThreadLocal<Object>();

  /**
   * The hostname is sometimes needed to generate the correct DocId; in the case
   * that it is needed and the host is an old HTTP/1.0 client, this value will
   * be used.
   */
  protected final String fallbackHostname;
  /**
   * Default encoding to encode simple response messages.
   */
  protected final Charset defaultEncoding;

  /**
   * @param fallbackHostname Fallback hostname in case we talk to an old HTTP
   *    client
   * @param defaultEncoding Encoding to use when sending simple text responses
   */
  protected AbstractHandler(String fallbackHostname, Charset defaultEncoding) {
    this.fallbackHostname = fallbackHostname;
    this.defaultEncoding = defaultEncoding;
  }

  protected String getLoggableRequestHeaders(HttpExchange ex) {
    StringBuilder sb = new StringBuilder();
    for (Map.Entry<String, List<String>> me
         : ex.getRequestHeaders().entrySet()) {
      for (String value : me.getValue()) {
        sb.append(me.getKey());
        sb.append(": ");
        sb.append(value);
        sb.append(", ");
      }
    }
    // Cut off trailing ", "
    return sb.substring(0, sb.length() - 2);
  }

  protected void logRequest(HttpExchange ex) {
    if (log.isLoggable(Level.FINER)) {
      log.log(Level.FINER, "Received {1} request to {0}. Headers: '{'{2}'}'",
              new Object[] {ex.getRequestURI(), ex.getRequestMethod(),
                            getLoggableRequestHeaders(ex)});
    }
  }

  /**
   * Best-effort attempt to reform the identical URI the client used to
   * contact the server.
   */
  protected URI getRequestUri(HttpExchange ex) {
    String host = ex.getRequestHeaders().getFirst("Host");
    if (host == null) {
      // Client must be using HTTP/1.0
      host = fallbackHostname;
    }
    String protocol = (ex.getHttpContext().getServer() instanceof HttpsServer)
        ? "https" : "http";
    URI base;
    try {
      base = new URI(protocol, host, "/", null, null);
    } catch (URISyntaxException e) {
      throw new IllegalStateException(e);
    }
    URI requestedUri = ex.getRequestURI();
    // If uri is already absolute (e.g., a proxy is involved), then this
    // does nothing, otherwise it resolves the URI for us based on who we
    // think we are
    requestedUri = base.resolve(requestedUri);
    log.log(Level.FINER, "Resolved original URI to: {0}", requestedUri);
    return requestedUri;
  }

  /**
   * Sends response to GSA. Should only be used when the request method is
   * HEAD.
   */
  protected void respondToHead(HttpExchange ex, int code, String contentType)
      throws IOException {
    ex.getResponseHeaders().set("Transfer-Encoding", "chunked");
    respond(ex, code, contentType, (byte[]) null);
  }

  /**
   * Sends cheaply-generated response message to GSA. This is intended for use
   * with pre-build, canned messages. It automatically handles not sending the
   * actual content when the request method is HEAD. If the content requires
   * a moderate amount of work to produce, then you should manually call
   * {@link #respond} or {@link #respondToHead} depending on the situation.
   */
  protected void cannedRespond(HttpExchange ex, int code, Translation response)
      throws IOException {
    // TODO(ejona): use exchange to decide on response language
    cannedRespond(ex, code, "text/plain", response.toString());
  }

  /**
   * Sends cheaply-generated response message to GSA. This is intended for use
   * with pre-build, canned messages. It automatically handles not sending the
   * actual content when the request method is HEAD. If the content requires
   * a moderate amount of work to produce, then you should manually call
   * {@link #respond} or {@link #respondToHead} depending on the situation.
   */
  protected void cannedRespond(HttpExchange ex, int code, Translation response,
                               Object... params) throws IOException {
    // TODO(ejona): use exchange to decide on response language
    cannedRespond(ex, code, "text/plain", response.toString(params));
  }

  private void cannedRespond(HttpExchange ex, int code, String contentType,
                             String response) throws IOException {
    if ("HEAD".equals(ex.getRequestMethod())) {
      respondToHead(ex, code, contentType);
    } else {
      respond(ex, code, contentType, response.getBytes(defaultEncoding));
    }
  }

  /**
   * Sends headers and configures {@code ex} for (possibly) sending content.
   * Completing the request is the caller's responsibility.
   */
  protected void startResponse(HttpExchange ex, int code, String contentType,
                               boolean hasBody) throws IOException {
    log.finest("Starting response");
    if (contentType != null) {
      ex.getResponseHeaders().set("Content-Type", contentType);
    }
    ex.setAttribute(ATTR_HEADERS_SENT, true);
    if (!hasBody) {
      // No body. Required for HEAD requests
      ex.sendResponseHeaders(code, -1);
    } else {
      // Chuncked encoding
      ex.sendResponseHeaders(code, 0);
      // Check to see if enableCompressionIfSupported was called
      if ("gzip".equals(ex.getResponseHeaders().getFirst("Content-Encoding"))) {
        // Creating the GZIPOutputStream must happen after sendResponseHeaders
        // since the constructor writes data to the provided OutputStream
        ex.setStreams(null, new GZIPOutputStream(ex.getResponseBody()));
      }
    }
  }

  /**
   * Sends response to GSA. Should not be used directly if the request method
   * is HEAD.
   */
  protected void respond(HttpExchange ex, int code, String contentType,
                         byte response[]) throws IOException {
    startResponse(ex, code, contentType, response != null);
    if (response != null) {
      OutputStream responseBody = ex.getResponseBody();
      log.finest("before writing response");
      responseBody.write(response);
      responseBody.flush();
      // This shouldn't be needed, but without it one developer had trouble
      responseBody.close();
      log.finest("after writing response");
    }
    ex.close();
    log.finest("after closing exchange");
  }

  /**
   * Redirect client to {@code location}. The client should retrieve the
   * referred location via GET, independent of the method of this request.
   */
  public void sendRedirect(HttpExchange ex, URI location)
      throws IOException {
    ex.getResponseHeaders().set("Location", location.toString());
    respond(ex, HttpURLConnection.HTTP_SEE_OTHER, null, null);
  }

  /**
   * If the client supports it, set the correct headers and make {@link
   * #respond} provide GZIPed response data to the client.
   */
  protected void enableCompressionIfSupported(HttpExchange ex)
      throws IOException {
    String encodingList = ex.getRequestHeaders().getFirst("Accept-Encoding");
    if (encodingList == null) {
      return;
    }
    Collection<String> encodings = Arrays.asList(encodingList.split(","));
    if (encodings.contains("gzip")) {
      log.finer("Enabling gzip compression for response");
      ex.getResponseHeaders().set("Content-Encoding", "gzip");
    }
  }

  /**
   * Retrieves and parses the If-Modified-Since from the request, returning null
   * if there was no such header or there was an error.
   */
  protected static Date getIfModifiedSince(HttpExchange ex) {
    String ifModifiedSince
        = ex.getRequestHeaders().getFirst("If-Modified-Since");
    if (ifModifiedSince == null) {
      return null;
    }
    try {
      return dateFormat.get().parse(ifModifiedSince);
    } catch (java.text.ParseException e) {
      log.log(Level.WARNING, "Exception when parsing ifModifiedSince", e);
      // Ignore and act like it wasn't present
      return null;
    }
  }

  protected void setLastModified(HttpExchange ex, Date lastModified) {
    ex.getResponseHeaders().set("Last-Modified",
                                dateFormat.get().format(lastModified));

  }

  protected abstract void meteredHandle(HttpExchange ex) throws IOException;

  /**
   * Performs entry logging, calls {@link #meteredHandle}, and performs exit
   * logging. Also logs and handles exceptions.
   */
  public void handle(HttpExchange ex) throws IOException {
    // Checking abortImmediately is part of a hack to immediately reject clients
    // when the work queue grows too long.
    if (abortImmediately.get() != null) {
      throw new IOException("Too many clients");
    }
    try {
      log.fine("beginning");
      logRequest(ex);
      log.log(Level.FINE, "Processing request with {0}",
              this.getClass().getName());
      ex.getResponseHeaders().set("Date", dateFormat.get().format(new Date()));
      meteredHandle(ex);
    } catch (Exception e) {
      Boolean headersSent = (Boolean) ex.getAttribute(ATTR_HEADERS_SENT);
      if (headersSent == null) {
        headersSent = false;
      }
      log.log(Level.WARNING, "Unexpected exception during request", e);
      if (headersSent) {
        // The headers have already been sent, so all we can do is throw the
        // exception up and allow the server to kill the connection.
        throw new RuntimeException(e);
      } else {
        cannedRespond(ex, HttpURLConnection.HTTP_INTERNAL_ERROR,
                      Translation.HTTP_INTERNAL_ERROR);
      }
    } finally {
      log.fine("ending");
    }
  }
}
