// 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.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.audit.AuditEvent;
import com.google.gerrit.audit.AuditService;
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.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.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 File site_path;
  private final File etc_dir;
  private final File static_dir;
  private final String gerrit_config_path;
  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.site_path = sitePaths.site_path.toFile();
    this.etc_dir = sitePaths.etc_dir.toFile();
    this.static_dir = sitePaths.static_dir.toFile();
    try {
      this.gerrit_config_path = sitePaths.gerrit_config.toFile().getCanonicalPath();
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

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

  @Override
  public void doPut(HttpServletRequest req, HttpServletResponse res)
      throws IOException {
    if (!isValidFile(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 = configFile(req);
    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);
    ByteArrayInputStream in = new ByteArrayInputStream(bytes);
    OutputStream out = res.getOutputStream();
    try {
      ByteStreams.copy(in, out);
    } finally {
      in.close();
    }
  }

  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 {
    File f = configFile(req);
    return gerrit_config_path.equals(f.getCanonicalPath());
  }

  private boolean isValidFile(HttpServletRequest req) throws IOException {
    File f = configFile(req);
    if (!f.isFile()) {
      return false;
    }
    return isParent(etc_dir, f) || isParent(static_dir, f);
  }

  private File configFile(HttpServletRequest req) {
    return new File(site_path, req.getServletPath() + req.getPathInfo());
  }

  private boolean isParent(File parent, File child) throws IOException {
    File p = parent.getCanonicalFile();
    File c = child.getCanonicalFile();
    for (;;) {
      c = c.getParentFile();
      if (c == null) {
        return false;
      }
      if (c.equals(p)) {
        return true;
      }
    }
  }

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

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

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