// Copyright 2023 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.producers;

import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.ConfiguredTargetValue;
import com.google.devtools.build.lib.analysis.config.CommonOptions;
import com.google.devtools.build.lib.analysis.platform.PlatformInfo;
import com.google.devtools.build.lib.analysis.platform.PlatformProviderUtils;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.packages.NoSuchPackageException;
import com.google.devtools.build.lib.packages.NoSuchTargetException;
import com.google.devtools.build.lib.skyframe.BuildConfigurationKey;
import com.google.devtools.build.lib.skyframe.ConfiguredTargetKey;
import com.google.devtools.build.lib.skyframe.ConfiguredValueCreationException;
import com.google.devtools.build.lib.skyframe.PackageValue;
import com.google.devtools.build.lib.skyframe.toolchains.PlatformLookupUtil;
import com.google.devtools.build.lib.skyframe.toolchains.PlatformLookupUtil.InvalidPlatformException;
import com.google.devtools.build.skyframe.SkyValue;
import com.google.devtools.build.skyframe.state.StateMachine;
import javax.annotation.Nullable;

/**
 * Retrieves {@link PlatformInfo} for a given platform.
 *
 * <p>Since platforms do not rely on the configuration, this uses a dummy blank configuration to
 * help reduce the number of skyframe edges created.
 *
 * <p>This creates an explicit dependency on the {@link Package} to retrieve the associated target,
 * so it is possible to verify that {@link PlatformInfo} is an advertised provider before
 * constructing the {@link ConfiguredTarget}.
 */
final class PlatformInfoProducer
    implements StateMachine, StateMachine.ValueOrExceptionSink<NoSuchPackageException> {
  interface ResultSink {
    void acceptPlatformInfo(PlatformInfo info);

    void acceptPlatformInfoError(InvalidPlatformException error);
  }

  // -------------------- Input --------------------
  private final Label platformLabel;

  // -------------------- Output --------------------
  private final ResultSink sink;

  // -------------------- Sequencing --------------------
  private final StateMachine runAfter;

  // -------------------- Internal State --------------------
  private boolean passedValidation = false;
  private ConfiguredTarget platform;

  PlatformInfoProducer(Label platformLabel, ResultSink sink, StateMachine runAfter) {
    this.platformLabel = platformLabel;
    this.sink = sink;
    this.runAfter = runAfter;
  }

  @Override
  public StateMachine step(Tasks tasks) {
    // Loads the Package first to verify the Target. The ConfiguredTarget should not be loaded
    // until after verification. See https://github.com/bazelbuild/bazel/pull/10307.
    //
    // In distributed analysis, these packages will be duplicated across shards.
    tasks.lookUp(
        platformLabel.getPackageIdentifier(),
        NoSuchPackageException.class,
        (StateMachine.ValueOrExceptionSink<NoSuchPackageException>) this);
    return this::lookupPlatform;
  }

  @Override
  public void acceptValueOrException(
      @Nullable SkyValue value, @Nullable NoSuchPackageException error) {
    if (value != null) {
      var pkg = ((PackageValue) value).getPackage();
      try {
        var target = pkg.getTarget(platformLabel.getName());
        if (!PlatformLookupUtil.hasPlatformInfo(target)) {
          // validation failure
          sink.acceptPlatformInfoError(new InvalidPlatformException(platformLabel));
          return;
        }
      } catch (NoSuchTargetException e) {
        sink.acceptPlatformInfoError(new InvalidPlatformException(e));
        return;
      }
      passedValidation = true;
      return;
    }
    if (error != null) {
      sink.acceptPlatformInfoError(new InvalidPlatformException(error));
      return;
    }
    throw new IllegalArgumentException("both value and error were null");
  }

  private StateMachine lookupPlatform(Tasks tasks) {
    if (!passedValidation) {
      return runAfter;
    }

    // Create a configured target key with a dummy configuration.
    ConfiguredTargetKey platformKey =
        ConfiguredTargetKey.builder()
            .setLabel(platformLabel)
            .setConfigurationKey(
                BuildConfigurationKey.withoutPlatformMapping(CommonOptions.EMPTY_OPTIONS))
            .build();
    tasks.lookUp(
        platformKey, ConfiguredValueCreationException.class, this::acceptPlatformValueOrError);
    return this::retrievePlatformInfo;
  }

  private void acceptPlatformValueOrError(
      @Nullable SkyValue value, @Nullable ConfiguredValueCreationException error) {
    if (value != null) {
      var configuredTargetValue = (ConfiguredTargetValue) value;
      this.platform = configuredTargetValue.getConfiguredTarget();
      return;
    }
    if (error != null) {
      sink.acceptPlatformInfoError(new InvalidPlatformException(platformLabel, error));
      return;
    }
    throw new IllegalArgumentException("both value and error were null");
  }

  private StateMachine retrievePlatformInfo(Tasks tasks) {
    if (platform == null) {
      return runAfter; // An error occurred and was reported.
    }

    PlatformInfo platformInfo = PlatformProviderUtils.platform(platform);
    if (platformInfo == null) {
      sink.acceptPlatformInfoError(new InvalidPlatformException(platform.getLabel()));
      return runAfter;
    }

    sink.acceptPlatformInfo(platformInfo);
    return runAfter;
  }
}
