// Copyright 2022 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.testutil;

import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;

import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableList;
import com.google.common.eventbus.AllowConcurrentEvents;
import com.google.common.eventbus.Subscribe;
import com.google.devtools.build.lib.actions.ActionCompletionEvent;
import com.google.devtools.build.lib.actions.ActionExecutedEvent;
import com.google.devtools.build.lib.actions.ActionExecutionMetadata;
import com.google.devtools.build.lib.actions.ActionMiddlemanEvent;
import com.google.devtools.build.lib.actions.ActionResultReceivedEvent;
import com.google.devtools.build.lib.actions.ActionStartedEvent;
import com.google.devtools.build.lib.actions.CachedActionEvent;
import com.google.devtools.build.lib.skyframe.proto.ActionRewind.ActionRewindEvent;
import com.google.devtools.build.lib.skyframe.rewinding.ActionRewindingStats;
import com.google.devtools.build.lib.skyframe.rewinding.ActionRewoundEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;

/** Records various action-related events for tests. */
public final class ActionEventRecorder {

  private final List<ActionStartedEvent> actionStartedEvents =
      Collections.synchronizedList(new ArrayList<>());
  private final List<ActionCompletionEvent> actionCompletionEvents =
      Collections.synchronizedList(new ArrayList<>());
  private final List<ActionExecutedEvent> actionExecutedEvents =
      Collections.synchronizedList(new ArrayList<>());
  private final List<ActionResultReceivedEvent> actionResultReceivedEvents =
      Collections.synchronizedList(new ArrayList<>());
  private final List<ActionMiddlemanEvent> actionMiddlemanEvents =
      Collections.synchronizedList(new ArrayList<>());
  private final List<CachedActionEvent> cachedActionEvents =
      Collections.synchronizedList(new ArrayList<>());
  private final List<ActionRewoundEvent> actionRewoundEvents =
      Collections.synchronizedList(new ArrayList<>());
  private final List<ActionRewindingStats> actionRewindingStatsPosts =
      Collections.synchronizedList(new ArrayList<>());

  private Consumer<ActionRewoundEvent> actionRewoundEventSubscriber = e -> {};

  public void setActionRewoundEventSubscriber(Consumer<ActionRewoundEvent> subscriber) {
    actionRewoundEventSubscriber = subscriber;
  }

  public List<ActionStartedEvent> getActionStartedEvents() {
    return actionStartedEvents;
  }

  public List<ActionCompletionEvent> getActionCompletionEvents() {
    return actionCompletionEvents;
  }

  public List<ActionExecutedEvent> getActionExecutedEvents() {
    return actionExecutedEvents;
  }

  public List<ActionResultReceivedEvent> getActionResultReceivedEvents() {
    return actionResultReceivedEvents;
  }

  public List<ActionRewoundEvent> getActionRewoundEvents() {
    return actionRewoundEvents;
  }

  public List<ActionRewindingStats> getActionRewindingStatsPosts() {
    return actionRewindingStatsPosts;
  }

  @SuppressWarnings("unused")
  @Subscribe
  @AllowConcurrentEvents
  void actionStarted(ActionStartedEvent event) {
    actionStartedEvents.add(event);
  }

  @SuppressWarnings("unused")
  @Subscribe
  @AllowConcurrentEvents
  void actionCompleted(ActionCompletionEvent event) {
    actionCompletionEvents.add(event);
  }

  @SuppressWarnings("unused")
  @Subscribe
  @AllowConcurrentEvents
  void actionExecuted(ActionExecutedEvent event) {
    actionExecutedEvents.add(event);
  }

  @SuppressWarnings("unused")
  @Subscribe
  @AllowConcurrentEvents
  void actionResultReceived(ActionResultReceivedEvent event) {
    actionResultReceivedEvents.add(event);
  }

  @SuppressWarnings("unused")
  @Subscribe
  @AllowConcurrentEvents
  void actionMiddleman(ActionMiddlemanEvent event) {
    actionMiddlemanEvents.add(event);
  }

  @SuppressWarnings("unused")
  @Subscribe
  @AllowConcurrentEvents
  void cachedAction(CachedActionEvent event) {
    cachedActionEvents.add(event);
  }

  @SuppressWarnings("unused")
  @Subscribe
  @AllowConcurrentEvents
  void actionRewound(ActionRewoundEvent event) {
    actionRewoundEvents.add(event);
    actionRewoundEventSubscriber.accept(event);
  }

  @SuppressWarnings("unused")
  @Subscribe
  @AllowConcurrentEvents
  void actionRewindingStats(ActionRewindingStats actionRewindingStats) {
    actionRewindingStatsPosts.add(actionRewindingStats);
  }

  public void clear() {
    actionStartedEvents.clear();
    actionCompletionEvents.clear();
    actionExecutedEvents.clear();
    actionResultReceivedEvents.clear();
    actionMiddlemanEvents.clear();
    cachedActionEvents.clear();
    actionRewoundEvents.clear();
    actionRewindingStatsPosts.clear();
  }

