/*
 *  The MIT License
 *
 *  Copyright 2015 Sony Mobile Communications AB. All rights reserved.
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in
 *  all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 *  THE SOFTWARE.
 */
package com.googlesource.gerrit.plugins.refprotection;

import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.server.config.PluginConfigFactory;
import com.google.gerrit.server.data.AccountAttribute;
import com.google.gerrit.server.data.RefUpdateAttribute;
import com.google.gerrit.server.events.RefUpdatedEvent;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.project.CreateBranch;
import com.google.gerrit.server.project.ProjectResource;
import com.google.inject.Inject;

import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
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.RefUpdate;
import org.eclipse.jgit.lib.RefUpdate.Result;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.TagBuilder;
import org.eclipse.jgit.revwalk.RevTag;
import org.eclipse.jgit.revwalk.RevWalk;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static org.eclipse.jgit.lib.Constants.R_HEADS;
import static org.eclipse.jgit.lib.Constants.R_REFS;
import static org.eclipse.jgit.lib.Constants.R_TAGS;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class BackupRef {
  public static final String R_BACKUPS = R_REFS + "backups/";
  private static final Logger log =
      LoggerFactory.getLogger(BackupRef.class);
  private final CreateBranch.Factory createBranchFactory;
  @Inject private static PluginConfigFactory cfg;
  @Inject private static GitRepositoryManager repoManager;
  @Inject @PluginName private static String pluginName;

  @Inject
  BackupRef(CreateBranch.Factory createBranchFactory) {
    this.createBranchFactory = createBranchFactory;
  }

  public void createBackup(RefUpdatedEvent event, ProjectResource project) {
    String refName = event.getRefName();

    try (Repository git = repoManager.openRepository(project.getNameKey())) {
      String backupRef = get(project, refName);

      // No-op if the backup branch name is same as the original
      if (backupRef.equals(refName)) {
        return;
      }

      try (RevWalk revWalk = new RevWalk(git)) {
        RefUpdateAttribute refUpdate = event.refUpdate.get();
        if (cfg.getFromGerritConfig(pluginName).getBoolean("createTag",
            false)) {
          TagBuilder tag = new TagBuilder();
          AccountAttribute submitter = event.submitter.get();
          tag.setTagger(
              new PersonIdent(submitter.name, submitter.email));
          tag.setObjectId(revWalk
              .parseCommit(ObjectId.fromString(refUpdate.oldRev)));
          String update = "Non-fast-forward update to";
          if (refUpdate.newRev.equals(ObjectId.zeroId().getName())) {
            update = "Deleted";
          }
          String type = "branch";
          String fullMessage = "";
          if (refUpdate.refName.startsWith(R_TAGS)) {
            type = "tag";
            try {
              RevTag origTag =
                  revWalk.parseTag(ObjectId.fromString(refUpdate.oldRev));
              SimpleDateFormat format = new SimpleDateFormat("EEE MMM d HH:mm:ss yyyy ZZZZ");
              PersonIdent taggerIdent = origTag.getTaggerIdent();
              String tagger =
                  String.format("Tagger: %s <%s>\nDate:   %s",
                      taggerIdent.getName(), taggerIdent.getEmailAddress(),
                      format.format(taggerIdent.getWhen()));
              fullMessage = "\n\nOriginal tag:\n" + tagger + "\n\n" + origTag.getFullMessage();
            } catch (MissingObjectException e) {
              log.warn("Original tag does not exist", e);
            } catch (IncorrectObjectTypeException e) {
              log.warn("Original tag was not a tag", e);
            } catch (IOException e) {
              log.warn("Unable to read original tag details", e);
            }
          }
          tag.setMessage(update + " " + type + " " + refUpdate.refName + fullMessage);
          tag.setTag(backupRef);

          ObjectInserter inserter = git.newObjectInserter();
          ObjectId tagId = inserter.insert(tag);
          inserter.flush();
          RefUpdate tagRef = git.updateRef(tag.getTag());
          tagRef.setNewObjectId(tagId);
          tagRef.setRefLogMessage("tagged deleted branch/tag " + tag.getTag(),
              false);
          tagRef.setForceUpdate(false);
          Result result = tagRef.update();
          switch (result) {
            case NEW:
            case FORCED:
              log.debug("Successfully created backup tag");
              break;

            case LOCK_FAILURE:
              log.error("Failed to lock repository while creating backup tag");
              break;

            case REJECTED:
              log.error("Tag already exists while creating backup tag");
              break;

            default:
              log.error("Unknown error while creating backup tag");
          }
        } else {
          CreateBranch.Input input = new CreateBranch.Input();
          input.ref = backupRef;
          // We need to parse the commit to ensure if it's a tag, we get the
          // commit the tag points to!
          input.revision = ObjectId.toString(
              revWalk.parseCommit(ObjectId.fromString(refUpdate.oldRev))
                  .getId());

          try {
            createBranchFactory.create(backupRef).apply(project, input);
          } catch (BadRequestException | AuthException
              | ResourceConflictException | IOException e) {
            log.error(e.getMessage(), e);
          }
        }
      }
    } catch (RepositoryNotFoundException e) {
      log.error("Repository does not exist", e);
    } catch (IOException e) {
      log.error("Could not open repository", e);
    }
  }

  static String get(ProjectResource project, String refName) {
    if (cfg.getFromGerritConfig(pluginName).getBoolean("useTimestamp", true)) {
      return getTimestampBranch(refName);
    }
    else {
      return getSequentialBranch(project, refName);
    }
  }

  static String getTimestampBranch(String refName) {
    if (refName.startsWith(R_HEADS) || refName.startsWith(R_TAGS)) {
      return String.format("%s-%s",
          R_BACKUPS + refName.replaceFirst(R_REFS, ""),
          new SimpleDateFormat("YYYYMMdd-HHmmss").format(new Date()));
    }

    return refName;
  }

  private static String getSequentialBranch(ProjectResource project, String branchName) {
    Integer rev = 1;
    String deletedName = branchName.replaceFirst(R_REFS, "");
    try (Repository git = repoManager.openRepository(project.getNameKey())) {
      for (Ref ref : git.getAllRefs().values()) {
        String name = ref.getName();
        if (name.startsWith(R_BACKUPS + deletedName + "/")) {
          Integer thisNum =
              Integer.parseInt(name.substring(name.lastIndexOf('/') + 1));
          if (thisNum >= rev) {
            rev = thisNum + 1;
          }
        }
      }
    } catch (RepositoryNotFoundException e) {
      log.error("Repository does not exist", e);
    } catch (IOException e) {
      log.error("Could not determine latest revision of deleted branch", e);
    }

    return R_BACKUPS + deletedName + "/" + rev;
  }
}
