// Copyright 2017 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.analysis;

import static java.util.stream.Collectors.joining;

import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.analysis.platform.PlatformInfo;
import com.google.devtools.build.lib.analysis.platform.ToolchainInfo;
import com.google.devtools.build.lib.analysis.platform.ToolchainTypeInfo;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
import com.google.devtools.build.lib.events.Location;
import com.google.devtools.build.lib.skylarkbuildapi.ToolchainContextApi;
import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
import com.google.devtools.build.lib.syntax.EvalException;
import com.google.devtools.build.lib.syntax.EvalUtils;
import java.util.Optional;
import java.util.Set;
import javax.annotation.Nullable;

/** Represents the data needed for a specific target's use of toolchains and platforms. */
@AutoValue
@Immutable
@ThreadSafe
public abstract class ToolchainContext implements ToolchainContextApi {

  static Builder builder() {
    return new AutoValue_ToolchainContext.Builder();
  }

  /** Builder interface to help create new instances of {@link ToolchainContext}. */
  @AutoValue.Builder
  interface Builder {
    /** Sets a description of the target being used, for error messaging. */
    Builder setTargetDescription(String targetDescription);

    /** Sets the selected execution platform that these toolchains use. */
    Builder setExecutionPlatform(PlatformInfo executionPlatform);

    /** Sets the target platform that these toolchains generate output for. */
    Builder setTargetPlatform(PlatformInfo targetPlatform);

    /** Sets the toolchain types that were requested. */
    Builder setRequiredToolchainTypes(Set<ToolchainTypeInfo> requiredToolchainTypes);

    /** Sets the map from toolchain type to toolchain provider. */
    Builder setToolchains(ImmutableMap<ToolchainTypeInfo, ToolchainInfo> toolchains);

    /** Sets the template variables that these toolchains provide. */
    Builder setTemplateVariableProviders(ImmutableList<TemplateVariableInfo> providers);

    /** Sets the labels of the specific toolchains being used. */
    Builder setResolvedToolchainLabels(ImmutableSet<Label> resolvedToolchainLabels);

    /** Returns a new {@link ToolchainContext}. */
    ToolchainContext build();
  }

  /** Returns a description of the target being used, for error messaging. */
  abstract String targetDescription();

  /** Returns the selected execution platform that these toolchains use. */
  public abstract PlatformInfo executionPlatform();

  /** Returns the target platform that these toolchains generate output for. */
  public abstract PlatformInfo targetPlatform();

  /** Returns the toolchain types that were requested. */
  public abstract ImmutableSet<ToolchainTypeInfo> requiredToolchainTypes();

  abstract ImmutableMap<ToolchainTypeInfo, ToolchainInfo> toolchains();

  /** Returns the template variables that these toolchains provide. */
  public abstract ImmutableList<TemplateVariableInfo> templateVariableProviders();

  /** Returns the labels of the specific toolchains being used. */
  public abstract ImmutableSet<Label> resolvedToolchainLabels();

  /**
   * Returns the toolchain for the given type, or {@code null} if the toolchain type was not
   * required in this context.
   */
  @Nullable
  public ToolchainInfo forToolchainType(Label toolchainTypeLabel) {
    Optional<ToolchainTypeInfo> toolchainType =
        toolchains().keySet().stream()
            .filter(info -> info.typeLabel().equals(toolchainTypeLabel))
            .findFirst();
    if (toolchainType.isPresent()) {
      return forToolchainType(toolchainType.get());
    } else {
      return null;
    }
  }

  @Nullable
  public ToolchainInfo forToolchainType(ToolchainTypeInfo toolchainType) {
    return toolchains().get(toolchainType);
  }

  @Override
  public boolean isImmutable() {
    return true;
  }

  @Override
  public void repr(SkylarkPrinter printer) {
    printer.append("<toolchain_context.resolved_labels: ");
    printer.append(
        toolchains().keySet().stream()
            .map(ToolchainTypeInfo::typeLabel)
            .map(Label::toString)
            .collect(joining(", ")));
    printer.append(">");
  }

  private Label transformKey(Object key, Location loc) throws EvalException {
    if (key instanceof Label) {
      return (Label) key;
    } else if (key instanceof ToolchainTypeInfo) {
      return ((ToolchainTypeInfo) key).typeLabel();
    } else if (key instanceof String) {
      Label toolchainType;
      String rawLabel = (String) key;
      try {
        toolchainType = Label.parseAbsolute(rawLabel, ImmutableMap.of());
      } catch (LabelSyntaxException e) {
        throw new EvalException(
            loc, String.format("Unable to parse toolchain %s: %s", rawLabel, e.getMessage()), e);
      }
      return toolchainType;
    } else {
      throw new EvalException(
          loc,
          String.format(
              "Toolchains only supports indexing by toolchain type, got %s instead",
              EvalUtils.getDataTypeName(key)));
    }
  }

  @Override
  public ToolchainInfo getIndex(Object key, Location loc) throws EvalException {
    Label toolchainTypeLabel = transformKey(key, loc);

    if (!containsKey(key, loc)) {
      throw new EvalException(
          loc,
          String.format(
              "In %s, toolchain type %s was requested but only types [%s] are configured",
              targetDescription(),
              toolchainTypeLabel,
              requiredToolchainTypes().stream()
                  .map(ToolchainTypeInfo::typeLabel)
                  .map(Label::toString)
                  .collect(joining(", "))));
    }
    return forToolchainType(toolchainTypeLabel);
  }

  @Override
  public boolean containsKey(Object key, Location loc) throws EvalException {
    Label toolchainTypeLabel = transformKey(key, loc);
    Optional<Label> matching =
        toolchains().keySet().stream()
            .map(ToolchainTypeInfo::typeLabel)
            .filter(label -> label.equals(toolchainTypeLabel))
            .findAny();
    return matching.isPresent();
  }
}
