/*
 * Copyright 2011 Google Inc.
 *
 * 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 com.google.gwt.dev.codeserver;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.TreeLogger.Type;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.dev.codeserver.CompileDir.PolicyFile;
import com.google.gwt.dev.codeserver.Pages.ErrorPage;
import com.google.gwt.dev.json.JsonObject;

import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.server.HttpConnection;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.servlets.GzipFilter;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.DispatcherType;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * The web server for Super Dev Mode, also known as the code server. The URLs handled include:
 * <ul>
 *   <li>HTML pages for the front page and module pages</li>
 *   <li>JavaScript that implementing the bookmarklets</li>
 *   <li>The web API for recompiling a GWT app</li>
 *   <li>The output files and log files from the GWT compiler</li>
 *   <li>Java source code (for source-level debugging)</li>
 * </ul>
 *
 * <p>EXPERIMENTAL. There is no authentication, encryption, or XSS protection, so this server is
 * only safe to run on localhost.</p>
 */
// This file was copied from GWT project and adjusted to run against
// Jetty 9.2.2. The original diff can be found here:
// https://gwt-review.googlesource.com/#/c/7857/13/dev/codeserver/java/com/google/gwt/dev/codeserver/WebServer.java
public class WebServer {

  private static final Pattern SAFE_DIRECTORY =
      Pattern.compile("([a-zA-Z0-9_-]+\\.)*[a-zA-Z0-9_-]+"); // no extension needed

  private static final Pattern SAFE_FILENAME =
      Pattern.compile("([a-zA-Z0-9_-]+\\.)+[a-zA-Z0-9_-]+"); // an extension is required

  private static final Pattern SAFE_MODULE_PATH =
      Pattern.compile("/(" + SAFE_DIRECTORY + ")/$");

  static final Pattern SAFE_DIRECTORY_PATH =
      Pattern.compile("/(" + SAFE_DIRECTORY + "/)+$");

  /* visible for testing */
  static final Pattern SAFE_FILE_PATH =
      Pattern.compile("/(" + SAFE_DIRECTORY + "/)+" + SAFE_FILENAME + "$");

  static final Pattern STRONG_NAME = Pattern.compile("[\\dA-F]{32}");

  private static final Pattern CACHE_JS_FILE = Pattern.compile("/(" + STRONG_NAME + ").cache.js$");

  private static final MimeTypes MIME_TYPES = new MimeTypes();

  private static final String TIME_IN_THE_PAST = "Mon, 01 Jan 1990 00:00:00 GMT";

  private final SourceHandler handler;
  private final JsonExporter jsonExporter;
  private final OutboxTable outboxes;
  private final JobRunner runner;
  private final JobEventTable eventTable;

  private final String bindAddress;
  private final int port;

  private Server server;

  WebServer(SourceHandler handler, JsonExporter jsonExporter, OutboxTable outboxes,
      JobRunner runner, JobEventTable eventTable, String bindAddress, int port) {
    this.handler = handler;
    this.jsonExporter = jsonExporter;
    this.outboxes = outboxes;
    this.runner = runner;
    this.eventTable = eventTable;
    this.bindAddress = bindAddress;
    this.port = port;
  }

