// Copyright (C) 2012 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.branchnetwork.canvas;

import com.google.gerrit.common.data.GitwebType;
import com.google.gerrit.entities.Project;
import com.google.gerrit.extensions.annotations.PluginCanonicalWebUrl;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.config.GitwebConfig;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.permissions.ProjectPermission;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.MalformedURLException;
import java.net.URL;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.Repository;

@Singleton
public class GitGraphServlet extends HttpServlet {

  private static final long serialVersionUID = -822406714154950673L;
  private static final int PROGRESS_BAR_WIDTH = 208;
  private static final int PROGRESS_BAR_HEIGHT = 13;
  private String canonicalPath;
  private GitRepositoryManager repoManager;
  private GitwebConfig gitWebConfig;
  private String pluginCanonicalWebUrl;
  private final Provider<CurrentUser> user;
  private final PermissionBackend permissionBackend;

  @Inject
  public GitGraphServlet(
      @PluginCanonicalWebUrl String url,
      GitwebConfig gitWebConfig,
      final GitRepositoryManager repoManager,
      Provider<CurrentUser> user,
      PermissionBackend permissionBackend)
      throws MalformedURLException {
    this.canonicalPath = new URL(url).getPath();
    this.pluginCanonicalWebUrl = url.substring(0, url.length() - (canonicalPath.length() - 1));
    this.repoManager = repoManager;
    this.gitWebConfig = gitWebConfig;
    this.user = user;
    this.permissionBackend = permissionBackend;
  }

  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp)
      throws ServletException, IOException {
    resp.setContentType("text/html;charset=UTF-8");
    PrintWriter out = resp.getWriter();

    try {
      String repoName = req.getParameter("p");
      if (repoName == null) {
        resp.sendRedirect("Documentation/index.html");
        return;
      }

      boolean naked = req.getParameter("naked") != null;
      int width = getParam(req, "width", 920);
      int height = getParam(req, "height", 600);

      if (repoName.endsWith(".git")) {
        repoName = repoName.substring(0, repoName.length() - 4);
      }

      final Project.NameKey nameKey = Project.nameKey(repoName);
      try {
        permissionBackend.user(user.get()).project(nameKey).check(ProjectPermission.ACCESS);
      } catch (AuthException | PermissionBackendException e) {
        resp.sendError(HttpServletResponse.SC_NOT_FOUND);
        return;
      }

      Repository repo = null;
      try {
        repo = repoManager.openRepository(nameKey);
      } catch (RepositoryNotFoundException e) {
        getServletContext().log("Cannot open repository", e);
        resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        return;
      } finally {
        if (repo != null) {
          repo.close();
        }
      }

      String networkMetaUrl = String.format("%1$snetwork_meta/%2$s/", canonicalPath, repoName);
      String networkDataChunkUrl =
          String.format("%1$snetwork_data_chunk/%2$s/?nethash=", canonicalPath, repoName);

      GitwebType type = gitWebConfig.getGitwebType();
      if (type == null) {
        out.println("<html>ERROR: invalid gitweb configuration</html>");
      } else {
        String commitUrlPattern =
            gitWebConfig.getUrl()
                + type.getRevision()
                    .replaceAll("\\$\\{project\\}", repoName)
                    .replaceAll("\\$\\{commit\\}", "{2}");
        String projectPattern =
            gitWebConfig.getUrl() + type.getProject().replaceAll("\\$\\{project\\}", repoName);

        commitUrlPattern =
            (commitUrlPattern.startsWith("/")
                ? commitUrlPattern
                : pluginCanonicalWebUrl + commitUrlPattern);
        projectPattern =
            (projectPattern.startsWith("/")
                ? projectPattern
                : pluginCanonicalWebUrl + projectPattern);

        String header =
            "<html>\n"
                + "<head>\n"
                + "<style type=\"text/css\">\n"
                + "div#progress\n"
                + "{\n"
                + "position:absolute;\n"
                + "left:"
                + (width - PROGRESS_BAR_WIDTH) / 2
                + "px;\n"
                + "top:"
                + (height - PROGRESS_BAR_HEIGHT) / 2
                + "px;\n"
                + "z-index:-1;\n"
                + "}\n"
                + "div#graph\n"
                + "{\n"
                + "position:absolute;\n"
                + "left:0px;\n"
                + "top:0px;\n"
                + "z-index:0;\n"
                + "}\n"
                + "</style>\n"
                + "</head>\n"
                + "<body>\n"
                + "<div id=\"progress\" >"
                + "<img src=\""
                + canonicalPath
                + "static/progress_bar.gif\" />"
                + "</div>"
                + "<div id=\"graph\">";
        String javaScript =
            "<script type=\"text/javascript\" src=\""
                + canonicalPath
                + "static/jquery-1.4.2.min.js\"></script>\n"
                + "<script type=\"text/javascript\" src=\""
                + canonicalPath
                + "static/network.js\"></script>\n"
                + "<script type=\"text/javascript\">"
                + "$(document).ready( function() {\n"
                + "new NetworkCanvas('network-canvas', "
                + width
                + ", "
                + height
                + " , null, null, null,\n"
                + "'"
                + commitUrlPattern
                + "',\n"
                + "'"
                + projectPattern
                + "',\n"
                + "'"
                + networkMetaUrl
                + "',\n"
                + "'"
                + networkDataChunkUrl
                + "');\n"
                + "});\n"
                + "</script>\n";
        String canvas =
            "<canvas id=\"network-canvas\" width=\""
                + width
                + "\" height=\""
                + height
                + "\" style=\"cursor: default; \"></canvas>";
        String footer = "</div>" + "</body>\n" + "</html>\n";
        out.println(naked ? (javaScript + canvas) : (header + javaScript + canvas + footer));
      }
    } finally {
      out.close();
    }
  }

  private int getParam(HttpServletRequest req, String name, int defValue) {
    String value = req.getParameter(name);
    if (value != null) {
      return Integer.parseInt(value);
    } else {
      return defValue;
    }
  }
}