  /**
   * Check how many of each type of event was emitted during a successful build.
   *
   * @param runOnce Actions which ran and are not rewound
   * @param completedRewound Actions which ran and then are rewound by a later failed action
   * @param failedRewound Actions which fail because of lost inputs and which rewind themselves and
   *     the actions that generate those lost inputs
   * @param exactlyOneMiddlemanEventChecks A list of predicates which should be satisfied exactly
   *     once by the sequence of middleman events emitted
   */
  public void assertEvents(
      ImmutableList<String> runOnce,
      ImmutableList<String> completedRewound,
      ImmutableList<String> failedRewound,
      ImmutableList<Predicate<ActionMiddlemanEvent>> exactlyOneMiddlemanEventChecks,
      ImmutableList<Integer> actionRewindingPostLostInputCounts) {
    assertEvents(
        runOnce,
        completedRewound,
        failedRewound,
        exactlyOneMiddlemanEventChecks,
        /*expectResultReceivedForFailedRewound=*/ true,
        actionRewindingPostLostInputCounts,
        /*lostInputAndActionsPosts=*/ ImmutableList.of());
  }

  /**
   * Like {@link #assertEvents(ImmutableList, ImmutableList, ImmutableList, ImmutableList,
   * ImmutableList)}. The {@code expectResultReceivedForFailedRewound} should be true iff the failed
   * rewound actions ever successfully complete.
   *
   * @param expectResultReceivedForFailedRewound whether the failed rewound actions ever
   *     successfully complete, because no {@link ActionResultReceivedEvent} is emitted for a failed
   *     action
   */
  public void assertEvents(
      ImmutableList<String> runOnce,
      ImmutableList<String> completedRewound,
      ImmutableList<String> failedRewound,
      ImmutableList<Predicate<ActionMiddlemanEvent>> exactlyOneMiddlemanEventChecks,
      boolean expectResultReceivedForFailedRewound,
      ImmutableList<Integer> actionRewindingPostLostInputCounts,
      ImmutableList<ImmutableList<ActionRewindEventAsserter>> lostInputAndActionsPosts) {
    EventCountAsserter eventCountAsserter =
        new EventCountAsserter(runOnce, completedRewound, failedRewound);

    eventCountAsserter.assertEventCounts(
        /*events=*/ actionStartedEvents,
        /*eventsName=*/ "actionStartedEvents",
        /*converter=*/ e -> progressMessageOrPrettyPrint(e.getAction()),
        /*expectedRunOnceEventCount=*/ 1,
        /*expectedCompletedRewoundEventCount=*/ 1,
        /*expectedFailedRewoundEventCount=*/ 2);

    eventCountAsserter.assertEventCounts(
        /*events=*/ actionCompletionEvents,
        /*eventsName=*/ "actionCompletionEvents",
        /*converter=*/ e -> progressMessageOrPrettyPrint(e.getAction()),
        /*expectedRunOnceEventCount=*/ 1,
        /*expectedCompletedRewoundEventCount=*/ 1,
        /*expectedFailedRewoundEventCount=*/ 1);

    eventCountAsserter.assertEventCounts(
        /*events=*/ actionExecutedEvents,
        /*eventsName=*/ "actionExecutedEvents",
        /*converter=*/ e -> progressMessageOrPrettyPrint(e.getAction()),
        /*expectedRunOnceEventCount=*/ 1,
        /*expectedCompletedRewoundEventCount=*/ 1,
        /*expectedFailedRewoundEventCount=*/ 1);

    eventCountAsserter.assertEventCounts(
        /*events=*/ actionResultReceivedEvents,
        /*eventsName=*/ "actionResultReceivedEvents",
        /*converter=*/ e -> progressMessageOrPrettyPrint(e.getAction()),
        /*expectedRunOnceEventCount=*/ 1,
        /*expectedCompletedRewoundEventCount=*/ 1,
        /*expectedFailedRewoundEventCount=*/ expectResultReceivedForFailedRewound ? 1 : 0);

    eventCountAsserter.assertEventCounts(
        /*events=*/ actionRewoundEvents,
        /*eventsName=*/ "actionRewoundEvents",
        /*converter=*/ e -> progressMessageOrPrettyPrint(e.getFailedRewoundAction()),
        /*expectedRunOnceEventCount=*/ 0,
        /*expectedCompletedRewoundEventCount=*/ 0,
        /*expectedFailedRewoundEventCount=*/ 1);

    assertRewindActionStats(actionRewindingPostLostInputCounts, lostInputAndActionsPosts);

    // No middlemen, no worries
    // for (Predicate<ActionMiddlemanEvent> check : exactlyOneMiddlemanEventChecks) {
    //   assertThat(actionMiddlemanEvents.stream().filter(check).count()).isEqualTo(1);
    // }
    assertThat(cachedActionEvents).isEmpty();
  }

