// Copyright (C) 2014 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.testutil;

import static com.google.common.base.MoreObjects.firstNonNull;
import static org.easymock.EasyMock.expect;

import com.google.common.collect.Ordering;
import com.google.gerrit.common.TimeUtil;
import com.google.gerrit.extensions.config.FactoryModule;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Branch;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.PatchSetInfo;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RevId;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.notedb.AbstractChangeNotes;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.ChangeUpdate;
import com.google.gerrit.server.notedb.NotesMigration;
import com.google.gerrit.server.project.ChangeControl;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Injector;

import org.easymock.EasyMock;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;

import java.util.TimeZone;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Utility functions to create and manipulate Change, ChangeUpdate, and
 * ChangeControl objects for testing.
 */
public class TestChanges {
  private static final AtomicInteger nextChangeId = new AtomicInteger(1);

  public static Change newChange(Project.NameKey project, Account.Id userId) {
    return newChange(project, userId, nextChangeId.getAndIncrement());
  }

  public static Change newChange(Project.NameKey project, Account.Id userId,
      int id) {
    Change.Id changeId = new Change.Id(id);
    Change c = new Change(
        new Change.Key("Iabcd1234abcd1234abcd1234abcd1234abcd1234"),
        changeId,
        userId,
        new Branch.NameKey(project, "master"),
        TimeUtil.nowTs());
    incrementPatchSet(c);
    return c;
  }

  public static PatchSet newPatchSet(PatchSet.Id id, ObjectId revision,
      Account.Id userId) {
    return newPatchSet(id, revision.name(), userId);
  }

  public static PatchSet newPatchSet(PatchSet.Id id, String revision,
      Account.Id userId) {
    PatchSet ps = new PatchSet(id);
    ps.setRevision(new RevId(revision));
    ps.setUploader(userId);
    ps.setCreatedOn(TimeUtil.nowTs());
    return ps;
  }

  public static ChangeUpdate newUpdate(Injector injector,
      Change c, final CurrentUser user) throws Exception  {
    injector = injector.createChildInjector(new FactoryModule() {
      @Override
      public void configure() {
        bind(CurrentUser.class).toInstance(user);
      }
    });
    ChangeUpdate update = injector.getInstance(ChangeUpdate.Factory.class)
        .create(
            stubChangeControl(
                injector.getInstance(AbstractChangeNotes.Args.class),
                c,
                user),
            TimeUtil.nowTs(), Ordering.<String> natural());

    ChangeNotes notes = update.getNotes();
    boolean hasPatchSets = notes.getPatchSets() != null
        && !notes.getPatchSets().isEmpty();
    NotesMigration migration = injector.getInstance(NotesMigration.class);
    if (hasPatchSets || !migration.readChanges()) {
      return update;
    }

    // Change doesn't exist yet. NoteDb requires that there be a commit for the
    // first patch set, so create one.
    GitRepositoryManager repoManager =
        injector.getInstance(GitRepositoryManager.class);
    try (Repository repo = repoManager.openRepository(c.getProject())) {
      TestRepository<Repository> tr = new TestRepository<>(repo);
      PersonIdent ident = user.asIdentifiedUser()
          .newCommitterIdent(update.getWhen(), TimeZone.getDefault());
      TestRepository<Repository>.CommitBuilder cb = tr.commit()
          .author(ident)
          .committer(ident)
          .message(firstNonNull(c.getSubject(), "Test change"));
      Ref parent = repo.exactRef(c.getDest().get());
      if (parent != null) {
        cb.parent(tr.getRevWalk().parseCommit(parent.getObjectId()));
      }
      update.setBranch(c.getDest().get());
      update.setChangeId(c.getKey().get());
      update.setCommit(tr.getRevWalk(), cb.create());
      return update;
    }
  }

  private static ChangeControl stubChangeControl(
      AbstractChangeNotes.Args args,
      Change c, CurrentUser user) throws OrmException {
    ChangeControl ctl = EasyMock.createMock(ChangeControl.class);
    expect(ctl.getChange()).andStubReturn(c);
    expect(ctl.getProject()).andStubReturn(new Project(c.getProject()));
    expect(ctl.getUser()).andStubReturn(user);
    ChangeNotes notes = new ChangeNotes(args, c).load();
    expect(ctl.getNotes()).andStubReturn(notes);
    expect(ctl.getId()).andStubReturn(c.getId());
    EasyMock.replay(ctl);
    return ctl;
  }

  public static void incrementPatchSet(Change change) {
    PatchSet.Id curr = change.currentPatchSetId();
    PatchSetInfo ps = new PatchSetInfo(new PatchSet.Id(
        change.getId(), curr != null ? curr.get() + 1 : 1));
    ps.setSubject("Change subject");
    change.setCurrentPatchSet(ps);
  }
}
