// 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.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig;
import com.google.protobuf.TextFormat;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Set;

/**
 * A helper class to create a crosstool package containing a CROSSTOOL file, and the various
 * rules needed for a mock - use this only for configured target tests, not for execution tests.
 */
final class Crosstool {
  private static final ImmutableList<String> CROSSTOOL_BINARIES =
      ImmutableList.of("ar", "as", "compile", "dwp", "link", "objcopy", "llvm-profdata");

  private final MockToolsConfig config;

  private final String crosstoolTop;
  private String version;
  private String crosstoolFileContents;
  private boolean addEmbeddedRuntimes;
  private String staticRuntimesLabel;
  private String dynamicRuntimesLabel;
  private ImmutableList<String> archs;
  private boolean addModuleMap;
  private boolean supportsHeaderParsing;

  Crosstool(MockToolsConfig config, String crosstoolTop) {
    this.config = config;
    this.crosstoolTop = crosstoolTop;
  }

  public Crosstool setAddModuleMap(boolean addModuleMap) {
    this.addModuleMap = addModuleMap;
    return this;
  }

  public Crosstool setCrosstoolFile(String version, String crosstoolFileContents) {
    this.version = version;
    this.crosstoolFileContents = crosstoolFileContents;
    return this;
  }

  public Crosstool setSupportedArchs(ImmutableList<String> archs) {
    this.archs = archs;
    return this;
  }

  public Crosstool setSupportsHeaderParsing(boolean supportsHeaderParsing) {
    this.supportsHeaderParsing = supportsHeaderParsing;
    return this;
  }

  public Crosstool setEmbeddedRuntimes(
      boolean addEmbeddedRuntimes, String staticRuntimesLabel, String dynamicRuntimesLabel) {
    this.addEmbeddedRuntimes = addEmbeddedRuntimes;
    this.staticRuntimesLabel = staticRuntimesLabel;
    this.dynamicRuntimesLabel = dynamicRuntimesLabel;
    return this;
  }

  public void write() throws IOException {
    String runtimes = "";
    for (String arch : archs) {
      runtimes +=
          Joiner.on('\n')
              .join(
                  "filegroup(name = 'dynamic-runtime-libs-" + arch + "',",
                  "          licenses = ['unencumbered'],",
                  "          srcs = ['libdynamic-runtime-lib-source.so'])",
                  "filegroup(name = 'static-runtime-libs-" + arch + "',",
                  "          licenses = ['unencumbered'],",
                  "          srcs = ['static-runtime-lib-source.a'])\n");
    }

    StringBuilder compilationTools = new StringBuilder();
    for (String compilationTool : CROSSTOOL_BINARIES) {
      Collection<String> archTargets = new ArrayList<>();
      for (String arch : archs) {
        archTargets.add(compilationTool + '-' + arch);
      }

      compilationTools.append(
          String.format(
              "filegroup(name = '%s', srcs = ['%s'])\n",
              compilationTool,
              Joiner.on("', '").join(archTargets)));
      for (String archTarget : archTargets) {
        compilationTools.append(
            String.format("filegroup(name = '%s', srcs = [':everything-multilib'])\n", archTarget));
      }
    }

    CrosstoolConfig.CrosstoolRelease.Builder configBuilder =
        CrosstoolConfig.CrosstoolRelease.newBuilder();
    TextFormat.merge(crosstoolFileContents, configBuilder);
    StringBuilder compilerMap = new StringBuilder();
    // Remove duplicates
    Set<String> keys = new LinkedHashSet<>();
    for (CrosstoolConfig.CToolchain toolchain : configBuilder.build().getToolchainList()) {
      String key = String.format("%s|%s", toolchain.getTargetCpu(), toolchain.getCompiler());
      if (!keys.contains(key)) {
        keys.add(key);
        compilerMap.append(
            String.format("'%s': ':cc-compiler-%s',\n", key, toolchain.getTargetCpu()));
      }
    }

    for (String arch : archs) {
      String compilerRule;
      String staticRuntimesString =
          staticRuntimesLabel == null ? "" : ", '" + staticRuntimesLabel + "'";
      String dynamicRuntimesString =
          dynamicRuntimesLabel == null ? "" : ", '" + dynamicRuntimesLabel + "'";

      compilerRule =
          Joiner.on("\n")
              .join(
                  "cc_toolchain(",
                  "    name = 'cc-compiler-" + arch + "',",
                  "    output_licenses = ['unencumbered'],",
                  addModuleMap ? "    module_map = 'crosstool.cppmap'," : "",
                  "    cpu = '" + arch + "',",
                  "    compiler = 'gcc-4.4.0',",
                  "    ar_files = 'ar-" + arch + "',",
                  "    as_files = 'as-" + arch + "',",
                  "    compiler_files = 'compile-" + arch + "',",
                  "    dwp_files = 'dwp-" + arch + "',",
                  "    linker_files = 'link-" + arch + "',",
                  "    strip_files = ':every-file',",
                  "    objcopy_files = 'objcopy-" + arch + "',",
                  "    all_files = ':every-file',",
                  "    licenses = ['unencumbered'],",
                  supportsHeaderParsing ? "    supports_header_parsing = 1," : "",
                  "    dynamic_runtime_libs = ['dynamic-runtime-libs-"
                      + arch
                      + "'"
                      + dynamicRuntimesString
                      + "],",
                  "    static_runtime_libs = ['static-runtime-libs-"
                      + arch
                      + "'"
                      + staticRuntimesString
                      + "])");

      compilationTools.append(compilerRule + "\n");
    }

    String build =
        Joiner.on("\n")
            .join(
                "package(default_visibility=['//visibility:public'])",
                "licenses(['restricted'])",
                "",
                "alias(name = 'toolchain', actual = 'everything')",
                "filegroup(name = 'everything-multilib',",
                "          srcs = glob(['" + version + "/**/*'],",
                "              exclude_directories = 1),",
                "          output_licenses = ['unencumbered'])",
                "",
                String.format(
                    "cc_toolchain_suite(name = 'everything', toolchains = {%s})", compilerMap),
                "",
                String.format(
                    "filegroup(name = 'every-file', srcs = ['%s'%s%s])",
                    Joiner.on("', '").join(CROSSTOOL_BINARIES),
                    addEmbeddedRuntimes ? ", ':dynamic-runtime-libs-k8'" : "",
                    addEmbeddedRuntimes ? ", ':static-runtime-libs-k8'" : ""),
                "",
                compilationTools.toString(),
                runtimes,
                "",
                // We add an empty :malloc target in case we need it.
                "cc_library(name = 'malloc')");

    config.create(crosstoolTop + "/" + version + "/x86/bin/gcc");
    config.create(crosstoolTop + "/" + version + "/x86/bin/ld");
    config.getPath(crosstoolTop + "/CROSSTOOL");
    config.overwrite(crosstoolTop + "/BUILD", build);
    config.overwrite(crosstoolTop + "/CROSSTOOL", crosstoolFileContents);
    config.create(crosstoolTop + "/crosstool.cppmap", "module crosstool {}");
  }
}
