// Copyright 2015 The Bazel Authors. All rights reserved.
//
// 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.devtools.build.lib.packages.util;

import com.google.common.base.Preconditions;
import com.google.devtools.build.lib.testutil.BlazeTestUtils;
import com.google.devtools.build.lib.testutil.TestConstants;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.util.FileSystems;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import javax.annotation.Nullable;

/**
 * Configuration for the mock client setup that we use for testing.
 */
public final class MockToolsConfig {

  private final Path rootDirectory;
  private final boolean realFileSystem;

  // Allow the injection of the runfiles directory where actual tools are found.
  // TestUtil.getRunfilesDir() caches the value of the "TEST_SRCDIR" system property, which makes
  // it impossible to change if it doesn't get set early in test configuration setup.
  private final Path runfilesDirectory;

  public MockToolsConfig(Path rootDirectory) {
    this(rootDirectory, false, null);
  }

  public MockToolsConfig(Path rootDirectory, boolean realFileSystem) {
    this(rootDirectory, realFileSystem, null);
  }

  public MockToolsConfig(
      Path rootDirectory, boolean realFileSystem, @Nullable Path runfilesDirectoryOpt) {
    this.rootDirectory = rootDirectory;
    this.realFileSystem = realFileSystem;
    if (!realFileSystem) {
      this.runfilesDirectory = null;
    } else if (runfilesDirectoryOpt == null) {
      // Turning the absolute path string from runfilesDir into a Path object.
      this.runfilesDirectory = rootDirectory.getRelative(BlazeTestUtils.runfilesDir());
    } else {
      this.runfilesDirectory = runfilesDirectoryOpt;
    }
  }

  public boolean isRealFileSystem() {
    return realFileSystem;
  }

  public Path getPath(String relativePath) {
    Preconditions.checkState(!relativePath.startsWith("/"), relativePath);
    return rootDirectory.getRelative(relativePath);
  }

  public Path create(String relativePath, String... lines) throws IOException {
    Path path = getPath(relativePath);
    if (!path.exists()) {
      FileSystemUtils.writeIsoLatin1(path, lines);
    } else if (lines.length > 0) {
      String existingContent = new String(FileSystemUtils.readContentAsLatin1(path));

      StringBuilder newContent = new StringBuilder();
      for (String line : lines) {
        newContent.append(line);
        newContent.append(System.lineSeparator());
      }

      if (!newContent.toString().trim().equals(existingContent.trim())) {
        throw new IOException(
            "Conflict: '"
                + relativePath
                + "':\n'"
                + newContent
                + "'\n vs \n'"
                + existingContent
                + "'");
      }
    }
    return path;
  }

  public Path overwrite(String relativePath, String... lines) throws IOException {
    Path path = getPath(relativePath);
    if (path.exists()) {
      path.deleteTree();
    }
    return create(relativePath, lines);
  }

  public Path append(String relativePath, String... lines) throws IOException {
    Path path = getPath(relativePath);
    if (!path.exists()) {
      return create(relativePath, lines);
    }

    FileSystemUtils.appendIsoLatin1(path, lines);
    return path;
  }

  /**
   * Links a tool into the workspace by creating a symbolic link to a real file. The target location
   * in the workspace uses the same relative path as the given path to the tool in the runfiles
   * tree. Use this if you do not need to rename or relocate the file, i.e., if the location in the
   * workspace and the runfiles tree matches. Otherwise use {@link #linkTool(String, String)}.
   *
   * @param relativePath the relative path within the runfiles tree of the current test
   * @throws IOException
   */
  public void linkTool(String relativePath) throws IOException {
    Preconditions.checkState(realFileSystem);
    linkTool(relativePath, relativePath);
  }

  public void copyTool(String relativePath) throws IOException {
    Path runfiles = FileSystems.getNativeFileSystem().getPath(BlazeTestUtils.runfilesDir());
    Path source = runfiles.getRelative(TestConstants.WORKSPACE_NAME).getRelative(relativePath);
    create(relativePath, FileSystemUtils.readContent(source, StandardCharsets.ISO_8859_1));
  }

  /**
   * Links a tool into the workspace by creating a symbolic link to a real file.
   *
   * @param relativePath the relative path within the runfiles tree of the current test
   * @param dest the relative path in the mock client
   * @throws IOException
   */
  public void linkTool(String relativePath, String dest) throws IOException {
    Preconditions.checkState(realFileSystem);
    Path target = runfilesDirectory.getRelative(TestConstants.WORKSPACE_NAME + "/" + relativePath);
    if (!target.exists()) {
      // In some cases we run tests in a special client with a ../READONLY/ path where we may also
      // find the runfiles. Try that, too.
      Path readOnlyClientPath =
          getPath("../READONLY/" + TestConstants.WORKSPACE_NAME + "/" + relativePath);
      if (!readOnlyClientPath.exists()) {
        throw new IOException("target does not exist " + target);
      } else {
        target = readOnlyClientPath;
      }
    }
    Path path = getPath(dest);
    FileSystemUtils.createDirectoryAndParents(path.getParentDirectory());
    path.delete();
    path.createSymbolicLink(target);
  }

  /**
   * Convenience method to link multiple tools. Same as calling {@link #linkTool(String)} for each
   * parameter.
   */
  public void linkTools(String... tools) throws IOException {
    for (String tool : tools) {
      linkTool(tool);
    }
  }
}
