// Copyright (C) 2009 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.httpd;

import static com.google.inject.Scopes.SINGLETON;

import com.google.common.base.Strings;
import com.google.gerrit.common.PageLinks;
import com.google.gerrit.extensions.client.AuthType;
import com.google.gerrit.httpd.raw.CatServlet;
import com.google.gerrit.httpd.raw.HostPageServlet;
import com.google.gerrit.httpd.raw.LegacyGerritServlet;
import com.google.gerrit.httpd.raw.SshInfoServlet;
import com.google.gerrit.httpd.raw.ToolServlet;
import com.google.gerrit.httpd.restapi.AccessRestApiServlet;
import com.google.gerrit.httpd.restapi.AccountsRestApiServlet;
import com.google.gerrit.httpd.restapi.ChangesRestApiServlet;
import com.google.gerrit.httpd.restapi.ConfigRestApiServlet;
import com.google.gerrit.httpd.restapi.GroupsRestApiServlet;
import com.google.gerrit.httpd.restapi.ProjectsRestApiServlet;
import com.google.gerrit.httpd.rpc.doc.QueryDocumentationFilter;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.config.AuthConfig;
import com.google.gerrit.server.config.GerritOptions;
import com.google.gwtexpui.server.CacheControlFilter;
import com.google.inject.Key;
import com.google.inject.Provider;
import com.google.inject.internal.UniqueAnnotations;
import com.google.inject.servlet.ServletModule;
import java.io.IOException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jgit.lib.Constants;

class UrlModule extends ServletModule {
  private GerritOptions options;
  private AuthConfig authConfig;

  UrlModule(GerritOptions options, AuthConfig authConfig) {
    this.options = options;
    this.authConfig = authConfig;
  }

  @Override
  protected void configureServlets() {
    filter("/*").through(Key.get(CacheControlFilter.class));
    bind(Key.get(CacheControlFilter.class)).in(SINGLETON);

    if (options.enableGwtUi()) {
      filter("/").through(XsrfCookieFilter.class);
      filter("/accounts/self/detail").through(XsrfCookieFilter.class);
      serve("/").with(HostPageServlet.class);
      serve("/Gerrit").with(LegacyGerritServlet.class);
      serve("/Gerrit/*").with(legacyGerritScreen());
      // Forward PolyGerrit URLs to their respective GWT equivalents.
      serveRegex("^/(c|q|x|admin|dashboard|settings)/(.*)").with(gerritUrl());
    }
    serve("/cat/*").with(CatServlet.class);

    if (authConfig.getAuthType() != AuthType.OAUTH && authConfig.getAuthType() != AuthType.OPENID) {
      serve("/logout").with(HttpLogoutServlet.class);
      serve("/signout").with(HttpLogoutServlet.class);
    }
    serve("/ssh_info").with(SshInfoServlet.class);

    serve("/Main.class").with(notFound());
    serve("/com/google/gerrit/launcher/*").with(notFound());
    serve("/servlet/*").with(notFound());

    serve("/all").with(query("status:merged"));
    serve("/mine").with(screen(PageLinks.MINE));
    serve("/open").with(query("status:open"));
    serve("/watched").with(query("is:watched status:open"));
    serve("/starred").with(query("is:starred"));

    serveRegex("^/settings/?$").with(screen(PageLinks.SETTINGS));
    serveRegex("^/register$").with(registerScreen(false));
    serveRegex("^/register/(.+)$").with(registerScreen(true));
    serveRegex("^/([1-9][0-9]*)/?$").with(directChangeById());
    serveRegex("^/p/(.*)$").with(queryProjectNew());
    serveRegex("^/r/(.+)/?$").with(DirectChangeByCommit.class);

    filter("/a/*").through(RequireIdentifiedUserFilter.class);

    // Must be after RequireIdentifiedUserFilter so auth happens before checking
    // for RunAs capability.
    install(new RunAsFilter.Module());

    serveRegex("^/(?:a/)?tools/(.*)$").with(ToolServlet.class);

    // Bind servlets for REST root collections.
    // The '/plugins/' root collection is already handled by HttpPluginServlet
    // which is bound in HttpPluginModule. We cannot bind it here again although
    // this means that plugins can't add REST views on PLUGIN_KIND.
    serveRegex("^/(?:a/)?access/(.*)$").with(AccessRestApiServlet.class);
    serveRegex("^/(?:a/)?accounts/(.*)$").with(AccountsRestApiServlet.class);
    serveRegex("^/(?:a/)?changes/(.*)$").with(ChangesRestApiServlet.class);
    serveRegex("^/(?:a/)?config/(.*)$").with(ConfigRestApiServlet.class);
    serveRegex("^/(?:a/)?groups/(.*)?$").with(GroupsRestApiServlet.class);
    serveRegex("^/(?:a/)?projects/(.*)?$").with(ProjectsRestApiServlet.class);

    filter("/Documentation/").through(QueryDocumentationFilter.class);
  }

