// Copyright (C) 2008 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.google.gerrit.server;

import com.google.gerrit.client.Link;
import com.google.gerrit.client.reviewdb.Account;
import com.google.gerrit.client.reviewdb.Change;
import com.google.gerrit.client.reviewdb.PatchSet;
import com.google.gerrit.client.reviewdb.RevId;
import com.google.gerrit.client.reviewdb.ReviewDb;
import com.google.gerrit.client.rpc.Common;
import com.google.gwtjsonrpc.server.XsrfException;
import com.google.gwtorm.client.OrmException;

import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/** Rewrites Gerrit 1 style URLs to Gerrit 2 style URLs. */
public class UrlRewriteFilter implements Filter {
  private static final Pattern CHANGE_ID = Pattern.compile("^/(\\d+)/?$");
  private static final Pattern REV_ID =
      Pattern.compile("^/r/([0-9a-fA-F]{4," + RevId.LEN + "})/?$");
  private static final Pattern USER_PAGE = Pattern.compile("^/user/(.*)/?$");
  private static final Map<String, String> staticLinks;
  private static final Set<String> staticExtensions;

  static {
    staticLinks = new HashMap<String, String>();
    staticLinks.put("", "");
    staticLinks.put("/", "");

    staticLinks.put("/mine", Link.MINE);
    staticLinks.put("/starred", Link.MINE_STARRED);
    staticLinks.put("/settings", Link.SETTINGS);

    staticLinks.put("/all_unclaimed", Link.ALL_UNCLAIMED);
    staticLinks.put("/all", Link.ALL_MERGED);
    staticLinks.put("/open", Link.ALL_OPEN);

    staticExtensions = new HashSet<String>();
    staticExtensions.add(".css");
    staticExtensions.add(".gif");
    staticExtensions.add(".html");
    staticExtensions.add(".js");
    staticExtensions.add(".png");
  }

  private FilterConfig config;

  public void init(final FilterConfig config) throws ServletException {
    this.config = config;
    try {
      GerritServer.getInstance();
    } catch (OrmException e) {
      throw new ServletException("Cannot initialize GerritServer", e);
    } catch (XsrfException e) {
      throw new ServletException("Cannot initialize GerritServer", e);
    }
  }

  public void destroy() {
  }

  public void doFilter(final ServletRequest sreq, final ServletResponse srsp,
      final FilterChain chain) throws IOException, ServletException {
    final HttpServletRequest req = (HttpServletRequest) sreq;
    final HttpServletResponse rsp = (HttpServletResponse) srsp;
    final String pathInfo = pathInfo(req);

    if (pathInfo.startsWith("/gerrit/rpc/")) {
      // RPC requests are very common in Gerrit 2, we want to make sure
      // they run quickly by jumping through the chain as fast as we can.
      //
      chain.doFilter(req, rsp);
    } else if (staticExtension(pathInfo, req, rsp, chain)) {
    } else if (staticLink(pathInfo, req, rsp)) {
    } else if (bareChangeId(pathInfo, req, rsp)) {
    } else if (bareRevisionId(pathInfo, req, rsp)) {
    } else if (bareUserEmailDashboard(pathInfo, req, rsp)) {
    } else {
      // Anything else is either a static resource request (which the container
      // can do for us) or is going to be a 404 error when the container cannot
      // find the resource. Either form of request is not very common compared
      // to the above cases.
      //
      chain.doFilter(req, rsp);
    }
  }

  private static boolean staticExtension(final String pathInfo,
      final HttpServletRequest req, final HttpServletResponse rsp,
      final FilterChain chain) throws IOException, ServletException {
    final int d = pathInfo.lastIndexOf('.');
    if (d > 0 && staticExtensions.contains(pathInfo.substring(d + 1))) {
      // Any URL which ends in this static extension is meant to be handled
      // by the servlet container, by returning a resource from the WAR.
      // We don't need to evaluate it any further.
      //
      chain.doFilter(req, rsp);
      return true;
    }
    return false;
  }

