// Copyright (C) 2015 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.google.gerrit.acceptance;

import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.common.base.MoreObjects;
import com.google.common.base.Strings;
import com.google.gerrit.server.config.SitePaths;

import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.util.FS;
import org.junit.runner.Description;

import java.io.IOException;
import java.io.InputStream;
import java.lang.ProcessBuilder.Redirect;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public abstract class PluginDaemonTest extends AbstractDaemonTest {

  private static final String BUCKLC = "buck";
  private static final String BUCKOUT = "buck-out";

  private Path gen;
  private Path testSite;
  private Path pluginRoot;
  private Path pluginsSitePath;
  private Path pluginSubPath;
  private Path pluginSource;
  private String pluginName;
  private boolean standalone;

  @Override
  protected void beforeTest(Description description) throws Exception {
    locatePaths();
    retrievePluginName();
    buildPluginJar();
    createTestSiteDirs();
    copyJarToTestSite();
    super.beforeTest(description);
  }

  protected void setPluginConfigString(String name, String value)
      throws IOException, ConfigInvalidException {
    SitePaths sitePath = new SitePaths(testSite);
    FileBasedConfig cfg = getGerritConfigFile(sitePath);
    cfg.load();
    cfg.setString("plugin", pluginName, name, value);
    cfg.save();
  }

  private FileBasedConfig getGerritConfigFile(SitePaths sitePath)
      throws IOException {
    FileBasedConfig cfg =
        new FileBasedConfig(sitePath.gerrit_config.toFile(), FS.DETECTED);
    if (!cfg.getFile().exists()) {
      Path etc_path = Files.createDirectories(sitePath.etc_dir);
      Files.createFile(etc_path.resolve("gerrit.config"));
    }
    return cfg;
  }

  private void locatePaths() {
    URL pluginClassesUrl =
        getClass().getProtectionDomain().getCodeSource().getLocation();
    Path basePath = Paths.get(pluginClassesUrl.getPath()).getParent();

    int idx = 0;
    int buckOutIdx = 0;
    int pluginsIdx = 0;
    for (Path subPath : basePath) {
      if (subPath.endsWith("plugins")) {
        pluginsIdx = idx;
      }
      if (subPath.endsWith(BUCKOUT)) {
        buckOutIdx = idx;
      }
      idx++;
    }
    standalone = checkStandalone(basePath);
    pluginRoot = basePath.getRoot().resolve(basePath.subpath(0, buckOutIdx));
    gen = pluginRoot.resolve(BUCKOUT).resolve("gen");

    if (standalone) {
      pluginSource = pluginRoot;
    } else {
      pluginSubPath = basePath.subpath(pluginsIdx, pluginsIdx + 2);
      pluginSource = pluginRoot.resolve(pluginSubPath);
    }
  }

  private boolean checkStandalone(Path basePath) {
    String pathCharStringOrNone = "[a-zA-Z0-9._-]*?";
    Pattern pattern = Pattern.compile(pathCharStringOrNone + "gerrit" +
        pathCharStringOrNone);
    Path partialPath = basePath;
    for (int i = basePath.getNameCount(); i > 0; i--) {
      int count = partialPath.getNameCount();
      if (count > 1) {
        String gerritDirCandidate =
            partialPath.subpath(count - 2, count - 1).toString();
        if (pattern.matcher(gerritDirCandidate).matches()) {
          if (partialPath.endsWith(gerritDirCandidate + "/" + BUCKOUT)) {
            return false;
          }
        }
      }
      partialPath = partialPath.getParent();
    }
    return true;
  }

  private void retrievePluginName() throws IOException {
    Path buckFile = pluginSource.resolve("BUCK");
    byte[] bytes = Files.readAllBytes(buckFile);
    String buckContent =
        new String(bytes, UTF_8).replaceAll("\\s+", "");
    Matcher matcher =
        Pattern.compile("gerrit_plugin\\(name='(.*?)'").matcher(buckContent);
    if (matcher.find()) {
      pluginName = matcher.group(1);
    }
    if (Strings.isNullOrEmpty(pluginName)) {
      if (standalone) {
        pluginName = pluginRoot.getFileName().toString();
      } else {
        pluginName = pluginSubPath.getFileName().toString();
      }
    }
  }

  private void buildPluginJar() throws IOException, InterruptedException {
    Properties properties = loadBuckProperties();
    String buck =
        MoreObjects.firstNonNull(properties.getProperty(BUCKLC), BUCKLC);
    String target;
    if (standalone) {
      target = "//:" + pluginName;
    } else {
      target = pluginSubPath.toString();
    }

    ProcessBuilder processBuilder =
        new ProcessBuilder(buck, "build", target).directory(pluginRoot.toFile())
            .redirectErrorStream(true);
    // otherwise plugin jar creation fails:
    processBuilder.environment().put("NO_BUCKD", "1");

    Path forceJar = pluginSource.resolve("src/main/java/ForceJarIfMissing.java");
    // if exists after cancelled test:
    Files.deleteIfExists(forceJar);

    Files.createFile(forceJar);
    testSite = tempSiteDir.getRoot().toPath();

    // otherwise process often hangs:
    Path log = testSite.resolve("log");
    processBuilder.redirectErrorStream(true);
    processBuilder.redirectOutput(Redirect.appendTo(log.toFile()));

    try {
      processBuilder.start().waitFor();
    } finally {
      Files.delete(forceJar);
      // otherwise jar not made next time if missing again:
      processBuilder.start().waitFor();
    }
  }

  private Properties loadBuckProperties() throws IOException {
    Properties properties = new Properties();
    Path propertiesPath = gen.resolve(Paths.get("tools/buck/buck.properties"));
    if (Files.exists(propertiesPath)) {
      try (InputStream in = Files.newInputStream(propertiesPath)) {
        properties.load(in);
      }
    }
    return properties;
  }

  private void createTestSiteDirs() throws IOException {
    SitePaths sitePath = new SitePaths(testSite);
    pluginsSitePath = Files.createDirectories(sitePath.plugins_dir);
    Files.createDirectories(sitePath.tmp_dir);
    Files.createDirectories(sitePath.etc_dir);
  }

  private void copyJarToTestSite() throws IOException {
    Path pluginOut;
    if (standalone) {
      pluginOut = gen;
    } else {
      pluginOut = gen.resolve(pluginSubPath);
    }
    Path jar = pluginOut.resolve(pluginName + ".jar");
    Path dest = pluginsSitePath.resolve(jar.getFileName());
    Files.copy(jar, dest, StandardCopyOption.REPLACE_EXISTING);
  }
}
