// Copyright (C) 2013 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;

import static com.google.gerrit.acceptance.GitUtil.cloneProject;
import static com.google.gerrit.acceptance.GitUtil.createProject;
import static com.google.gerrit.acceptance.GitUtil.initSsh;
import static org.junit.Assert.assertEquals;

import com.google.common.base.Joiner;
import com.google.common.primitives.Chars;
import com.google.gerrit.acceptance.AcceptanceTestRequestScope.Context;
import com.google.gerrit.extensions.api.GerritApi;
import com.google.gerrit.extensions.api.changes.RevisionApi;
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.common.ListChangesOption;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.OutputFormat;
import com.google.gerrit.server.change.ChangeJson;
import com.google.gerrit.testutil.ConfigSuite;
import com.google.gson.Gson;
import com.google.gwtorm.server.SchemaFactory;
import com.google.inject.Inject;
import com.google.inject.util.Providers;

import org.apache.http.HttpStatus;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.lib.Config;
import org.junit.Rule;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runner.RunWith;
import org.junit.runners.model.Statement;

import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;

@RunWith(ConfigSuite.class)
public abstract class AbstractDaemonTest {
  @ConfigSuite.Parameter
  public Config baseConfig;

  @Inject
  protected AccountCreator accounts;

  @Inject
  private SchemaFactory<ReviewDb> reviewDbProvider;

  @Inject
  protected GerritApi gApi;

  @Inject
  private AcceptanceTestRequestScope atrScope;

  @Inject
  private IdentifiedUser.GenericFactory identifiedUserFactory;

  @Inject
  protected PushOneCommit.Factory pushFactory;

  protected Git git;
  protected GerritServer server;
  protected TestAccount admin;
  protected TestAccount user;
  protected RestSession adminSession;
  protected RestSession userSession;
  protected SshSession sshSession;
  protected ReviewDb db;
  protected Project.NameKey project;

  @Rule
  public TestRule testRunner = new TestRule() {
    @Override
    public Statement apply(final Statement base, final Description description) {
      return new Statement() {
        @Override
        public void evaluate() throws Throwable {
          boolean mem = description.getAnnotation(UseLocalDisk.class) == null;
          boolean enableHttpd = description.getAnnotation(NoHttpd.class) == null
              && description.getTestClass().getAnnotation(NoHttpd.class) == null;
          beforeTest(config(description), mem, enableHttpd);
          base.evaluate();
          afterTest();
        }
      };
    }
  };

  private Config config(Description description) {
    GerritConfigs cfgs = description.getAnnotation(GerritConfigs.class);
    GerritConfig cfg = description.getAnnotation(GerritConfig.class);
    if (cfgs != null && cfg != null) {
      throw new IllegalStateException("Use either @GerritConfigs or @GerritConfig not both");
    }
    if (cfgs != null) {
      return ConfigAnnotationParser.parse(baseConfig, cfgs);
    } else if (cfg != null) {
      return ConfigAnnotationParser.parse(baseConfig, cfg);
    } else {
      return baseConfig;
    }
  }

  private void beforeTest(Config cfg, boolean memory, boolean enableHttpd) throws Exception {
    server = startServer(cfg, memory, enableHttpd);
    server.getTestInjector().injectMembers(this);
    admin = accounts.admin();
    user = accounts.user();
    adminSession = new RestSession(server, admin);
    userSession = new RestSession(server, user);
    initSsh(admin);
    db = reviewDbProvider.open();
    Context ctx = newRequestContext(admin);
    atrScope.set(ctx);
    sshSession = ctx.getSession();
    project = new Project.NameKey("p");
    createProject(sshSession, project.get());
    git = cloneProject(sshSession.getUrl() + "/" + project.get());
  }

  protected GerritServer startServer(Config cfg, boolean memory,
      boolean enableHttpd) throws Exception {
    return GerritServer.start(cfg, memory, enableHttpd);
  }

  private void afterTest() throws Exception {
    db.close();
    sshSession.close();
    server.stop();
    TempFileUtil.cleanup();
  }

  protected PushOneCommit.Result createChange() throws GitAPIException,
      IOException {
    PushOneCommit push = pushFactory.create(db, admin.getIdent());
    return push.to(git, "refs/for/master");
  }

  private static final List<Character> RANDOM =
      Chars.asList(new char[]{'a','b','c','d','e','f','g','h'});
  protected PushOneCommit.Result amendChange(String changeId)
      throws GitAPIException, IOException {
    Collections.shuffle(RANDOM);
    PushOneCommit push =
        pushFactory.create(db, admin.getIdent(), PushOneCommit.SUBJECT,
            PushOneCommit.FILE_NAME, new String(Chars.toArray(RANDOM)), changeId);
    return push.to(git, "refs/for/master");
  }

  protected ChangeJson.ChangeInfo getChange(String changeId, ListChangesOption... options)
      throws IOException {
    return getChange(adminSession, changeId, options);
  }

  protected ChangeJson.ChangeInfo getChange(RestSession session, String changeId,
      ListChangesOption... options) throws IOException {
    String q = options.length > 0 ? "?o=" + Joiner.on("&o=").join(options) : "";
    RestResponse r = session.get("/changes/" + changeId + q);
    assertEquals(HttpStatus.SC_OK, r.getStatusCode());
    return newGson().fromJson(r.getReader(), ChangeJson.ChangeInfo.class);
  }

  protected ChangeInfo info(String id)
      throws RestApiException {
    return gApi.changes().id(id).info();
  }

  protected ChangeInfo get(String id)
      throws RestApiException {
    return gApi.changes().id(id).get();
  }

  protected ChangeInfo get(String id, ListChangesOption... options)
      throws RestApiException {
    EnumSet<ListChangesOption> s = EnumSet.noneOf(ListChangesOption.class);
    s.addAll(Arrays.asList(options));
    return gApi.changes().id(id).get(s);
  }

  protected List<ChangeInfo> query(String q) throws RestApiException {
    return gApi.changes().query(q).get();
  }

  private Context newRequestContext(TestAccount account) {
    return atrScope.newContext(reviewDbProvider, new SshSession(server, admin),
        identifiedUserFactory.create(Providers.of(db), account.getId()));
  }

  protected Context setApiUser(TestAccount account) {
    return atrScope.set(newRequestContext(account));
  }

  protected static Gson newGson() {
    return OutputFormat.JSON_COMPACT.newGson();
  }

  protected RevisionApi revision(PushOneCommit.Result r) throws Exception {
    return gApi.changes()
        .id(r.getChangeId())
        .current();
  }
}
