// 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.bazel.rules.android.ndkcrosstools;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.devtools.build.lib.rules.cpp.CppConfiguration;
import com.google.devtools.build.lib.rules.cpp.CppConfiguration.Tool;
import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig.ToolPath;
import java.util.Arrays;
import java.util.List;

/**
 * Class for creating paths that are specific to the structure of the Android NDK, but which are
 * common to all crosstool toolchains.
 */
public class NdkPaths {

  /**
   * Removes the NDK repository prefix from the given path. Eg:
   * "external/%repositoryName%/ndk/a/b/c" -> "ndk/a/b/c"
   */
  public static String stripRepositoryPrefix(String path) {
    return path.split("/", 3)[2];
  }

  private final String repositoryName;
  private final String hostPlatform;
  private final ApiLevel apiLevel;
  private final Integer majorRevision;

  public NdkPaths(
      String repositoryName, String hostPlatform, ApiLevel apiLevel, Integer majorRevision) {
    this.repositoryName = repositoryName;
    this.hostPlatform = hostPlatform;
    this.apiLevel = apiLevel;
    this.majorRevision = majorRevision;
  }

  public ImmutableList<ToolPath> createToolpaths(String toolchainName, String targetPlatform,
      CppConfiguration.Tool... excludedTools) {

    ImmutableList.Builder<ToolPath> toolPaths = ImmutableList.builder();

    for (Tool tool : CppConfiguration.Tool.values()) {

      // Some toolchains don't have particular tools.
      if (!Arrays.asList(excludedTools).contains(tool)) {

        String toolPath = createToolPath(toolchainName, targetPlatform + "-" + tool.getNamePart());

        toolPaths.add(ToolPath.newBuilder()
            .setName(tool.getNamePart())
            .setPath(toolPath)
            .build());
      }
    }

    return toolPaths.build();
  }

  public ImmutableList<ToolPath> createClangToolpaths(String toolchainName, String targetPlatform,
      String llvmVersion, CppConfiguration.Tool... excludedTools) {

    // Add GCC to the list of excluded tools. It will be replaced by clang below.
    excludedTools = ImmutableList.<CppConfiguration.Tool>builder()
        .add(excludedTools)
        .add(CppConfiguration.Tool.GCC)
        .build()
        .toArray(new CppConfiguration.Tool[excludedTools.length + 1]);

    // Create the regular tool paths, then add clang.
    return ImmutableList.<ToolPath>builder()
        .addAll(createToolpaths(toolchainName, targetPlatform, excludedTools))

        .add(ToolPath.newBuilder()
            .setName("gcc")
            .setPath(createToolPath(llvmVersion == null ? "llvm" : "llvm-" + llvmVersion, "clang"))
            .build())
        .build();
  }

  private String createToolPath(String toolchainName, String toolName) {

    String toolpathTemplate = "ndk/toolchains/%toolchainName%/prebuilt/%hostPlatform%"
        + "/bin/%toolName%";

    return toolpathTemplate
        .replace("%repositoryName%", repositoryName)
        .replace("%toolchainName%", toolchainName)
        .replace("%hostPlatform%", hostPlatform)
        .replace("%toolName%", toolName);
  }

  public static String getToolchainDirectoryFromToolPath(String toolPath) {
    return toolPath.split("/")[2];
  }

  public String createGccToolchainPath(String toolchainName) {

    String gccToolchainPathTemplate =
        "external/%repositoryName%/ndk/toolchains/%toolchainName%/prebuilt/%hostPlatform%";

    return gccToolchainPathTemplate
        .replace("%repositoryName%", repositoryName)
        .replace("%toolchainName%", toolchainName)
        .replace("%hostPlatform%", hostPlatform);
  }

  /**
   * Gets the clang NDK builtin includes directories that exist in the NDK. These directories are
   * always searched for header files by clang and should be added to the CROSSTOOL in the
   * cxx_builtin_include_directories list.
   *
   * <p>You can see the list of directories and the order that they are searched in by running
   * {@code clang -E -x c++ - -v < /dev/null}.
   */
  public String createClangToolchainBuiltinIncludeDirectory(String clangVersion) {
    String clangBuiltinIncludeDirectoryPathTemplate =
        "external/%repositoryName%/ndk/toolchains/llvm/prebuilt/%hostPlatform%/lib64/clang/"
            + "%clangVersion%/include";
    return clangBuiltinIncludeDirectoryPathTemplate
        .replace("%repositoryName%", repositoryName)
        .replace("%hostPlatform%", hostPlatform)
        .replace("%clangVersion%", clangVersion);
  }

  /**
   * Gets the gcc NDK builtin includes directories that exist in the NDK. These directories are
   * always searched for header files by clang and should be added to the CROSSTOOL in the
   * cxx_builtin_include_directories list.
   *
   * <p>You can see the list of directories and the order that they are searched in by running
   * {@code gcc -E -x c++ - -v < /dev/null}.
   */
  public List<String> createGccToolchainBuiltinIncludeDirectories(
      final String toolchainName, final String targetPlatform, final String gccVersion) {
    final String toolchainIncludePathTemplate =
        "external/%repositoryName%/ndk/toolchains/%toolchainName%/prebuilt/%hostPlatform%"
            + "/lib/gcc/%targetPlatform%/%gccVersion%/%includeFolderName%";
    return Lists.transform(
        ImmutableList.of("include", "include-fixed"),
        includeFolderName ->
            toolchainIncludePathTemplate
                .replace("%repositoryName%", repositoryName)
                .replace("%toolchainName%", toolchainName)
                .replace("%hostPlatform%", hostPlatform)
                .replace("%targetPlatform%", targetPlatform)
                .replace("%gccVersion%", gccVersion)
                .replace("%includeFolderName%", includeFolderName));
  }

