// 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.googlesource.gerrit.plugins.serviceuser;

import static com.googlesource.gerrit.plugins.serviceuser.CreateServiceUser.KEY_CREATED_BY;
import static com.googlesource.gerrit.plugins.serviceuser.CreateServiceUser.KEY_OWNER;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.eclipse.jgit.lib.Constants.OBJ_COMMIT;

import com.google.gerrit.extensions.common.AccountInfo;
import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.config.AnonymousCowardName;
import com.google.gerrit.server.git.NotesBranchUtil;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import com.googlesource.gerrit.plugins.serviceuser.GetServiceUser.ServiceUserInfo;
import java.io.IOException;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.notes.NoteMap;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevObject;
import org.eclipse.jgit.revwalk.RevWalk;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

class CreateServiceUserNotes {
  private static final Logger log = LoggerFactory.getLogger(CreateServiceUserNotes.class);

  interface Factory {
    CreateServiceUserNotes create(Project.NameKey project, Repository git);
  }

  private static final String REFS_NOTES_SERVICEUSER = "refs/notes/serviceuser";

  private final PersonIdent gerritServerIdent;
  private final NotesBranchUtil.Factory notesBranchUtilFactory;
  private final ServiceUserResolver serviceUserResolver;
  private final @AnonymousCowardName String anonymousCowardName;
  private final Project.NameKey project;
  private final Repository git;

  private ObjectInserter inserter;
  private NoteMap serviceUserNotes;
  private StringBuilder message;

  @Inject
  CreateServiceUserNotes(
      @GerritPersonIdent PersonIdent gerritIdent,
      NotesBranchUtil.Factory notesBranchUtilFactory,
      ServiceUserResolver serviceUserResolver,
      @AnonymousCowardName String anonymousCowardName,
      @Assisted Project.NameKey project,
      @Assisted Repository git) {
    this.gerritServerIdent = gerritIdent;
    this.notesBranchUtilFactory = notesBranchUtilFactory;
    this.serviceUserResolver = serviceUserResolver;
    this.anonymousCowardName = anonymousCowardName;
    this.project = project;
    this.git = git;
  }

  void createNotes(String branch, ObjectId oldObjectId, ObjectId newObjectId)
      throws IOException, OrmException, ConfigInvalidException, PermissionBackendException,
          RestApiException {
    if (ObjectId.zeroId().equals(newObjectId)) {
      return;
    }

    try (RevWalk rw = new RevWalk(git)) {
      try {
        RevObject obj = rw.peel(rw.parseAny(newObjectId));
        if (obj.getType() != OBJ_COMMIT) {
          return;
        }
        RevCommit n = (RevCommit) obj;
        rw.markStart(n);
        if (n.getParentCount() == 1 && n.getParent(0).equals(oldObjectId)) {
          rw.markUninteresting(rw.parseCommit(oldObjectId));
        } else {
          markUninteresting(git, branch, rw, oldObjectId);
        }
      } catch (Exception e) {
        log.error(e.getMessage(), e);
        return;
      }

      for (RevCommit c : rw) {
        ServiceUserInfo serviceUser = serviceUserResolver.getAsServiceUser(c.getCommitterIdent());
        if (serviceUser != null) {
          ObjectId content = createNoteContent(branch, serviceUser);
          getNotes().set(c, content);
          getMessage().append("* ").append(c.getShortMessage()).append("\n");
        }
      }
    }
  }

  void commitNotes() throws IOException {
    try {
      if (serviceUserNotes == null) {
        return;
      }

      message.insert(0, "Update notes for service user commits\n\n");
      notesBranchUtilFactory
          .create(project, git, inserter)
          .commitAllNotes(
              serviceUserNotes, REFS_NOTES_SERVICEUSER, gerritServerIdent, message.toString());
    } finally {
      if (inserter != null) {
        inserter.close();
      }
    }
  }

  private void markUninteresting(Repository git, String branch, RevWalk rw, ObjectId oldObjectId) {
    for (Ref r : git.getAllRefs().values()) {
      try {
        if (r.getName().equals(branch)) {
          if (!ObjectId.zeroId().equals(oldObjectId)) {
            // For the updated branch the oldObjectId is the tip of uninteresting
            // commit history
            rw.markUninteresting(rw.parseCommit(oldObjectId));
          }
        } else if (r.getName().startsWith(Constants.R_HEADS)
            || r.getName().startsWith(Constants.R_TAGS)) {
          rw.markUninteresting(rw.parseCommit(r.getObjectId()));
        }
      } catch (IOException e) {
        // skip if not parseable as a commit
      }
    }
  }

  private ObjectId createNoteContent(String branch, ServiceUserInfo serviceUser)
      throws IOException, OrmException, MethodNotAllowedException, PermissionBackendException {
    return getInserter()
        .insert(Constants.OBJ_BLOB, createServiceUserNote(branch, serviceUser).getBytes(UTF_8));
  }

  private String createServiceUserNote(String branch, ServiceUserInfo serviceUser)
      throws OrmException, MethodNotAllowedException, PermissionBackendException {
    HeaderFormatter fmt = new HeaderFormatter(gerritServerIdent.getTimeZone(), anonymousCowardName);
    fmt.appendDate();
    fmt.append("Project", project.get());
    fmt.append("Branch", branch);
    fmt.appendUser(KEY_CREATED_BY, serviceUser.createdBy);
    for (AccountInfo owner : serviceUserResolver.listActiveOwners(serviceUser)) {
      fmt.appendUser(KEY_OWNER, owner);
    }
    return fmt.toString();
  }

  private ObjectInserter getInserter() {
    if (inserter == null) {
      inserter = git.newObjectInserter();
    }
    return inserter;
  }

  private NoteMap getNotes() {
    if (serviceUserNotes == null) {
      serviceUserNotes = NoteMap.newEmptyMap();
    }
    return serviceUserNotes;
  }

  private StringBuilder getMessage() {
    if (message == null) {
      message = new StringBuilder();
    }
    return message;
  }
}
