// Copyright (C) 2015 Google Inc. All Rights Reserved.
//
// 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.gitiles;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;
import static javax.servlet.http.HttpServletResponse.SC_OK;

import com.google.common.base.Strings;
import com.google.common.net.HttpHeaders;
import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import java.util.Map;
import java.util.Optional;
import javax.annotation.Nullable;
import org.eclipse.jgit.internal.storage.dfs.DfsRepository;
import org.eclipse.jgit.internal.storage.dfs.DfsRepositoryDescription;
import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
import org.eclipse.jgit.junit.MockSystemReader;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.util.SystemReader;
import org.junit.After;
import org.junit.Before;

/** Base class for servlet tests. */
public class ServletTest {
  protected TestRepository<DfsRepository> repo;
  protected GitilesServlet servlet;

  @Before
  public void setUp() throws Exception {
    MockSystemReader mockSystemReader = new MockSystemReader();
    SystemReader.setInstance(mockSystemReader);
    DfsRepository r = new InMemoryRepository(new DfsRepositoryDescription("repo"));
    repo = new TestRepository<>(r, new RevWalk(r), mockSystemReader);
    servlet = TestGitilesServlet.create(repo);
  }

  @After
  public void tearDown() {
    SystemReader.setInstance(null);
  }

  protected FakeHttpServletResponse buildResponse(
      String path, String queryString, int expectedStatus, String origin) throws Exception {
    FakeHttpServletRequest req = FakeHttpServletRequest.newRequest();
    req.setHeader(HttpHeaders.ORIGIN, origin);
    req.setPathInfo(path);
    if (queryString != null) {
      req.setQueryString(queryString);
    }
    FakeHttpServletResponse res = new FakeHttpServletResponse();
    servlet.service(req, res);
    assertThat(res.getStatus()).isEqualTo(expectedStatus);
    return res;
  }

  protected FakeHttpServletResponse buildResponse(
      String path, String queryString, int expectedStatus) throws Exception {
    return buildResponse(path, queryString, expectedStatus, "http://localhost");
  }

  protected FakeHttpServletResponse build(String path) throws Exception {
    return buildResponse(path, null, SC_OK);
  }

  protected String buildHtml(String path, boolean assertHasETag) throws Exception {
    FakeHttpServletResponse res = build(path);
    assertThat(res.getHeader(HttpHeaders.CONTENT_TYPE)).isEqualTo("text/html");
    if (assertHasETag) {
      assertWithMessage("missing ETag").that(res.getHeader(HttpHeaders.ETAG)).isNotNull();
    }
    return res.getActualBodyString();
  }

  protected String buildHtml(String path) throws Exception {
    return buildHtml(path, true);
  }

  protected Map<String, Object> buildData(String path) throws Exception {
    // Render the page through Soy to ensure templates are valid, then return
    // the Soy data for introspection.
    FakeHttpServletRequest req = FakeHttpServletRequest.newRequest();
    req.setPathInfo(path);
    FakeHttpServletResponse res = new FakeHttpServletResponse();
    servlet.service(req, res);
    return BaseServlet.getData(req);
  }

  protected FakeHttpServletResponse buildText(String path) throws Exception {
    FakeHttpServletResponse res = buildResponse(path, "format=text", SC_OK);
    assertThat(res.getHeader(HttpHeaders.CONTENT_TYPE)).isEqualTo("text/plain");
    return res;
  }

  private String buildJsonRaw(String path, @Nullable String queryString) throws Exception {
    String fmt = "format=JSON";
    queryString = Strings.isNullOrEmpty(queryString) ? fmt : fmt + "&" + queryString;
    FakeHttpServletResponse res = buildResponse(path, queryString, SC_OK);
    assertThat(res.getHeader(HttpHeaders.CONTENT_TYPE)).isEqualTo("application/json");
    String body = res.getActualBodyString();
    String magic = ")]}'\n";
    assertThat(body).startsWith(magic);
    return body.substring(magic.length());
  }

  protected <T> T buildJson(Class<T> classOfT, String path, String queryString) throws Exception {
    return newGson().fromJson(buildJsonRaw(path, queryString), classOfT);
  }

  protected <T> T buildJson(Class<T> classOfT, String path) throws Exception {
    return buildJson(classOfT, path, null);
  }

  protected <T> T buildJson(TypeToken<T> typeOfT, String path, String queryString)
      throws Exception {
    return newGson().fromJson(buildJsonRaw(path, queryString), typeOfT.getType());
  }

  protected <T> T buildJson(TypeToken<T> typeOfT, String path) throws Exception {
    return buildJson(typeOfT, path, null);
  }

  private static Gson newGson() {
    return new GsonBuilder()
        .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
        .create();
  }

  protected String currentTimeFormatted() {
    PersonIdent p = new PersonIdent(repo.getRepository());
    return new DateFormatter(Optional.empty(), DateFormatter.Format.ISO).format(p);
  }

  protected void assertNotFound(String path, String queryString) throws Exception {
    buildResponse(path, queryString, SC_NOT_FOUND);
  }
}