  /**
   * NDK 14 and below. Each API level has its own headers. See
   * https://android.googlesource.com/platform/ndk/+/ndk-r15-release/docs/UnifiedHeaders.md#supporting-unified-headers-in-your-build-system
   *
   * @param targetCpu the target CPU architecture
   * @return the path to the compile time sysroot
   */
  public String createBuiltinSysroot(String targetCpu) {

    String correctedApiLevel = apiLevel.getCpuCorrectedApiLevel(targetCpu);

    String androidPlatformIncludePathTemplate =
        "external/%repositoryName%/ndk/platforms/android-%apiLevel%/arch-%arch%";

    return androidPlatformIncludePathTemplate
        .replace("%repositoryName%", repositoryName)
        .replace("%apiLevel%", correctedApiLevel)
        .replace("%arch%", targetCpu);
  }

  /**
   * NDK 15 and above. The headers have been unified into ndk/sysroot.
   *
   * @return the sysroot location for NDK 15 and above.
   */
  public String createBuiltinSysroot() {
    // This location does not exist prior to NDK 15
    Preconditions.checkState(majorRevision >= 15);

    return "external/%repositoryName%/ndk/sysroot".replace("%repositoryName%", repositoryName);
  }

  public String getCorrectedApiLevel(String targetCpu) {
    return apiLevel.getCpuCorrectedApiLevel(targetCpu);
  }

  ImmutableList<String> createGnuLibstdcIncludePaths(String gccVersion, String targetCpu) {

    String cpuNoThumb = targetCpu.replaceAll("-thumb$", "");

    String prefix = "external/%repositoryName%/ndk/sources/cxx-stl/gnu-libstdc++/%gccVersion%/";
    List<String> includePathTemplates = Arrays.asList(
        prefix + "include",
        prefix + "libs/%targetCpu%/include",
        prefix + "include/backward");

    ImmutableList.Builder<String> includePaths = ImmutableList.builder();
    for (String template : includePathTemplates) {
      includePaths.add(
          template
            .replace("%repositoryName%", repositoryName)
            .replace("%gccVersion%", gccVersion)
            .replace("%targetCpu%", cpuNoThumb));
    }
    return includePaths.build();
  }

  ImmutableList<String> createStlportIncludePaths() {

    String prefix =
        "external/%repositoryName%/ndk/sources/cxx-stl/"
            .replace("%repositoryName%", repositoryName);

    return ImmutableList.of(prefix + "stlport/stlport", prefix + "gabi++/include");
  }

  ImmutableList<String> createLibcxxIncludePaths() {

    String prefix =
        "external/%repositoryName%/ndk/sources/".replace("%repositoryName%", repositoryName);

    ImmutableList.Builder<String> includePaths = ImmutableList.builder();
    
    if (majorRevision <= 12) {
      includePaths.add(prefix + "cxx-stl/llvm-libc++/libcxx/include");
      includePaths.add(prefix + "cxx-stl/llvm-libc++abi/libcxxabi/include");
    } else {
      // libcxx/include was moved one level up from r13 onwards.
      // See https://github.com/bazelbuild/bazel/issues/3641
      includePaths.add(prefix + "cxx-stl/llvm-libc++/include");
      includePaths.add(prefix + "cxx-stl/llvm-libc++abi/include");
    }

    includePaths.add(prefix + "android/support/include");

    return includePaths.build();
  }

  /**
   * @param stl The STL name as it appears in the NDK path
   * @param gccVersion The GCC version "4.8" or "4.9", applicable only to gnu-libstdc++, or null
   * @param targetCpu Target CPU
   * @param fileExtension "a" or "so"
   * @return A glob pattern for the STL runtime libs in the NDK.
   */
  static String createStlRuntimeLibsGlob(
      String stl, String gccVersion, String targetCpu, String fileExtension) {

    if (gccVersion != null) {
      stl += "/" + gccVersion;
    }

    targetCpu = targetCpu.replaceAll("-thumb$", "/thumb");

    String template =
        "ndk/sources/cxx-stl/%stl%/libs/%targetCpu%/*.%fileExtension%";
    return template
        .replace("%stl%", stl)
        .replace("%targetCpu%", targetCpu)
        .replace("%fileExtension%", fileExtension);
  }

  /**
   * @param targetCpu Target CPU
   * @return the directory of the target CPU's runtime .a files for linking
   */
  public String createLibcppLinkerPath(String targetCpu) {
    return "external/%repositoryName%/ndk/sources/cxx-stl/llvm-libc++/libs/%targetCpu%"
        .replace("%repositoryName%", repositoryName)
        .replace("%targetCpu%", targetCpu);
  }
}

