// Copyright 2013 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 com.google.enterprise.adaptor;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableSet;

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

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import java.util.TreeMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * Generates and serves a .zip file containing diagnostic information.
 *
 * <p>For example, it can include logs and a thread dump.
 */
class DownloadDumpHandler implements HttpHandler {
  private static final Logger log
      = Logger.getLogger(DownloadDumpHandler.class.getName());

  /** Used to generate the configuration output file */
  private Config config;

  /** To be used as part of the zip file name */
  private String feedName;

  /** Used to obtain statistics for one file in the .zip */
  private final StatRpcMethod statRpcMethod;

  /** Used to specify the top-level directory where logs are kept */
  private final File logsDir;

  /** Only used by the test class, to pass in a canned date */
  private final TimeProvider timeProvider;

  /** Used in handle() to generate the date portion of the zip file name;
      we are implicitly using the local time zone. */
  private final DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");

  /** Default to "logs/" and System time */
  public DownloadDumpHandler(Config config, String feedName,
      StatRpcMethod statRpcMethod) {
    this(config, feedName, statRpcMethod, new File("logs/"),
        new SystemTimeProvider());
  }

  @VisibleForTesting
  DownloadDumpHandler(Config config, String feedName,
      StatRpcMethod statRpcMethod, File logsDir, TimeProvider timeProvider) {
    if (null == config) {
      throw new NullPointerException();
    }
    if (null == feedName) {
      throw new NullPointerException();
    }
    if (feedName.contains("\"")) {
      throw new IllegalArgumentException(
          "feedName must not contain the \" character");
    }
    this.config = config;
    this.feedName = feedName;
    this.statRpcMethod = statRpcMethod; // OK to leave as null
    this.logsDir = logsDir;
    this.timeProvider = timeProvider;
  }

  @Override
  public void handle(HttpExchange ex) throws IOException {
    String requestMethod = ex.getRequestMethod();
    if (!"GET".equals(requestMethod)) {
      HttpExchanges.cannedRespond(ex, HttpURLConnection.HTTP_BAD_METHOD,
          Translation.HTTP_BAD_METHOD);
      return;
    }
    if (!ex.getRequestURI().getPath().equals(ex.getHttpContext().getPath())) {
      HttpExchanges.cannedRespond(ex, HttpURLConnection.HTTP_NOT_FOUND,
          Translation.HTTP_NOT_FOUND);
      return;
    }
    String dateAsString;
    synchronized (this) {  // DateFormat.format() is not thread-safe!
      dateAsString = dateFormat.format(
          new Date(timeProvider.currentTimeMillis()));
    }
    String filename = feedName + "-" + dateAsString + ".zip";
    String contentType = "application/zip";
    ex.getResponseHeaders().set("Content-Disposition",
        "attachment; filename=\"" + filename + "\"");
    // stream the contents of the zip
    HttpExchanges.startResponse(
        ex, HttpURLConnection.HTTP_OK, contentType, true);
    OutputStream os = ex.getResponseBody();
    BufferedOutputStream bos = new BufferedOutputStream(os);
    ZipOutputStream zos = new ZipOutputStream(bos);
    generateZipContents(logsDir, zos);
    zos.close();  // NOT in a "finally" clause - connection killed on an error.
  }

  private void generateZipContents(File logsDir, ZipOutputStream zos)
      throws IOException {
    dumpLogFiles(logsDir, zos);
    dumpStackTraces(zos);
    dumpConfig(zos);
    dumpStats(zos);
    zos.flush();
  }

  private void dumpLogFiles(File logsDir, ZipOutputStream zos)
      throws IOException {
    File[] files = logsDir.listFiles();
    if (files == null) {
      log.log(Level.FINER, "Unable to find logs directory {0}", logsDir);
      return;
    }
    for (File f : files) {
      // avoid zipping the (empty) lock file
      if (f.getName().endsWith(".lck")) {
        log.log(Level.FINEST, "Skipping lock file: {0}", f.getName());
        continue;
      }
      if (!f.isFile()) {
        // TODO(myk): consider zipping up files present under subdirectories.
        log.log(Level.FINEST, "Ignoring directory entry: {0}", f.getName());
        continue;
      }
      log.log(Level.FINEST, "Adding file: {0}/{1}",
          new Object[] {logsDir, f.getName()});
      InputStream is = createInputStream(f);
      try {
        zos.putNextEntry(new ZipEntry(logsDir.toString() + "/" + f.getName()));
        IOHelper.copyStream(is, zos);
      } finally {
        is.close();
      }
      zos.closeEntry();
    }
  }

