// Copyright 2018 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.repository;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.analysis.BlazeDirectories;
import com.google.devtools.build.lib.analysis.RuleDefinition;
import com.google.devtools.build.lib.bazel.ResolvedEvent;
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.rules.repository.RepositoryDirectoryValue;
import com.google.devtools.build.lib.rules.repository.RepositoryFunction;
import com.google.devtools.build.lib.rules.repository.ResolvedHashesFunction;
import com.google.devtools.build.lib.util.CPU;
import com.google.devtools.build.lib.util.OS;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.XattrProvider;
import com.google.devtools.build.skyframe.SkyFunction.Environment;
import com.google.devtools.build.skyframe.SkyFunctionException.Transience;
import com.google.devtools.build.skyframe.SkyKey;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.annotation.Nullable;

/** Create a local repository that describes the auto-detected host platform. */
public class LocalConfigPlatformFunction extends RepositoryFunction {

  @Override
  public boolean isLocal(Rule rule) {
    return true;
  }

  @Override
  public Class<? extends RuleDefinition> getRuleDefinition() {
    return LocalConfigPlatformRule.class;
  }

  @Override
  public RepositoryDirectoryValue.Builder fetch(
      Rule rule,
      Path outputDirectory,
      BlazeDirectories directories,
      Environment env,
      Map<String, String> markerData,
      SkyKey key)
      throws RepositoryFunctionException {

    CPU hostCpu = CPU.getCurrent();
    OS hostOs = OS.getCurrent();

    String name = rule.getName();
    try {
      outputDirectory.createDirectoryAndParents();
      RepositoryFunction.writeFile(outputDirectory, "WORKSPACE", workspaceFileContent(name));
      RepositoryFunction.writeFile(outputDirectory, "MODULE.bazel", moduleFileContent(name));
      RepositoryFunction.writeFile(outputDirectory, "BUILD.bazel", buildFileContent(name));
      RepositoryFunction.writeFile(
          outputDirectory, "constraints.bzl", constraintFileContent(hostCpu, hostOs));
    } catch (IOException e) {
      throw new RepositoryFunctionException(
          new IOException("Could not create content for " + name + ": " + e.getMessage()),
          Transience.TRANSIENT);
    }

    // Save in the resolved repository file.
    env.getListener()
        .post(
            new ResolvedEvent() {
              @Override
              public String getName() {
                return name;
              }

              @Override
              public Object getResolvedInformation(XattrProvider xattrProvider) {
                String repr = String.format("local_config_platform(name = '%s')", name);
                return ImmutableMap.<String, Object>builder()
                    .put(ResolvedHashesFunction.ORIGINAL_RULE_CLASS, LocalConfigPlatformRule.NAME)
                    .put(
                        ResolvedHashesFunction.ORIGINAL_ATTRIBUTES,
                        ImmutableMap.<String, Object>builder().put("name", name).buildOrThrow())
                    .put(ResolvedHashesFunction.NATIVE, repr)
                    .buildOrThrow();
              }
            });

    // Return the needed info.
    return RepositoryDirectoryValue.builder().setPath(outputDirectory);
  }

  @Nullable
  static String cpuToConstraint(CPU cpu) {
    switch (cpu) {
      case X86_32:
        return "@platforms//cpu:x86_32";
      case X86_64:
        return "@platforms//cpu:x86_64";
      case PPC:
        return "@platforms//cpu:ppc";
      case ARM:
        return "@platforms//cpu:arm";
      case AARCH64:
        return "@platforms//cpu:aarch64";
      case S390X:
        return "@platforms//cpu:s390x";
      case MIPS64:
        return "@platforms//cpu:mips64";
      case RISCV64:
        return "@platforms//cpu:riscv64";
      default:
        // Unknown, so skip it.
        return null;
    }
  }

  @Nullable
  static String osToConstraint(OS os) {
    switch (os) {
      case DARWIN:
        return "@platforms//os:osx";
      case FREEBSD:
        return "@platforms//os:freebsd";
      case OPENBSD:
        return "@platforms//os:openbsd";
      case LINUX:
        return "@platforms//os:linux";
      case WINDOWS:
        return "@platforms//os:windows";
      default:
        // Unknown, so skip it.
        return null;
    }
  }

  private static String workspaceFileContent(String repositoryName) {
    return format(
        ImmutableList.of(
            "# DO NOT EDIT: automatically generated WORKSPACE file for local_config_platform",
            "workspace(name = \"%s\")"),
        repositoryName);
  }

  private static String moduleFileContent(String repositoryName) {
    return format(
        ImmutableList.of(
            "# DO NOT EDIT: automatically generated MODULE file for local_config_platform",
            "module(name = \"%s\")",
            // Try to keep this updated with the src/MODULE.tools file. (Due to MVS, even if this is
            // not kept up to date, we'll use the latest version anyhow)
            "bazel_dep(name = \"platforms\", version = \"0.0.4\")"),
        repositoryName);
  }

  private static String buildFileContent(String repositoryName) {
    return format(
        ImmutableList.of(
            "# DO NOT EDIT: automatically generated BUILD file for local_config_platform",
            "package(default_visibility = ['//visibility:public'])",
            "load(':constraints.bzl', 'HOST_CONSTRAINTS')",
            "platform(name = 'host',",
            "  # Auto-detected host platform constraints.",
            "  constraint_values = HOST_CONSTRAINTS,",
            ")",
            "exports_files([",
            "  # Export constraints.bzl for use in downstream bzl_library targets.",
            "  'constraints.bzl',",
            "])"),
        repositoryName);
  }

  private static String constraintFileContent(CPU hostCpu, OS hostOs) {
    List<String> contents = new ArrayList<>();
    contents.add(
        "# DO NOT EDIT: automatically generated constraints list for local_config_platform");
    contents.add("# Auto-detected host platform constraints.");
    contents.add("HOST_CONSTRAINTS = [");

    String cpuConstraint = cpuToConstraint(hostCpu);
    if (cpuConstraint != null) {
      contents.add("  '" + cpuConstraint + "',");
    }
    String osConstraint = osToConstraint(hostOs);
    if (osConstraint != null) {
      contents.add("  '" + osConstraint + "',");
    }
    contents.add("]");

    return format(contents);
  }

  private static String format(List<String> lines, Object... params) {
    // Add a newline between each line, and also after the final line.
    String content = lines.stream().collect(Collectors.joining("\n", "", "\n"));
    return String.format(content, params);
  }
}
