// 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.util;

import com.google.common.flogger.FluentLogger;
import com.google.gerrit.reviewdb.client.Branch;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.AccountCache;
import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.TagCache;
import com.google.gerrit.server.project.NoSuchProjectException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.io.IOException;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.Repository;

public class RefUpdater {
  private static final FluentLogger log = FluentLogger.forEnclosingClass();

  public class Args {
    public final Branch.NameKey branch;
    public ObjectId expectedOldObjectId;
    public ObjectId newObjectId;
    public boolean isForceUpdate;
    public PersonIdent refLogIdent;
    public String refLogMessage;

    public Args(Branch.NameKey branch) {
      this.branch = branch;
      CurrentUser user = userProvider.get();
      if (user instanceof IdentifiedUser) {
        refLogIdent = ((IdentifiedUser) user).newRefLogIdent();
      } else {
        refLogIdent = gerrit;
      }
    }
  }

  protected final Provider<CurrentUser> userProvider;
  protected final @GerritPersonIdent PersonIdent gerrit;
  protected final GitRepositoryManager repoManager;
  protected final GitReferenceUpdated gitRefUpdated;
  protected final TagCache tagCache;
  protected final AccountCache accountCache;

  @Inject
  RefUpdater(
      AccountCache accountCache,
      Provider<CurrentUser> userProvider,
      @GerritPersonIdent PersonIdent gerrit,
      GitRepositoryManager repoManager,
      TagCache tagCache,
      GitReferenceUpdated gitRefUpdated) {
    this.accountCache = accountCache;
    this.userProvider = userProvider;
    this.gerrit = gerrit;
    this.repoManager = repoManager;
    this.tagCache = tagCache;
    this.gitRefUpdated = gitRefUpdated;
  }

  public void update(Branch.NameKey branch, ObjectId oldRefId, ObjectId newRefId)
      throws IOException, NoSuchProjectException {
    this.update(branch, oldRefId, newRefId, null);
  }

  public void update(
      Branch.NameKey branch, ObjectId oldRefId, ObjectId newRefId, String refLogMessage)
      throws IOException, NoSuchProjectException {
    Args args = new Args(branch);
    args.expectedOldObjectId = oldRefId;
    args.newObjectId = newRefId;
    args.refLogMessage = refLogMessage;
    this.update(args);
  }

  public void forceUpdate(Branch.NameKey branch, ObjectId newRefId)
      throws IOException, NoSuchProjectException {
    this.forceUpdate(branch, newRefId, null);
  }

  public void forceUpdate(Branch.NameKey branch, ObjectId newRefId, String refLogMessage)
      throws IOException, NoSuchProjectException {
    Args args = new Args(branch);
    args.newObjectId = newRefId;
    args.isForceUpdate = true;
    args.refLogMessage = refLogMessage;
    update(args);
  }

  public void delete(Branch.NameKey branch) throws IOException, NoSuchProjectException {
    Args args = new Args(branch);
    args.newObjectId = ObjectId.zeroId();
    args.isForceUpdate = true;
    update(args);
  }

  public void update(Args args) throws IOException, NoSuchProjectException {
    new Update(args).update();
  }

  protected class Update {
    protected Repository repo;
    protected Args args;
    protected RefUpdate update;
    protected Branch.NameKey branch;
    protected Project.NameKey project;
    protected boolean delete;

    protected Update(Args args) {
      this.args = args;
      branch = args.branch;
      project = branch.getParentKey();
      delete = args.newObjectId.equals(ObjectId.zeroId());
    }

    protected void update() throws IOException, NoSuchProjectException {
      try {
        repo = repoManager.openRepository(project);
        try {
          initUpdate();
          handleResult(runUpdate());
        } catch (IOException err) {
          log.atSevere().withCause(err).log(
              "RefUpdate failed: branch not updated: %s", branch.get());
          throw err;
        } finally {
          repo.close();
          repo = null;
        }
      } catch (RepositoryNotFoundException e) {
        throw new NoSuchProjectException(project);
      }
    }

    protected void initUpdate() throws IOException {
      update = repo.updateRef(branch.get());
      update.setExpectedOldObjectId(args.expectedOldObjectId);
      update.setNewObjectId(args.newObjectId);
      update.setRefLogIdent(args.refLogIdent);
      update.setForceUpdate(args.isForceUpdate);
      if (args.refLogMessage != null) {
        update.setRefLogMessage(args.refLogMessage, true);
      }
    }

    protected RefUpdate.Result runUpdate() throws IOException {
      if (delete) {
        return update.delete();
      }
      return update.update();
    }

    protected void handleResult(RefUpdate.Result result) throws IOException {
      switch (result) {
        case FORCED:
          if (!delete && !args.isForceUpdate) {
            throw new IOException(result.name());
          }
          // $FALL-THROUGH$
        case FAST_FORWARD:
        case NEW:
        case NO_CHANGE:
          onUpdated(update, args);
          break;
        case IO_FAILURE:
        case LOCK_FAILURE:
        case NOT_ATTEMPTED:
        case REJECTED:
        case REJECTED_CURRENT_BRANCH:
        case REJECTED_MISSING_OBJECT:
        case REJECTED_OTHER_REASON:
        case RENAMED:
        default:
          throw new IOException(result.name());
      }
    }

    protected void onUpdated(RefUpdate update, Args args) {
      if (update.getResult() == RefUpdate.Result.FAST_FORWARD) {
        tagCache.updateFastForward(
            project, update.getName(), update.getOldObjectId(), args.newObjectId);
      }
      if (userProvider.get().isIdentifiedUser()) {
        AccountState accountState = accountCache.get(userProvider.get().getAccountId()).get();
        gitRefUpdated.fire(project, update, accountState);
      }
    }
  }
}