  /**
   * Output the stack trace for every running thread (sorted by thread name).
   *
   * <p>For example:
   * <p><code>
   * Thread[Reference Handler,10,system]
   *   java.lang.Object.wait(Native Method)
   *   java.lang.Object.wait(Object.java:502)
   *   java.lang.ref.Reference$ReferenceHandler.run(Reference.java:129)
   * </code><p><code>
   * Thread ...
   * </code>
   */
  private void dumpStackTraces(ZipOutputStream zos) throws IOException {
    OutputStreamWriter writer = new OutputStreamWriter(zos, "UTF-8");
    String newline = "\n"; // so our support folks always see the same results
    Map<Thread, StackTraceElement[]> allThreads = Thread.getAllStackTraces();
    Map<String, StackTraceElement[]> sortedThreads =
        new TreeMap<String, StackTraceElement[]>();
    for (Map.Entry<Thread, StackTraceElement[]> me : allThreads.entrySet()) {
      sortedThreads.put(me.getKey().toString(), me.getValue());
    }
    zos.putNextEntry(new ZipEntry("threaddump.txt"));
    for (Map.Entry<String, StackTraceElement[]> me : sortedThreads.entrySet()) {
      writer.write(me.getKey());
      writer.write(newline);
      for (StackTraceElement element : me.getValue()) {
        writer.write(" ");
        writer.write("" + element);
        writer.write(newline);
      }
      writer.write(newline);
    }
    writer.flush();
    zos.closeEntry();
  }

  /**
   * Output the configuration into the diagnostics zip
   */
  private void dumpConfig(ZipOutputStream zos) throws IOException {
    PrintWriter writer = new PrintWriter(new OutputStreamWriter(zos, "UTF-8"));
    String newline = "\n"; // so our support folks always see the same results
    TreeMap<String, String> sortedConfig = new TreeMap<String, String>();
    for (String key : config.getAllKeys()) {
      sortedConfig.put(key, config.getValue(key));
    }
    zos.putNextEntry(new ZipEntry("config.txt"));
    prettyPrintMap(writer, sortedConfig);
    writer.flush();
    zos.closeEntry();
  }

  /**
   * Output the version info and statistics into the diagnostics zip
   */
  private void dumpStats(ZipOutputStream zos) throws IOException {
    PrintWriter writer = new PrintWriter(new OutputStreamWriter(zos, "UTF-8"));
    if (statRpcMethod == null) {
      return;  // don't generate empty stats file
    }
    @SuppressWarnings("unchecked")
    Map<String, Object> map = (Map<String, Object>) statRpcMethod.run(null);

    zos.putNextEntry(new ZipEntry("stats.txt"));

    if (null != map.get("versionStats")) {
      @SuppressWarnings("unchecked")
      Map<String, Object> vMap = (Map<String, Object>) map.get("versionStats");
      prettyPrintMap(writer, vMap);
    }

    if (null != map.get("simpleStats")) {
      @SuppressWarnings("unchecked")
      Map<String, Object> sMap = (Map<String, Object>) map.get("simpleStats");
      Set<String> expectedDateAttrs = ImmutableSet.of("whenStarted",
          "lastSuccessfulFullPushStart", "lastSuccessfulFullPushEnd",
          "currentFullPushStart", "lastSuccessfulIncrementalPushStart",
          "lastSuccessfulIncrementalPushEnd");
      DateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss Z");
      dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
      for (String key : expectedDateAttrs) {
        if (!sMap.containsKey(key)) {
          log.log(Level.INFO,
              "Did not find expected key \"{0}\" in simpleStats", key);
          continue;
        }
        Object value = sMap.get(key);
        if (value == null) {
          continue;
        }
        if (!(value instanceof Number)) {
          log.log(Level.INFO,
              "Key \"{0}\" contained non-date value \"{1}\" in simpleStats",
              new Object[] {key, value});
          continue;
        }
        long date = ((Number) value).longValue();
        if (date <= 0) {
          continue;
        }
        // It's a number > 0 -- assume it's a date.
        // Replace value in map with a formatted date.
        sMap.put(key, dateFormat.format(new Date(date)));
      }
      prettyPrintMap(writer, sMap);
    }

    writer.flush();
    zos.closeEntry();
  }

  /**
   * Pretty-prints a map
   */
  void prettyPrintMap(PrintWriter writer, Map<String, ?> map) {
    int maxKeyLength = 0;

    for (String key : map.keySet()) {
      if (key.length() > maxKeyLength) {
        maxKeyLength = key.length();
      }
    }

    String outputFormat = "%-" + (maxKeyLength + 1) + "s= %s%n";
    for (Map.Entry<String, ?> me : map.entrySet()) {
      writer.format(outputFormat, me.getKey(),
          (me.getValue() == null ? "[null]" : me.getValue().toString()));
    }
    writer.format("%n");
  }

  /**
   * Method gets overriden in test class to avoid using "real" IO.
   */
  @VisibleForTesting
  InputStream createInputStream(File file) throws IOException {
    return new FileInputStream(file);
  }
}
