// Copyright 2014 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.actions;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.SkyValue;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;

/**
 * Base class for all values which can provide the generating action of an artifact.
 */
public abstract class ActionLookupValue implements SkyValue {

  @AutoCodec.VisibleForSerialization protected final boolean removeActionsAfterEvaluation;

  public ActionLookupValue(boolean removeActionsAfterEvaluation) {
    this.removeActionsAfterEvaluation = removeActionsAfterEvaluation;
  }

  /**
   * Returns a list of actions registered by this {@link SkyValue}.
   */
  protected abstract ArrayList<ActionAnalysisMetadata> getActions();

  /**
   * Returns a map where keys are artifacts generated by this {@link SkyValue}, and values are
   * the index of the action which generates this artifact.
   */
  protected abstract ImmutableMap<Artifact, Integer> getGeneratingActionIndex();

  /**
   * Returns the index of the action that generates {@code artifact} in this value, or null if this
   * value does not have a generating action for this artifact. The index together with the key for
   * this {@link ActionLookupValue} uniquely identifies the action.
   *
   * <p>Unlike {@link #getAction}, this may be called after action execution.
   */
  @Nullable
  public Integer getGeneratingActionIndex(Artifact artifact) {
    return getGeneratingActionIndex().get(artifact);
  }

  /**
   * Returns the action that generates {@code artifact}, if known to this value, or null. This
   * method should be avoided. Call it only when the action is really needed, and it is known to be
   * present, either because the execution phase has not started, or because {@link
   * Action#canRemoveAfterExecution} is known to be false for the action being requested.
   */
  @Nullable
  public ActionAnalysisMetadata getGeneratingActionDangerousReadJavadoc(Artifact artifact) {
    Integer actionIndex = getGeneratingActionIndex(artifact);
    if (actionIndex == null) {
      return null;
    }
    return getActions().get(actionIndex);
  }

  /**
   * Returns the {@link Action} with index {@code index} in this value. Never null. Should only be
   * called during action execution by {@code ArtifactFunction} and {@code ActionExecutionFunction}
   * -- after an action has executed, calling this with its index may crash.
   */
  @SuppressWarnings("unchecked") // We test to make sure it's an Action.
  public Action getAction(int index) {
    ActionAnalysisMetadata result = getActions().get(index);
    Preconditions.checkState(result instanceof Action, "Not action: %s %s %s", result, index, this);
    return (Action) result;
  }

  public ActionTemplate<?> getActionTemplate(int index) {
    ActionAnalysisMetadata result = getActions().get(index);
    Preconditions.checkState(
        result instanceof ActionTemplate, "Not action template: %s %s %s", result, index, this);
    return (ActionTemplate<?>) result;
  }

  /**
   * Returns if the action at {@code index} is an {@link ActionTemplate} so that tree artifacts can
   * take the proper action.
   */
  public boolean isActionTemplate(int index) {
    return getActions().get(index) instanceof ActionTemplate;
  }

  /** To be used only when checking consistency of the action graph -- not by other values. */
  public Map<Artifact, ActionAnalysisMetadata> getMapForConsistencyCheck() {
    return getMapForConsistencyCheck(getGeneratingActionIndex(), getActions());
  }

  public static Map<Artifact, ActionAnalysisMetadata> getMapForConsistencyCheck(
      Map<Artifact, Integer> generatingActionIndex,
      final List<? extends ActionAnalysisMetadata> actions) {
    return Maps.transformValues(generatingActionIndex, actions::get);
  }

  /**
   * Returns the number of {@link Action} objects present in this value.
   */
  public int getNumActions() {
    return getActions().size();
  }

  /**
   * If this object was initialized with {@code removeActionsAfterEvaluation} and {@link
   * Action#canRemoveAfterExecution()} is true for {@code action}, then remove this action from this
   * object's index as a memory-saving measure. The {@code artifact -> index} mapping remains
   * intact, so this action's execution value can still be addressed by its inputs.
   */
  @ThreadSafe
  public void actionEvaluated(int actionIndex, Action action) {
    if (removeActionsAfterEvaluation && action.canRemoveAfterExecution()) {
      // This method may concurrently mutate an ArrayList, which is unsafe on its face. However,
      // ArrayList mutation on different indices that does not affect the size of the ArrayList is
      // safe, and that is what does this code does.
      ArrayList<ActionAnalysisMetadata> actionArrayList = getActions();
      ActionAnalysisMetadata oldAction = actionArrayList.set(actionIndex, null);
      Preconditions.checkState(
          action.equals(oldAction), "Not same: %s %s %s %s", action, oldAction, this, actionIndex);
    }
  }


  /**
   * All subclasses of ActionLookupValue "own" artifacts with {@link ArtifactOwner}s that are
   * subclasses of ActionLookupKey. This allows callers to easily find the value key, while
   * remaining agnostic to what ActionLookupValues actually exist.
   */
  public abstract static class ActionLookupKey implements ArtifactOwner, SkyKey {
    @Override
    public Label getLabel() {
      return null;
    }
  }
}
