// 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.pgm.init.api;

import com.google.errorprone.annotations.CanIgnoreReturnValue;
import com.google.gerrit.entities.Project;
import com.google.gerrit.server.GerritPersonIdentProvider;
import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.git.meta.VersionedMetaData;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.internal.storage.file.FileRepository;
import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.RepositoryCache.FileKey;
import org.eclipse.jgit.revwalk.RevTree;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.util.FS;

public abstract class VersionedMetaDataOnInit extends VersionedMetaData {

  protected final String project;
  private final InitFlags flags;
  private final SitePaths site;
  private final String ref;

  protected VersionedMetaDataOnInit(InitFlags flags, SitePaths site, String project, String ref) {
    this.flags = flags;
    this.site = site;
    this.project = project;
    this.ref = ref;
  }

  @Override
  protected String getRefName() {
    return ref;
  }

  @CanIgnoreReturnValue
  public VersionedMetaDataOnInit load() throws IOException, ConfigInvalidException {
    File path = getPath();
    if (path != null) {
      try (Repository repo = new FileRepository(path)) {
        load(Project.nameKey(project), repo);
      }
    }
    return this;
  }

  public void save(String message) throws IOException, ConfigInvalidException {
    save(new GerritPersonIdentProvider(flags.cfg).get(), message);
  }

  protected void save(PersonIdent ident, String msg) throws IOException, ConfigInvalidException {
    try (Repository repo = openGitRepository();
        ObjectInserter i = repo.newObjectInserter();
        ObjectReader r = repo.newObjectReader();
        RevWalk rw = new RevWalk(r)) {
      inserter = i;
      reader = r;

      RevTree srcTree = revision != null ? rw.parseTree(revision) : null;
      newTree = readTree(srcTree);

      CommitBuilder commit = new CommitBuilder();
      commit.setAuthor(ident);
      commit.setCommitter(ident);
      commit.setMessage(msg);

      if (!onSave(commit)) {
        return;
      }

      ObjectId res = newTree.writeTree(inserter);
      if (res.equals(srcTree)) {
        return;
      }
      commit.setTreeId(res);

      if (revision != null) {
        commit.addParentId(revision);
      }
      ObjectId newRevision = inserter.insert(commit);
      updateRef(repo, ident, newRevision, "commit: " + msg);
      revision = rw.parseCommit(newRevision);
    } finally {
      inserter = null;
      reader = null;
    }
  }

  private void updateRef(Repository repo, PersonIdent ident, ObjectId newRevision, String refLogMsg)
      throws IOException {
    RefUpdate ru = repo.updateRef(getRefName());
    ru.setRefLogIdent(ident);
    ru.setNewObjectId(newRevision);
    ru.setExpectedOldObjectId(revision);
    ru.setRefLogMessage(refLogMsg, false);
    RefUpdate.Result r = ru.update();
    switch (r) {
      case FAST_FORWARD:
      case NEW:
      case NO_CHANGE:
        break;
      case FORCED:
      case IO_FAILURE:
      case LOCK_FAILURE:
      case NOT_ATTEMPTED:
      case REJECTED:
      case REJECTED_CURRENT_BRANCH:
      case RENAMED:
      case REJECTED_MISSING_OBJECT:
      case REJECTED_OTHER_REASON:
      default:
        throw new IOException(
            "Failed to update " + getRefName() + " of " + project + ": " + r.name());
    }
  }

  private File getPath() {
    Path basePath = site.resolve(flags.cfg.getString("gerrit", null, "basePath"));
    if (basePath == null) {
      throw new IllegalStateException("gerrit.basePath must be configured");
    }
    return FileKey.resolve(basePath.resolve(project).toFile(), FS.DETECTED);
  }

  public Repository openGitRepository() throws IOException {
    File path = getPath();
    if (path == null) {
      throw new IOException(project + " does not exist.");
    }

    return new FileRepository(path);
  }
}
