// Copyright (C) 2019 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.acceptance.rest.binding;

import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.rest.util.RestApiCallHelper;
import com.google.gerrit.acceptance.rest.util.RestCall;
import com.google.gerrit.acceptance.rest.util.RestCall.Method;
import com.google.gerrit.extensions.registration.DynamicMap;
import com.google.gerrit.extensions.restapi.ChildCollection;
import com.google.gerrit.extensions.restapi.IdString;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.extensions.restapi.RestApiModule;
import com.google.gerrit.extensions.restapi.RestCollectionModifyView;
import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.extensions.restapi.RestResource;
import com.google.gerrit.extensions.restapi.RestView;
import com.google.gerrit.extensions.restapi.TopLevelResource;
import com.google.gerrit.httpd.restapi.RestApiServlet;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import com.google.inject.TypeLiteral;
import com.google.inject.servlet.ServletModule;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import org.junit.Test;

/**
 * Tests for checking plugin-provided REST API bindings directly under {@code /}.
 *
 * <p>These tests only verify that the plugin-provided REST endpoints are correctly bound, they do
 * not test the functionality of the plugin REST endpoints.
 */
public class PluginProvidedRootRestApiBindingsIT extends AbstractDaemonTest {

  /** Resource to bind a child collection. */
  public static final TypeLiteral<RestView<TestPluginResource>> TEST_KIND =
      new TypeLiteral<RestView<TestPluginResource>>() {};

  private static final String PLUGIN_NAME = "my-plugin";

  private static final ImmutableSet<RestCall> TEST_CALLS =
      ImmutableSet.of(
          RestCall.get("/plugins/" + PLUGIN_NAME + "/test-collection/"),
          RestCall.get("/plugins/" + PLUGIN_NAME + "/test-collection/1/detail"),
          RestCall.post("/plugins/" + PLUGIN_NAME + "/test-collection/"),
          RestCall.post("/plugins/" + PLUGIN_NAME + "/test-collection/1/update"),
          RestCall.builder(Method.GET, "/plugins/" + PLUGIN_NAME + "/not-found")
              .expectedResponseCode(SC_NOT_FOUND)
              .build());

  /** Module for all HTTP bindings. */
  static class MyPluginHttpModule extends ServletModule {
    @Override
    public void configureServlets() {
      bind(TestRootCollection.class);

      install(
          new RestApiModule() {
            @Override
            public void configure() {
              DynamicMap.mapOf(binder(), TEST_KIND);

              postOnCollection(TEST_KIND).to(TestPostOnCollection.class);
              post(TEST_KIND, "update").to(TestPost.class);
              get(TEST_KIND, "detail").to(TestGet.class);
            }
          });

      serveRegex("/(?:a/)?test-collection/(.*)$").with(TestRestApiServlet.class);
    }
  }

  @Singleton
  static class TestRestApiServlet extends RestApiServlet {
    private static final long serialVersionUID = 1L;

    @Inject
    TestRestApiServlet(RestApiServlet.Globals globals, Provider<TestRootCollection> collection) {
      super(globals, collection);
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse)
        throws ServletException, IOException {
      // This is...unfortunate. HttpPluginServlet (and/or ContextMapper) doesn't properly set the
      // servlet path on the wrapped request. Based on what RestApiServlet produces for non-plugin
      // requests, it should be:
      //   contextPath = "/plugins/checks"
      //   servletPath = "/checkers/"
      //   pathInfo = checkerUuid
      // Instead it does:
      //   contextPath = "/plugins/checks"
      //   servletPath = ""
      //   pathInfo = "/checkers/" + checkerUuid
      // This results in RestApiServlet splitting the pathInfo into ["", "checkers", checkerUuid],
      // and it passes the "" to CheckersCollection#parse, which understandably, but unfortunately,
      // fails.
      //
      // This frankly seems like a bug that should be fixed, but it would quite likely break
      // existing plugins in confusing ways. So, we work around it by introducing our own request
      // wrapper with the correct paths.
      HttpServletRequest req = (HttpServletRequest) servletRequest;
      String pathInfo = req.getPathInfo();
      String correctServletPath = "/test-collection/";
      String fixedPathInfo = pathInfo.substring(correctServletPath.length());
      HttpServletRequestWrapper wrapped =
          new HttpServletRequestWrapper(req) {
            @Override
            public String getServletPath() {
              return correctServletPath;
            }

            @Override
            public String getPathInfo() {
              return fixedPathInfo;
            }
          };

      super.service(wrapped, (HttpServletResponse) servletResponse);
    }
  }

  static class TestPluginResource implements RestResource {}

  @Singleton
  static class TestRootCollection implements ChildCollection<TopLevelResource, TestPluginResource> {
    private final DynamicMap<RestView<TestPluginResource>> views;

    @Inject
    TestRootCollection(DynamicMap<RestView<TestPluginResource>> views) {
      this.views = views;
    }

    @Override
    public RestView<TopLevelResource> list() throws RestApiException {
      return (RestReadView<TopLevelResource>)
          resource -> Response.ok(ImmutableList.of("one", "two"));
    }

    @Override
    public TestPluginResource parse(TopLevelResource parent, IdString id) throws Exception {
      return new TestPluginResource();
    }

    @Override
    public DynamicMap<RestView<TestPluginResource>> views() {
      return views;
    }
  }

  @Singleton
  static class TestPostOnCollection
      implements RestCollectionModifyView<TopLevelResource, TestPluginResource, String> {
    @Override
    public Response<String> apply(TopLevelResource parentResource, String input) throws Exception {
      return Response.ok("test");
    }
  }

  @Singleton
  static class TestPost implements RestModifyView<TestPluginResource, String> {
    @Override
    public Response<String> apply(TestPluginResource resource, String input) throws Exception {
      return Response.ok("test");
    }
  }

  @Singleton
  static class TestGet implements RestReadView<TestPluginResource> {
    @Override
    public Response<String> apply(TestPluginResource resource) throws Exception {
      return Response.ok("test");
    }
  }

  @Test
  public void testEndpoints() throws Exception {
    try (AutoCloseable ignored = installPlugin(PLUGIN_NAME, null, MyPluginHttpModule.class, null)) {
      RestApiCallHelper.execute(adminRestSession, TEST_CALLS.asList());
    }
  }
}
