// Copyright (C) 2013 The Android Open Source Project
//
// 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.googlesource.gerrit.plugins.serverconfig;

import com.google.common.base.CharMatcher;
import com.google.common.base.Charsets;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.MultimapBuilder;
import com.google.common.io.ByteStreams;
import com.google.gerrit.common.TimeUtil;
import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.extensions.registration.DynamicItem;
import com.google.gerrit.httpd.WebSession;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.audit.AuditEvent;
import com.google.gerrit.server.audit.AuditService;
import com.google.gerrit.server.config.SitePaths;
import com.google.inject.Inject;
import com.google.inject.Singleton;

import org.eclipse.jgit.diff.RawText;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.util.FS;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.text.MessageFormat;

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

@Singleton
public class ServerConfigServlet extends HttpServlet {
  private static final long serialVersionUID = 1L;
  private static final Logger log = LoggerFactory
      .getLogger(ServerConfigServlet.class);

  private final SitePaths sitePaths;
  private final AuditService auditService;
  private final DynamicItem<WebSession> webSession;
  private final String pluginName;

  @Inject
  ServerConfigServlet(SitePaths sitePaths, DynamicItem<WebSession> webSession,
      AuditService auditService, @PluginName String pluginName) {
    this.webSession = webSession;
    this.auditService = auditService;
    this.pluginName = pluginName;
    this.sitePaths = sitePaths;
  }

  @Override
  public void doGet(HttpServletRequest req, HttpServletResponse res)
      throws IOException {
    if (!isAllowedPath(req)) {
      res.setStatus(HttpServletResponse.SC_FORBIDDEN);
      return;
    }
    streamFile(req, res);
  }

  @Override
  public void doPut(HttpServletRequest req, HttpServletResponse res)
      throws IOException {
    if (!isAllowedPath(req)) {
      res.setStatus(HttpServletResponse.SC_FORBIDDEN);
      return;
    }
    if (isGerritConfig(req)) {
      writeFileAndFireAuditEvent(req, res);
    } else {
      writeFile(req, res);
    }
  }

  private void writeFileAndFireAuditEvent(HttpServletRequest req,
      HttpServletResponse res) throws IOException {
    File oldFile = resolvePath(req).toFile();
    File dir = oldFile.getParentFile();
    File newFile = File.createTempFile(oldFile.getName(), ".new", dir);
    streamRequestToFile(req, newFile);

    try {
      FileBasedConfig config = new FileBasedConfig(newFile, FS.DETECTED);
      config.load();

      String diff = diff(oldFile, newFile);
      audit("about to change config file", oldFile.getPath(), diff);

      newFile.renameTo(oldFile);
      audit("changed config file", oldFile.getPath(), diff);

      res.setStatus(HttpServletResponse.SC_NO_CONTENT);
    } catch (ConfigInvalidException e) {
      log.warn("Configuration file is invalid", e);

      Throwable cause = e.getCause();
      final String msg =
          cause instanceof ConfigInvalidException ? cause.getMessage()
              : e.getMessage();

      newFile.delete();
      respondInvalidConfig(req, res, msg);
    }
  }

  private void respondInvalidConfig(HttpServletRequest req,
      HttpServletResponse res, String messageTxt) throws IOException {
    String message =
        MessageFormat.format("Invalid config file {0}: {1}", req.getPathInfo(),
            messageTxt);
    res.setStatus(HttpServletResponse.SC_BAD_REQUEST);
    res.setContentType("application/octet-stream");
    res.setContentLength(message.length());
    byte[] bytes = message.getBytes(Charsets.UTF_8);
    OutputStream out = res.getOutputStream();
    try (ByteArrayInputStream in = new ByteArrayInputStream(bytes)) {
      ByteStreams.copy(in, out);
    }
  }

  private static String diff(File oldFile, File newFile) throws IOException {
    RawText oldContext = new RawText(oldFile);
    RawText newContext = new RawText(newFile);
    UnifiedDiffer differ = new UnifiedDiffer();
    return differ.diff(oldContext, newContext);
  }

  private void audit(String what, String path, String diff) {
    String sessionId = webSession.get().getSessionId();
    CurrentUser who = webSession.get().getUser();
    long when = TimeUtil.nowMs();
    ListMultimap<String, Object> params =
        MultimapBuilder.hashKeys().arrayListValues().build();
    params.put("plugin", pluginName);
    params.put("class", ServerConfigServlet.class);
    params.put("diff", diff);
    params.put("file", path);
    auditService.dispatch(new AuditEvent(sessionId, who, what, when, params, null));
  }

  private boolean isGerritConfig(HttpServletRequest req) throws IOException {
    return Files.isSameFile(sitePaths.gerrit_config, resolvePath(req));
  }

  private boolean isAllowedPath(HttpServletRequest req) throws IOException {
    Path p = resolvePath(req);
    if (!Files.isRegularFile(p)) {
      return false;
    }
    return isParent(sitePaths.etc_dir, p) || isParent(sitePaths.static_dir, p);
  }

  private Path resolvePath(HttpServletRequest req) {
    return sitePaths.resolve(CharMatcher.is('/').trimLeadingFrom(
        req.getServletPath() + req.getPathInfo()));
  }

  private boolean isParent(Path parent, Path child) throws IOException {
    Path p = child;
    for (;;) {
      p = p.getParent();
      if (p == null) {
        return false;
      }
      if (Files.isSameFile(p, parent)) {
        return true;
      }
    }
  }

  private void streamFile(HttpServletRequest req, HttpServletResponse res)
      throws IOException {
    File f = resolvePath(req).toFile();
    res.setStatus(HttpServletResponse.SC_OK);
    res.setContentType("application/octet-stream");
    res.setContentLength((int) f.length());
    OutputStream out = res.getOutputStream();
    try (InputStream in = new FileInputStream(f)) {
      ByteStreams.copy(in, out);
    }
  }

  private void writeFile(HttpServletRequest req, HttpServletResponse res)
      throws IOException {
    res.setStatus(HttpServletResponse.SC_NO_CONTENT);
    streamRequestToFile(req, resolvePath(req).toFile());
  }

  private void streamRequestToFile(HttpServletRequest req, File file)
      throws IOException, FileNotFoundException {
    InputStream in = req.getInputStream();
    try (OutputStream out = new FileOutputStream(file)) {
      ByteStreams.copy(in, out);
    }
  }
}
