// Copyright (C) 2013 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.deleteproject.fs;

import java.io.File;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.BasicFileAttributes;

import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.RepositoryCache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.extensions.events.ProjectDeletedListener;
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.config.PluginConfigFactory;
import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.project.ProjectResource;
import com.google.inject.Inject;

import com.googlesource.gerrit.plugins.deleteproject.CannotDeleteProjectException;

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

  private final File gitDir;
  private final GitRepositoryManager repoManager;
  private final DynamicSet<ProjectDeletedListener> deletedListener;
  private final PluginConfigFactory cfgFactory;
  private final String pluginName;

  @Inject
  public FilesystemDeleteHandler(GitRepositoryManager repoManager,
      SitePaths site,
      @GerritServerConfig Config cfg,
      DynamicSet<ProjectDeletedListener> deletedListener,
      PluginConfigFactory cfgFactory,
      @PluginName String pluginName) {
    gitDir = site.resolve(cfg.getString("gerrit", null, "basePath"));
    this.repoManager = repoManager;
    this.deletedListener = deletedListener;
    this.cfgFactory = cfgFactory;
    this.pluginName = pluginName;
  }

  public void delete(Project project, boolean preserveGitRepository)
      throws IOException, RepositoryNotFoundException {
    // Remove from the jgit cache
    Repository repository =
        repoManager.openRepository(project.getNameKey());
    File repoFile = repository.getDirectory();
    cleanCache(repository);
    if (!preserveGitRepository) {
      deleteGitRepository(project.getNameKey(), repoFile);
    }
  }

  public void assertCanDelete(ProjectResource rsrc, boolean preserveGitRepository)
      throws CannotDeleteProjectException {
    if (!preserveGitRepository
        && !cfgFactory.getFromGerritConfig(pluginName).getBoolean(
            "allowDeletionOfReposWithTags", true)) {
      assertHasNoTags(rsrc);
    }
  }

  private void assertHasNoTags(ProjectResource rsrc)
      throws CannotDeleteProjectException {
    try {
      Repository repo = repoManager.openRepository(rsrc.getNameKey());
      try {
        if (!repo.getRefDatabase().getRefs(Constants.R_TAGS).isEmpty()) {
          throw new CannotDeleteProjectException(
              String.format("Project %s has tags", rsrc.getName()));
        }
      } finally {
        repo.close();
      }
    } catch (IOException e) {
      throw new CannotDeleteProjectException(e);
    }
  }

  private void deleteGitRepository(final Project.NameKey project,
      final File repoFile) throws IOException {
    // Delete the repository from disk
    Path trash = moveToTrash(repoFile.toPath(), project);
    try {
      recursiveDelete(trash);
    } catch (IOException e) {
      // Only log if delete failed - repo already moved to trash.
      // Otherwise, listeners are never called.
      log.warn("Error trying to delete " + trash, e);
    }

    // Delete parent folders if they are (now) empty
    recursiveDeleteParent(repoFile.getParentFile(), gitDir);

    // Send an event that the repository was deleted
    ProjectDeletedListener.Event event = new ProjectDeletedListener.Event() {
      @Override
      public String getProjectName() {
        return project.get();
      }
    };
    for (ProjectDeletedListener l : deletedListener) {
      try {
        l.onProjectDeleted(event);
      } catch (RuntimeException e) {
        log.warn("Failure in ProjectDeletedListener", e);
      }
    }
  }

  private Path moveToTrash(Path directory, Project.NameKey nameKey)
      throws IOException {
    File trashRepo =
        new File(gitDir, nameKey.get() + "." + System.currentTimeMillis() + ".deleted");
    return Files.move(directory, trashRepo.toPath(), StandardCopyOption.ATOMIC_MOVE);
  }

  private void cleanCache(final Repository repository) {
    repository.close();
    RepositoryCache.close(repository);
  }

  /**
   * Recursively delete the specified file and all of its contents.
   *
   * @throws IOException
   */
  private void recursiveDelete(Path file) throws IOException {
    Files.walkFileTree(file, new SimpleFileVisitor<Path>() {
      @Override
      public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
          throws IOException {
        Files.delete(file);
        return FileVisitResult.CONTINUE;
      }

      @Override
      public FileVisitResult postVisitDirectory(Path dir, IOException e)
          throws IOException {
        if (e != null) {
          throw e;
        }
        Files.delete(dir);
        return FileVisitResult.CONTINUE;
      }
    });
  }

  /**
   * Recursively delete the specified file and its parent files until we hit the
   * file {@code Until} or the parent file is populated. This is used when we
   * have a tree structure such as a/b/c/d.git and a/b/e.git - if we delete
   * a/b/c/d.git, we no longer need a/b/c/.
   */
  private void recursiveDeleteParent(File file, File until) {
    if (file.equals(until)) {
      return;
    }
    if (file.listFiles().length == 0) {
      File parent = file.getParentFile();
      file.delete();
      recursiveDeleteParent(parent, until);
    }
  }
}
