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

import com.google.common.base.Charsets;
import com.google.common.base.Function;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.Lists;
import com.google.gerrit.server.config.PluginConfig;
import com.google.gerrit.server.git.validators.CommitValidationMessage;

import org.apache.commons.io.FileUtils;
import org.eclipse.jgit.api.AddCommand;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.RmCommand;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.dircache.DirCacheEntry;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevTree;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;

public class TestUtils {
  public static final PluginConfig EMPTY_PLUGIN_CONFIG = new PluginConfig("", new Config());

  protected static final byte[] EMPTY_CONTENT = "".getBytes(Charsets.UTF_8);

  private static final Function<CommitValidationMessage, String> MESSAGE_TRANSFORMER =
      new Function<CommitValidationMessage, String>() {
        @Override
        public String apply(CommitValidationMessage input) {
          String pre = (input.isError()) ? "ERROR: " : "MSG: ";
          return pre + input.getMessage();
        }
      };

  public static final LoadingCache<String, Pattern> PATTERN_CACHE =
      CacheBuilder.newBuilder().build(new PatternCacheModule.Loader());

  public static Repository createNewRepository(File repoFolder) throws IOException {
    Repository repository = FileRepositoryBuilder.create(new File(repoFolder, ".git"));
    repository.create();
    return repository;
  }

  public static RevCommit makeCommit(RevWalk rw, Repository repo, String message, Set<File> files)
      throws IOException, GitAPIException {
    Map<File, byte[]> tmp = new HashMap<>();
    for (File f : files) {
      tmp.put(f, null);
    }
    return makeCommit(rw, repo, message, tmp);
  }

  public static RevCommit makeCommit(
      RevWalk rw, Repository repo, String message, Map<File, byte[]> files)
      throws IOException, GitAPIException {
    try (Git git = new Git(repo)) {
      if (files != null) {
        addFiles(git, files);
      }
      return rw.parseCommit(git.commit().setMessage(message).call());
    }
  }

  private static String generateFilePattern(File f, Git git) {
    return f.getAbsolutePath()
        .replace(git.getRepository().getWorkTree().getAbsolutePath(), "")
        .substring(1);
  }

  public static void removeFiles(Git git, Set<File> files) throws GitAPIException {
    RmCommand rmc = git.rm();
    for (File f : files) {
      rmc.addFilepattern(generateFilePattern(f, git));
    }
    rmc.call();
  }

  private static void addFiles(Git git, Map<File, byte[]> files)
      throws IOException, GitAPIException {
    AddCommand ac = git.add();
    for (File f : files.keySet()) {
      if (!f.exists()) {
        FileUtils.touch(f);
      }
      if (files.get(f) != null) {
        FileUtils.writeByteArrayToFile(f, files.get(f));
      }
      ac = ac.addFilepattern(generateFilePattern(f, git));
    }
    ac.call();
  }

  public static File createEmptyFile(String name, Repository repo) {
    return new File(repo.getDirectory().getParent(), name);
  }

  public static String transformMessage(CommitValidationMessage messages) {
    return MESSAGE_TRANSFORMER.apply(messages);
  }

  public static List<String> transformMessages(List<CommitValidationMessage> messages) {
    return Lists.transform(messages, MESSAGE_TRANSFORMER);
  }

  public static DirCacheEntry[] createEmptyDirCacheEntries(
      List<String> filenames, TestRepository<Repository> repo) throws Exception {
    DirCacheEntry[] entries = new DirCacheEntry[filenames.size()];
    for (int x = 0; x < filenames.size(); x++) {
      entries[x] = createDirCacheEntry(filenames.get(x), EMPTY_CONTENT, repo);
    }
    return entries;
  }

  public static DirCacheEntry createDirCacheEntry(
      String pathname, byte[] content, TestRepository<Repository> repo) throws Exception {
    return repo.file(pathname, repo.blob(content));
  }

  public static RevCommit makeCommit(
      RevWalk rw, DirCacheEntry[] entries, TestRepository<Repository> repo) throws Exception {
    return makeCommit(rw, entries, repo, (RevCommit[]) null);
  }

  public static RevCommit makeCommit(
      RevWalk rw, DirCacheEntry[] entries, TestRepository<Repository> repo, RevCommit... parents)
      throws Exception {
    final RevTree ta = repo.tree(entries);
    RevCommit c = (parents == null) ? repo.commit(ta) : repo.commit(ta, parents);
    repo.parseBody(c);
    return rw.parseCommit(c);
  }
}
