// 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.entities.BranchNameKey;
import com.google.gerrit.entities.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 BranchNameKey branch;
    public ObjectId expectedOldObjectId;
    public ObjectId newObjectId;
    public boolean isForceUpdate;
    public PersonIdent refLogIdent;
    public String refLogMessage;

    public Args(BranchNameKey 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(BranchNameKey branch, ObjectId oldRefId, ObjectId newRefId)
      throws IOException, NoSuchProjectException {
    this.update(branch, oldRefId, newRefId, null);
  }

  public void update(
      BranchNameKey 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(BranchNameKey branch, ObjectId newRefId)
      throws IOException, NoSuchProjectException {
    this.forceUpdate(branch, newRefId, null);
  }

  public void forceUpdate(BranchNameKey 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(BranchNameKey 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 BranchNameKey branch;
    protected Project.NameKey project;
    protected boolean delete;

    protected Update(Args args) {
      this.args = args;
      branch = args.branch;
      project = branch.project();
      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.branch());
          throw err;
        } finally {
          repo.close();
          repo = null;
        }
      } catch (RepositoryNotFoundException e) {
        throw new NoSuchProjectException(project);
      }
    }

    protected void initUpdate() throws IOException {
      update = repo.updateRef(branch.branch());
      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);
      }
    }
  }
}