  @SuppressWarnings("serial")
  void start(final TreeLogger logger) throws UnableToCompleteException {

    Server newServer = new Server();
    ServerConnector connector = new ServerConnector(newServer);
    connector.setHost(bindAddress);
    connector.setPort(port);
    connector.setReuseAddress(false);
    connector.setSoLingerTime(0);

    newServer.addConnector(connector);

    ServletContextHandler newHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);
    newHandler.setContextPath("/");
    newHandler.addServlet(new ServletHolder(new HttpServlet() {
      @Override
      protected void doGet(HttpServletRequest request, HttpServletResponse response)
          throws ServletException, IOException {
        handleRequest(request.getPathInfo(), request, response, logger);
      }
    }), "/*");
    newHandler.addFilter(GzipFilter.class, "/*", EnumSet.allOf(DispatcherType.class));
    newServer.setHandler(newHandler);
    try {
      newServer.start();
    } catch (Exception e) {
      logger.log(TreeLogger.ERROR, "cannot start web server", e);
      throw new UnableToCompleteException();
    }
    this.server = newServer;
  }

  public int getPort() {
    return port;
  }

  public void stop() throws Exception {
    server.stop();
    server = null;
  }

  /**
   * Returns the location of the compiler output. (Changes after every recompile.)
   * @param outputModuleName the module name that the GWT compiler used in its output.
   */
  public File getCurrentWarDir(String outputModuleName) {
    return outboxes.findByOutputModuleName(outputModuleName).getWarDir();
  }

  private void handleRequest(String target, HttpServletRequest request,
      HttpServletResponse response, TreeLogger parentLogger)
      throws IOException {

    if (request.getMethod().equalsIgnoreCase("get")) {

      TreeLogger logger = parentLogger.branch(Type.TRACE, "GET " + target);

      Response page = doGet(target, request, logger);
      if (page == null) {
        logger.log(Type.WARN, "not handled: " + target);
        return;
      }

      setHandled(request);
      if (!target.endsWith(".cache.js")) {
        // Make sure IE9 doesn't cache any pages.
        // (Nearly all pages may change on server restart.)
        response.setHeader("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate");
        response.setHeader("Pragma", "no-cache");
        response.setHeader("Expires", TIME_IN_THE_PAST);
        response.setDateHeader("Date", new Date().getTime());
      }
      page.send(request, response, logger);
    }
  }

  /**
   * Returns the page that should be sent in response to a GET request, or null for no response.
   */
  private Response doGet(String target, HttpServletRequest request, TreeLogger logger)
      throws IOException {

    if (target.equals("/")) {
      JsonObject json = jsonExporter.exportFrontPageVars();
      return Pages.newHtmlPage("config", json, "frontpage.html");
    }

    if (target.equals("/dev_mode_on.js")) {
      JsonObject json = jsonExporter.exportDevModeOnVars();
      return Responses.newJavascriptResponse("__gwt_codeserver_config", json,
          "dev_mode_on.js");
    }

    // Recompile on request from the bookmarklet.
    // This is a GET because a bookmarklet can call it from a different origin (JSONP).
    if (target.startsWith("/recompile/")) {
      String moduleName = target.substring("/recompile/".length());
      Outbox box = outboxes.findByOutputModuleName(moduleName);
      if (box == null) {
        return new ErrorPage("No such module: " + moduleName);
      }

      // We are passing properties from an unauthenticated GET request directly to the compiler.
      // This should be safe, but only because these are binding properties. For each binding
      // property, you can only choose from a set of predefined values. So all an attacker can do is
      // cause a spurious recompile, resulting in an unexpected permutation being loaded later.
      //
      // It would be unsafe to allow a configuration property to be changed.
      Job job = box.makeJob(getBindingProperties(request), logger);
      runner.submit(job);
      Job.Result result = job.waitForResult();
      JsonObject json = jsonExporter.exportRecompileResponse(result);
      return Responses.newJsonResponse(json);
    }

    if (target.startsWith("/log/")) {
      String moduleName = target.substring("/log/".length());
      Outbox box = outboxes.findByOutputModuleName(moduleName);
      if (box == null) {
        return new ErrorPage("No such module: " + moduleName);
      } else if (box.containsStubCompile()) {
        return new ErrorPage("This module hasn't been compiled yet.");
      } else {
        return makeLogPage(box);
      }
    }

    if (target.equals("/favicon.ico")) {
      InputStream faviconStream = getClass().getResourceAsStream("favicon.ico");
      if (faviconStream == null) {
        return new ErrorPage("icon not found");
      }
      // IE8 will not load the favicon in an img tag with the default MIME type,
      // so use "image/x-icon" instead.
      return Responses.newBinaryStreamResponse("image/x-icon", faviconStream);
    }

    if (target.equals("/policies/")) {
      return makePolicyIndexPage();
    }

    if (target.equals("/progress")) {
      // TODO: return a list of progress objects here, one for each job.
      JobEvent event = eventTable.getCompilingJobEvent();

      JsonObject json;
      if (event == null) {
        json = new JsonObject();
        json.put("status", "idle");
      } else {
        json = jsonExporter.exportProgressResponse(event);
      }
      return Responses.newJsonResponse(json);
    }

    Matcher matcher = SAFE_MODULE_PATH.matcher(target);
    if (matcher.matches()) {
      return makeModulePage(matcher.group(1));
    }

    matcher = SAFE_DIRECTORY_PATH.matcher(target);
    if (matcher.matches() && SourceHandler.isSourceMapRequest(target)) {
      return handler.handle(target, request, logger);
    }

    matcher = SAFE_FILE_PATH.matcher(target);
    if (matcher.matches()) {
      if (SourceHandler.isSourceMapRequest(target)) {
        return handler.handle(target, request, logger);
      }
      if (target.startsWith("/policies/")) {
        return makePolicyFilePage(target);
      }
      return makeCompilerOutputPage(target);
    }

    logger.log(TreeLogger.WARN, "ignored get request: " + target);
    return null; // not handled
  }

  /**
   * Returns a file that the compiler wrote to its war directory.
   */
  private Response makeCompilerOutputPage(String target) {

    int secondSlash = target.indexOf('/', 1);
    String moduleName = target.substring(1, secondSlash);
    Outbox box = outboxes.findByOutputModuleName(moduleName);
    if (box == null) {
      return new ErrorPage("No such module: " + moduleName);
    }

    final String contentEncoding;
    File file = box.getOutputFile(target);
    if (!file.isFile()) {
      // perhaps it's compressed
      file = box.getOutputFile(target + ".gz");
      if (!file.isFile()) {
        return new ErrorPage("not found: " + file.toString());
      }
      contentEncoding = "gzip";
    } else {
      contentEncoding = null;
    }

    final String sourceMapUrl;
    Matcher match = CACHE_JS_FILE.matcher(target);
    if (match.matches()) {
      String strongName = match.group(1);
      String template = SourceHandler.sourceMapLocationTemplate(moduleName);
      sourceMapUrl = template.replace("__HASH__", strongName);
    } else {
      sourceMapUrl = null;
    }

    String mimeType = guessMimeType(target);
    final Response barePage = Responses.newFileResponse(mimeType, file);

    // Wrap the response to send the extra headers.
    return new Response() {
      @Override
      public void send(HttpServletRequest request, HttpServletResponse response, TreeLogger logger)
          throws IOException {
        // TODO: why do we need this? Looks like Ray added it a long time ago.
        response.setHeader("Access-Control-Allow-Origin", "*");

        if (sourceMapUrl != null) {
          response.setHeader("X-SourceMap", sourceMapUrl);
          response.setHeader("SourceMap", sourceMapUrl);
        }

        if (contentEncoding != null) {
          if (!request.getHeader("Accept-Encoding").contains("gzip")) {
            response.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED);
            logger.log(TreeLogger.WARN, "client doesn't accept gzip; bailing");
            return;
          }
          response.setHeader("Content-Encoding", "gzip");
        }

        barePage.send(request, response, logger);
      }
    };
  }

  private Response makeModulePage(String moduleName) {
    Outbox box = outboxes.findByOutputModuleName(moduleName);
    if (box == null) {
      return new ErrorPage("No such module: " + moduleName);
    }

    JsonObject json = jsonExporter.exportModulePageVars(box);
    return Pages.newHtmlPage("config", json, "modulepage.html");
  }

  private Response makePolicyIndexPage() {

    return new Response() {

      @Override
      public void send(HttpServletRequest request, HttpServletResponse response, TreeLogger logger)
          throws IOException {
        response.setContentType("text/html");

        HtmlWriter out = new HtmlWriter(response.getWriter());

        out.startTag("html").nl();
        out.startTag("head").nl();
        out.startTag("title").text("Policy Files").endTag("title").nl();
        out.endTag("head");
        out.startTag("body");

        out.startTag("h1").text("Policy Files").endTag("h1").nl();

        for (Outbox box : outboxes.getOutboxes()) {
          List<PolicyFile> policies = box.readRpcPolicyManifest();
          if (!policies.isEmpty()) {
            out.startTag("h2").text(box.getOutputModuleName()).endTag("h2").nl();

            out.startTag("table").nl();
            for (PolicyFile policy : policies) {

              out.startTag("tr");

              out.startTag("td");

              out.startTag("a", "href=", policy.getServiceSourceUrl());
              out.text(policy.getServiceName());
              out.endTag("a");

              out.endTag("td");

              out.startTag("td");

              out.startTag("a", "href=", policy.getUrl());
              out.text(policy.getName());
              out.endTag("a");

              out.endTag("td");

              out.endTag("tr").nl();
            }
            out.endTag("table").nl();
          }
        }

        out.endTag("body").nl();
        out.endTag("html").nl();
      }
    };
  }

  private Response makePolicyFilePage(String target) {

    int secondSlash = target.indexOf('/', 1);
    if (secondSlash < 1) {
      return new ErrorPage("invalid URL for policy file: " + target);
    }

    String rest = target.substring(secondSlash + 1);
    if (rest.contains("/") || !rest.endsWith(".gwt.rpc")) {
      return new ErrorPage("invalid name for policy file: " + rest);
    }

    File fileToSend = outboxes.findPolicyFile(rest);
    if (fileToSend == null) {
      return new ErrorPage("Policy file not found: " + rest);
    }

    return Responses.newFileResponse("text/plain", fileToSend);
  }

  /**
   * Sends the log file as html with errors highlighted in red.
   */
  private Response makeLogPage(final Outbox box) {
    final File file = box.getCompileLog();
    if (!file.isFile()) {
      return new ErrorPage("log file not found");
    }

    return new Response() {

      @Override
      public void send(HttpServletRequest request, HttpServletResponse response, TreeLogger logger)
          throws IOException {
        BufferedReader reader = new BufferedReader(new FileReader(file));

        response.setStatus(HttpServletResponse.SC_OK);
        response.setContentType("text/html");
        response.setHeader("Content-Style-Type", "text/css");

        HtmlWriter out = new HtmlWriter(response.getWriter());
        out.startTag("html").nl();
        out.startTag("head").nl();
        out.startTag("title").text(box.getOutputModuleName() + " compile log").endTag("title").nl();
        out.startTag("style").nl();
        out.text(".error { color: red; font-weight: bold; }").nl();
        out.endTag("style").nl();
        out.endTag("head").nl();
        out.startTag("body").nl();
        sendLogAsHtml(reader, out);
        out.endTag("body").nl();
        out.endTag("html").nl();
      }
    };
  }

  private static final Pattern ERROR_PATTERN = Pattern.compile("\\[ERROR\\]");

  /**
   * Copies in to out line by line, escaping each line for html characters and highlighting
   * error lines. Closes <code>in</code> when done.
   */
  private static void sendLogAsHtml(BufferedReader in, HtmlWriter out) throws IOException {
    try {
      out.startTag("pre").nl();
      String line = in.readLine();
      while (line != null) {
        Matcher m = ERROR_PATTERN.matcher(line);
        boolean error = m.find();
        if (error) {
          out.startTag("span", "class=", "error");
        }
        out.text(line);
        if (error) {
          out.endTag("span");
        }
        out.nl(); // the readLine doesn't include the newline.
        line = in.readLine();
      }
      out.endTag("pre").nl();
    } finally {
      in.close();
    }
  }

  /* visible for testing */
  static String guessMimeType(String filename) {
    String mimeType = MIME_TYPES.getMimeByExtension(filename);
    return mimeType != null ? mimeType : "";
  }

  /**
   * Returns the binding properties from the web page where dev mode is being used. (As passed in
   * by dev_mode_on.js in a JSONP request to "/recompile".)
   */
  private Map<String, String> getBindingProperties(HttpServletRequest request) {
    Map<String, String> result = new HashMap<>();
    for (Object key : request.getParameterMap().keySet()) {
      String propName = (String) key;
      if (!propName.equals("_callback")) {
        result.put(propName, request.getParameter(propName));
      }
    }
    return result;
  }

  private static void setHandled(HttpServletRequest request) {
    Request baseRequest = (request instanceof Request) ? (Request) request :
        HttpConnection.getCurrentConnection().getHttpChannel().getRequest();
    baseRequest.setHandled(true);
  }
}