  private static boolean staticLink(final String pathInfo,
      final HttpServletRequest req, final HttpServletResponse rsp)
      throws IOException {
    final String newLink = staticLinks.get(pathInfo);
    if (newLink == null) {
      return false;
    }

    // A static link (one with no parameters).
    //
    final StringBuffer url = toGerrit(req);
    if (newLink.length() > 0) {
      url.append('#');
      url.append(newLink);
    }
    rsp.sendRedirect(url.toString());
    return true;
  }

  private static boolean bareChangeId(final String pathInfo,
      final HttpServletRequest req, final HttpServletResponse rsp)
      throws IOException {
    final Matcher m = CHANGE_ID.matcher(pathInfo);
    if (!m.matches()) {
      return false;
    }

    final Change.Id id = Change.Id.parse(m.group(1));
    final StringBuffer url = toGerrit(req);
    url.append('#');
    url.append(Link.toChange(id));
    rsp.sendRedirect(url.toString());
    return true;
  }

  private boolean bareRevisionId(final String pathInfo,
      final HttpServletRequest req, final HttpServletResponse rsp)
      throws IOException {
    final Matcher m = REV_ID.matcher(pathInfo);
    if (!m.matches()) {
      return false;
    }

    final String rev = m.group(1).toLowerCase();
    if (rev.length() > RevId.LEN) {
      rsp.sendError(HttpServletResponse.SC_NOT_FOUND);
      return true;
    }

    final RevId id = new RevId(rev);
    final List<PatchSet> patches;
    try {
      final ReviewDb db = Common.getSchemaFactory().open();
      try {
        if (id.isComplete()) {
          patches = db.patchSets().byRevision(id).toList();
        } else {
          patches = db.patchSets().byRevisionRange(id, id.max()).toList();
        }
      } finally {
        db.close();
      }
    } catch (OrmException e) {
      config.getServletContext().log("Unable to query for " + rev, e);
      rsp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
      return true;
    }

    if (patches.size() == 0) {
      rsp.sendError(HttpServletResponse.SC_NOT_FOUND);
    } else if (patches.size() == 1) {
      final StringBuffer url = toGerrit(req);
      url.append('#');
      url.append(Link.toChange(patches.get(0).getId().getParentKey()));
      rsp.sendRedirect(url.toString());
    } else {
      // TODO Someday this should be a menu of choices.
      rsp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
    }
    return true;
  }

  private boolean bareUserEmailDashboard(final String pathInfo,
      final HttpServletRequest req, final HttpServletResponse rsp)
      throws IOException {
    final Matcher m = USER_PAGE.matcher(pathInfo);
    if (!m.matches()) {
      return false;
    }

    final String email = cleanEmail(m.group(1));
    final List<Account> people;
    try {
      final ReviewDb db = Common.getSchemaFactory().open();
      try {
        people = db.accounts().byPreferredEmail(email).toList();
      } finally {
        db.close();
      }
    } catch (OrmException e) {
      config.getServletContext().log("Unable to query for " + email, e);
      rsp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
      return true;
    }

    if (people.size() == 0) {
      rsp.sendError(HttpServletResponse.SC_NOT_FOUND);
    } else if (people.size() == 1) {
      final StringBuffer url = toGerrit(req);
      url.append('#');
      url.append(Link.toAccountDashboard(people.get(0).getId()));
      rsp.sendRedirect(url.toString());
    } else {
      // TODO Someday this should be a menu of choices.
      rsp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
    }
    return true;
  }

  private static String cleanEmail(final String email) {
    int dc = email.indexOf(",,");
    if (dc >= 0) {
      return email.substring(0, dc) + "@" + email.substring(dc + 2);
    }

    dc = email.indexOf(',');
    if (dc >= 0) {
      return email.substring(0, dc) + "@" + email.substring(dc + 1);
    }
    return email;
  }

  private static String pathInfo(final HttpServletRequest req) {
    final String uri = req.getRequestURI();
    final String ctx = req.getContextPath();
    return uri.startsWith(ctx) ? uri.substring(ctx.length()) : uri;
  }

  private static StringBuffer toGerrit(final HttpServletRequest req) {
    final StringBuffer url = new StringBuffer();
    url.append(req.getContextPath());
    url.append("/Gerrit");
    return url;
  }
}