  /**
   * Assert that the contents of the {@link ActionRewindingStats} event matches expected results.
   *
   * @param totalLostInputCounts - The list of the counts of all lost inputs logged with each
   *     ActionRewindingStats post.
   * @param lostInputAndActionsPosts - The list of all expected values in all ActionRewindingStats
   *     posts. The outer list represents the ActionRewindingStats posts, the inner list contains
   *     {@link ActionRewindEventAsserter} that has the expected values of each action rewind event
   *     within each corresponding post.
   */
  public void assertRewindActionStats(
      ImmutableList<Integer> totalLostInputCounts,
      ImmutableList<ImmutableList<ActionRewindEventAsserter>> lostInputAndActionsPosts) {
    assertThat(actionRewindingStatsPosts).hasSize(totalLostInputCounts.size());
    for (int postIndex = 0; postIndex < lostInputAndActionsPosts.size(); postIndex++) {
      ActionRewindingStats actionRewindingStats = actionRewindingStatsPosts.get(postIndex);
      assertThat(actionRewindingStats.lostInputsCount())
          .isEqualTo(totalLostInputCounts.get(postIndex));
      ImmutableList<ActionRewindEventAsserter> expectedLostInputPost =
          lostInputAndActionsPosts.get(postIndex);

      for (int r = 0; r < actionRewindingStats.actionRewindEvents().size(); r++) {
        ActionRewindEvent actualActionRewind = actionRewindingStats.actionRewindEvents().get(r);
        expectedLostInputPost.get(r).assertActionRewindEvent(actualActionRewind);
      }
    }
  }

  @AutoValue
  public abstract static class ActionRewindEventAsserter {

    public static ActionRewindEventAsserter create(
        String expectedActionMnemonic,
        String expectedActionOwnerLabel,
        int expectedLostInputsCount,
        int expectedInvalidatedNodesCount) {
      return new AutoValue_ActionEventRecorder_ActionRewindEventAsserter(
          expectedActionMnemonic,
          expectedActionOwnerLabel,
          expectedLostInputsCount,
          expectedInvalidatedNodesCount);
    }

    ActionRewindEventAsserter() {}

    private void assertActionRewindEvent(ActionRewindEvent actualEvent) {
      assertThat(actualEvent.getActionDescription().getType()).isEqualTo(expectedActionMnemonic());
      assertThat(actualEvent.getActionDescription().getRuleLabel())
          .isEqualTo(expectedActionOwnerLabel());
      assertThat(actualEvent.getTotalLostInputsCount()).isEqualTo(expectedLostInputsCount());
      assertThat(actualEvent.getInvalidatedNodesCount()).isEqualTo(expectedInvalidatedNodesCount());
    }

    abstract String expectedActionMnemonic();

    abstract String expectedActionOwnerLabel();

    abstract int expectedLostInputsCount();

    abstract int expectedInvalidatedNodesCount();
  }

  private static final class EventCountAsserter {
    private final ImmutableList<String> runOnce;
    private final ImmutableList<String> completedRewound;
    private final ImmutableList<String> failedRewound;

    private EventCountAsserter(
        ImmutableList<String> runOnce,
        ImmutableList<String> completedRewound,
        ImmutableList<String> failedRewound) {
      this.runOnce = runOnce;
      this.completedRewound = completedRewound;
      this.failedRewound = failedRewound;
    }

    private <T> void assertEventCounts(
        List<T> events,
        String eventsName,
        Function<T, String> converter,
        int expectedRunOnceEventCount,
        int expectedCompletedRewoundEventCount,
        int expectedFailedRewoundEventCount) {
      ImmutableList<String> eventDescriptions =
          events.stream().map(converter).collect(toImmutableList());
      for (String runOnceAction : runOnce) {
        assertWithMessage("Run-once action \"%s\" in %s", runOnceAction, eventsName)
            .that(eventDescriptions.stream().filter(d -> d.equals(runOnceAction)).count())
            .isEqualTo(expectedRunOnceEventCount);
      }
      for (String rewoundAction : completedRewound) {
        assertWithMessage("Completed rewound action \"%s\" in %s", rewoundAction, eventsName)
            .that(eventDescriptions.stream().filter(d -> d.equals(rewoundAction)).count())
            .isEqualTo(expectedCompletedRewoundEventCount);
      }
      for (String failedRewoundAction : failedRewound) {
        assertWithMessage("Failed rewound action \"%s\" in %s", failedRewoundAction, eventsName)
            .that(eventDescriptions.stream().filter(d -> d.equals(failedRewoundAction)).count())
            .isEqualTo(expectedFailedRewoundEventCount);
      }
    }
  }

  public static String progressMessageOrPrettyPrint(ActionExecutionMetadata action) {
    String progressMessage = action.getProgressMessage();
    return progressMessage != null ? progressMessage : action.prettyPrint();
  }
}
