// Copyright (C) 2016 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.server.submit;

import static com.google.common.base.Preconditions.checkState;
import static java.util.Objects.requireNonNull;

import com.google.common.collect.Maps;
import com.google.gerrit.reviewdb.client.Branch;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.change.NotifyResolver;
import com.google.gerrit.server.git.CodeReviewCommit;
import com.google.gerrit.server.git.CodeReviewCommit.CodeReviewRevWalk;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.MergeTip;
import com.google.gerrit.server.git.validators.OnSubmitValidators;
import com.google.gerrit.server.project.NoSuchProjectException;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectState;
import com.google.gerrit.server.update.BatchUpdate;
import com.google.inject.Inject;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevFlag;
import org.eclipse.jgit.revwalk.RevSort;

/**
 * This is a helper class for MergeOp and not intended for general use.
 *
 * <p>Some database backends require to open a repository just once within a transaction of a
 * submission, this caches open repositories to satisfy that requirement.
 */
public class MergeOpRepoManager implements AutoCloseable {
  public class OpenRepo {
    final Repository repo;
    final CodeReviewRevWalk rw;
    final RevFlag canMergeFlag;
    final ObjectInserter ins;

    final ProjectState project;
    BatchUpdate update;

    private final ObjectReader reader;
    private final Map<Branch.NameKey, OpenBranch> branches;

    private OpenRepo(Repository repo, ProjectState project) {
      this.repo = repo;
      this.project = project;
      ins = repo.newObjectInserter();
      reader = ins.newReader();
      rw = CodeReviewCommit.newRevWalk(reader);
      rw.sort(RevSort.TOPO);
      rw.sort(RevSort.COMMIT_TIME_DESC, true);
      rw.setRetainBody(false);
      canMergeFlag = rw.newFlag("CAN_MERGE");
      rw.retainOnReset(canMergeFlag);

      branches = Maps.newHashMapWithExpectedSize(1);
    }

    OpenBranch getBranch(Branch.NameKey branch) throws IntegrationException {
      OpenBranch ob = branches.get(branch);
      if (ob == null) {
        ob = new OpenBranch(this, branch);
        branches.put(branch, ob);
      }
      return ob;
    }

    public Repository getRepo() {
      return repo;
    }

    Project.NameKey getProjectName() {
      return project.getNameKey();
    }

    public CodeReviewRevWalk getCodeReviewRevWalk() {
      return rw;
    }

    public BatchUpdate getUpdate() {
      checkState(caller != null, "call setContext before getUpdate");
      if (update == null) {
        update =
            batchUpdateFactory
                .create(getProjectName(), caller, ts)
                .setRepository(repo, rw, ins)
                .setNotify(notify)
                .setOnSubmitValidators(onSubmitValidatorsFactory.create());
      }
      return update;
    }

    private void close() {
      if (update != null) {
        update.close();
      }
      rw.close();
      reader.close();
      ins.close();
      repo.close();
    }
  }

  public static class OpenBranch {
    final RefUpdate update;
    final CodeReviewCommit oldTip;
    MergeTip mergeTip;

    OpenBranch(OpenRepo or, Branch.NameKey name) throws IntegrationException {
      try {
        update = or.repo.updateRef(name.get());
        if (update.getOldObjectId() != null) {
          oldTip = or.rw.parseCommit(update.getOldObjectId());
        } else if (Objects.equals(or.repo.getFullBranch(), name.get())
            || Objects.equals(RefNames.REFS_CONFIG, name.get())) {
          oldTip = null;
          update.setExpectedOldObjectId(ObjectId.zeroId());
        } else {
          throw new IntegrationException(
              "The destination branch " + name + " does not exist anymore.");
        }
      } catch (IOException e) {
        throw new IntegrationException("Cannot open branch " + name, e);
      }
    }
  }

  private final Map<Project.NameKey, OpenRepo> openRepos;
  private final BatchUpdate.Factory batchUpdateFactory;
  private final OnSubmitValidators.Factory onSubmitValidatorsFactory;
  private final GitRepositoryManager repoManager;
  private final ProjectCache projectCache;

  private Timestamp ts;
  private IdentifiedUser caller;
  private NotifyResolver.Result notify;

  @Inject
  MergeOpRepoManager(
      GitRepositoryManager repoManager,
      ProjectCache projectCache,
      BatchUpdate.Factory batchUpdateFactory,
      OnSubmitValidators.Factory onSubmitValidatorsFactory) {
    this.repoManager = repoManager;
    this.projectCache = projectCache;
    this.batchUpdateFactory = batchUpdateFactory;
    this.onSubmitValidatorsFactory = onSubmitValidatorsFactory;

    openRepos = new HashMap<>();
  }

  public void setContext(Timestamp ts, IdentifiedUser caller, NotifyResolver.Result notify) {
    this.ts = requireNonNull(ts);
    this.caller = requireNonNull(caller);
    this.notify = requireNonNull(notify);
  }

  public OpenRepo getRepo(Project.NameKey project) throws NoSuchProjectException, IOException {
    if (openRepos.containsKey(project)) {
      return openRepos.get(project);
    }

    ProjectState projectState = projectCache.get(project);
    if (projectState == null) {
      throw new NoSuchProjectException(project);
    }
    try {
      OpenRepo or = new OpenRepo(repoManager.openRepository(project), projectState);
      openRepos.put(project, or);
      return or;
    } catch (RepositoryNotFoundException e) {
      throw new NoSuchProjectException(project, e);
    }
  }

  public List<BatchUpdate> batchUpdates(Collection<Project.NameKey> projects)
      throws NoSuchProjectException, IOException {
    List<BatchUpdate> updates = new ArrayList<>(projects.size());
    for (Project.NameKey project : projects) {
      updates.add(getRepo(project).getUpdate().setNotify(notify).setRefLogMessage("merged"));
    }
    return updates;
  }

  @Override
  public void close() {
    for (OpenRepo repo : openRepos.values()) {
      repo.close();
    }
    openRepos.clear();
  }
}