  private Key<HttpServlet> notFound() {
    return key(
        new HttpServlet() {
          private static final long serialVersionUID = 1L;

          @Override
          protected void doGet(final HttpServletRequest req, final HttpServletResponse rsp)
              throws IOException {
            rsp.sendError(HttpServletResponse.SC_NOT_FOUND);
          }
        });
  }

  private Key<HttpServlet> gerritUrl() {
    return key(
        new HttpServlet() {
          private static final long serialVersionUID = 1L;

          @Override
          protected void doGet(final HttpServletRequest req, final HttpServletResponse rsp)
              throws IOException {
            toGerrit(req.getRequestURI().substring(req.getContextPath().length()), req, rsp);
          }
        });
  }

  private Key<HttpServlet> screen(final String target) {
    return key(
        new HttpServlet() {
          private static final long serialVersionUID = 1L;

          @Override
          protected void doGet(final HttpServletRequest req, final HttpServletResponse rsp)
              throws IOException {
            toGerrit(target, req, rsp);
          }
        });
  }

  private Key<HttpServlet> legacyGerritScreen() {
    return key(
        new HttpServlet() {
          private static final long serialVersionUID = 1L;

          @Override
          protected void doGet(final HttpServletRequest req, final HttpServletResponse rsp)
              throws IOException {
            final String token = req.getPathInfo().substring(1);
            toGerrit(token, req, rsp);
          }
        });
  }

  private Key<HttpServlet> directChangeById() {
    return key(
        new HttpServlet() {
          private static final long serialVersionUID = 1L;

          @Override
          protected void doGet(final HttpServletRequest req, final HttpServletResponse rsp)
              throws IOException {
            try {
              String idString = req.getPathInfo();
              if (idString.endsWith("/")) {
                idString = idString.substring(0, idString.length() - 1);
              }
              Change.Id id = Change.Id.parse(idString);
              toGerrit(PageLinks.toChange(id), req, rsp);
            } catch (IllegalArgumentException err) {
              rsp.sendError(HttpServletResponse.SC_NOT_FOUND);
            }
          }
        });
  }

  private Key<HttpServlet> queryProjectNew() {
    return key(
        new HttpServlet() {
          private static final long serialVersionUID = 1L;

          @Override
          protected void doGet(HttpServletRequest req, HttpServletResponse rsp) throws IOException {
            String name = req.getPathInfo();
            if (Strings.isNullOrEmpty(name)) {
              toGerrit(PageLinks.ADMIN_PROJECTS, req, rsp);
              return;
            }

            while (name.endsWith("/")) {
              name = name.substring(0, name.length() - 1);
            }
            if (name.endsWith(Constants.DOT_GIT_EXT)) {
              name =
                  name.substring(
                      0, //
                      name.length() - Constants.DOT_GIT_EXT.length());
            }
            while (name.endsWith("/")) {
              name = name.substring(0, name.length() - 1);
            }
            Project.NameKey project = new Project.NameKey(name);
            toGerrit(
                PageLinks.toChangeQuery(PageLinks.projectQuery(project, Change.Status.NEW)),
                req,
                rsp);
          }
        });
  }

  private Key<HttpServlet> query(final String query) {
    return key(
        new HttpServlet() {
          private static final long serialVersionUID = 1L;

          @Override
          protected void doGet(final HttpServletRequest req, final HttpServletResponse rsp)
              throws IOException {
            toGerrit(PageLinks.toChangeQuery(query), req, rsp);
          }
        });
  }

  private Key<HttpServlet> key(final HttpServlet servlet) {
    final Key<HttpServlet> srv = Key.get(HttpServlet.class, UniqueAnnotations.create());
    bind(srv)
        .toProvider(
            new Provider<HttpServlet>() {
              @Override
              public HttpServlet get() {
                return servlet;
              }
            })
        .in(SINGLETON);
    return srv;
  }

  private Key<HttpServlet> registerScreen(final Boolean slash) {
    return key(
        new HttpServlet() {
          private static final long serialVersionUID = 1L;

          @Override
          protected void doGet(final HttpServletRequest req, final HttpServletResponse rsp)
              throws IOException {
            String path = String.format("/register%s", slash ? req.getPathInfo() : "");
            toGerrit(path, req, rsp);
          }
        });
  }

  static void toGerrit(
      final String target, final HttpServletRequest req, final HttpServletResponse rsp)
      throws IOException {
    final StringBuilder url = new StringBuilder();
    url.append(req.getContextPath());
    url.append('/');
    url.append('#');
    url.append(target);
    rsp.sendRedirect(url.toString());
  }
}
