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

import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.googlesource.gerrit.plugins.renameproject.monitor.ProgressMonitor;
import java.io.File;
import java.io.IOException;
import java.nio.file.FileVisitOption;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.Comparator;
import java.util.Optional;
import java.util.stream.Stream;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.RepositoryCache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Singleton
public class FilesystemRenameHandler {
  private static final Logger log = LoggerFactory.getLogger(FilesystemRenameHandler.class);

  private final GitRepositoryManager repoManager;

  @Inject
  public FilesystemRenameHandler(GitRepositoryManager repoManager) {
    this.repoManager = repoManager;
  }

  public void rename(
      Project.NameKey oldProjectKey, Project.NameKey newProjectKey, Optional<ProgressMonitor> opm)
      throws IOException, RepositoryNotFoundException {
    Repository repository = repoManager.openRepository(oldProjectKey);
    File repoFile = repository.getDirectory();
    RepositoryCache.close(repository);
    opm.ifPresent(pm -> pm.beginTask("Renaming git repository"));
    renameGitRepository(repoFile, newProjectKey, oldProjectKey);
  }

  private void renameGitRepository(
      File source, Project.NameKey newProjectKey, Project.NameKey oldProjectKey)
      throws IOException {
    log.debug("Creating the new git repo - {}", newProjectKey.get());
    try (Repository newRepo = repoManager.createRepository(newProjectKey)) {
      File target = newRepo.getDirectory();
      RepositoryCache.close(newRepo);
      // delete the created repo, we just needed the absolute path from repo manager
      recursiveDelete(target.toPath());
      log.debug(
          "Moving the content of {} to new git repo - {}",
          oldProjectKey.get(),
          newProjectKey.get());
      Files.move(source.toPath(), target.toPath(), StandardCopyOption.ATOMIC_MOVE);
    } catch (IOException e) {
      throw new IOException("Failed to move the content to new git repo.", e);
    }
  }

  private void recursiveDelete(Path oldFile) throws IOException {
    try (Stream<Path> dir = Files.walk(oldFile, FileVisitOption.FOLLOW_LINKS)) {
      dir.sorted(Comparator.reverseOrder()).map(Path::toFile).forEach(File::delete);
    } catch (IOException e) {
      log.error("Failed to delete {}", oldFile.getFileName(), e);
      throw e;
    }
  }
}
