// 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.runtime;

import static com.google.common.truth.Truth.assertThat;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.buildtool.BuildResult;
import com.google.devtools.build.lib.buildtool.ExecutionProgressReceiver;
import com.google.devtools.build.lib.buildtool.buildevent.BuildCompleteEvent;
import com.google.devtools.build.lib.buildtool.buildevent.ExecutionProgressReceiverAvailableEvent;
import com.google.devtools.build.lib.pkgcache.LoadingPhaseCompleteEvent;
import com.google.devtools.build.lib.runtime.SkymeldUiStateTracker.BuildStatus;
import com.google.devtools.build.lib.skyframe.ConfigurationPhaseStartedEvent;
import com.google.devtools.build.lib.skyframe.ConfiguredTargetProgressReceiver;
import com.google.devtools.build.lib.skyframe.LoadingPhaseStartedEvent;
import com.google.devtools.build.lib.skyframe.PackageProgressReceiver;
import com.google.devtools.build.lib.testutil.FoundationTestCase;
import com.google.devtools.build.lib.testutil.ManualClock;
import com.google.devtools.build.lib.util.DetailedExitCode;
import com.google.devtools.build.lib.util.Pair;
import com.google.devtools.build.lib.util.io.LoggingTerminalWriter;
import com.google.devtools.build.lib.util.io.PositionAwareAnsiTerminalWriter;
import java.io.IOException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Tests {@link SkymeldUiStateTracker}. */
@RunWith(JUnit4.class)
public class SkymeldUiStateTrackerTest extends FoundationTestCase {

  @Test
  public void buildStarted_stateChanges() {
    ManualClock clock = new ManualClock();
    SkymeldUiStateTracker uiStateTracker = new SkymeldUiStateTracker(clock);

    uiStateTracker.buildStarted();
    assertThat(uiStateTracker.buildStatus).isEqualTo(BuildStatus.BUILD_STARTED);
  }

  @Test
  public void loadingStarted_stateChanges() {
    ManualClock clock = new ManualClock();
    SkymeldUiStateTracker uiStateTracker = new SkymeldUiStateTracker(clock);
    uiStateTracker.buildStatus = BuildStatus.BUILD_STARTED;

    uiStateTracker.loadingStarted(
        new LoadingPhaseStartedEvent(mock(PackageProgressReceiver.class)));

    assertThat(uiStateTracker.buildStatus).isEqualTo(BuildStatus.TARGET_PATTERN_PARSING);
  }

  @Test
  public void loadingComplete_stateChanges() {
    ManualClock clock = new ManualClock();
    SkymeldUiStateTracker uiStateTracker = new SkymeldUiStateTracker(clock);
    uiStateTracker.buildStatus = BuildStatus.TARGET_PATTERN_PARSING;

    uiStateTracker.loadingComplete(
        new LoadingPhaseCompleteEvent(ImmutableSet.of(), ImmutableSet.of()));

    assertThat(uiStateTracker.buildStatus).isEqualTo(BuildStatus.LOADING_COMPLETE);
  }

  @Test
  public void configurationStarted_stateChanges() {
    ManualClock clock = new ManualClock();
    SkymeldUiStateTracker uiStateTracker = new SkymeldUiStateTracker(clock);
    uiStateTracker.buildStatus = BuildStatus.LOADING_COMPLETE;

    uiStateTracker.configurationStarted(
        new ConfigurationPhaseStartedEvent(mock(ConfiguredTargetProgressReceiver.class)));

    assertThat(uiStateTracker.buildStatus).isEqualTo(BuildStatus.CONFIGURATION);
  }

  @Test
  public void analysisAndExecution_stateChangesAndWriteProgressBar() throws IOException {
    ManualClock clock = new ManualClock();
    SkymeldUiStateTracker uiStateTracker = new SkymeldUiStateTracker(clock);
    String additionalMessage = "5 targets";
    uiStateTracker.buildStatus = BuildStatus.CONFIGURATION;
    uiStateTracker.additionalMessage = additionalMessage;

    // First we need to set up the state tracker to already be analysing.
    String loadingState = "42 packages loaded";
    String loadingActivity = "currently loading //src/foo/bar and 17 more";
    uiStateTracker.packageProgressReceiver =
        mockPackageProgressReceiver(loadingState, loadingActivity);

    String configuredTargetProgressString = "5 targets configured";
    uiStateTracker.configuredTargetProgressReceiver =
        mockConfiguredTargetProgressReceiver(configuredTargetProgressString);

    // Mock starting execution while configuring (before analysis complete).
    ExecutionProgressReceiver executionProgressReceiver = new ExecutionProgressReceiver(0, null);
    uiStateTracker.progressReceiverAvailable(
        new ExecutionProgressReceiverAvailableEvent(executionProgressReceiver));

    assertThat(uiStateTracker.buildStatus).isEqualTo(BuildStatus.ANALYSIS_AND_EXECUTION);

    LoggingTerminalWriter terminalWriter = new LoggingTerminalWriter(/*discardHighlight=*/ true);
    uiStateTracker.writeProgressBar(terminalWriter);
    String output = terminalWriter.getTranscript();
    // Should write analysis and execution information.
    assertThat(output).contains("Analyzing");
    assertThat(output).contains(additionalMessage);
    assertThat(output).contains(loadingState);
    assertThat(output).contains(loadingActivity);
    assertThat(output).contains(configuredTargetProgressString);
    assertThat(output).contains("[0 / 0]");
  }

  @Test
  public void executionFromAnalysisAndExecution_stateChanges() {
    ManualClock clock = new ManualClock();
    SkymeldUiStateTracker uiStateTracker = new SkymeldUiStateTracker(clock);
    uiStateTracker.buildStatus = BuildStatus.ANALYSIS_AND_EXECUTION;

    uiStateTracker.analysisComplete();

    assertThat(uiStateTracker.buildStatus).isEqualTo(BuildStatus.EXECUTION);
  }

  @Test
  public void buildCompleted_stateChanges() {
    ManualClock clock = new ManualClock();
    SkymeldUiStateTracker uiStateTracker = new SkymeldUiStateTracker(clock);
    uiStateTracker.buildStatus = BuildStatus.EXECUTION;

    BuildResult buildResult = new BuildResult(clock.currentTimeMillis());
    buildResult.setDetailedExitCode(DetailedExitCode.success());
    clock.advanceMillis(SECONDS.toMillis(1));
    buildResult.setStopTime(clock.currentTimeMillis());
    uiStateTracker.buildComplete(new BuildCompleteEvent(buildResult));

    assertThat(uiStateTracker.buildStatus).isEqualTo(BuildStatus.BUILD_COMPLETED);
  }

  @Test
  public void testWriteBaseProgress() throws IOException {
    ManualClock clock = new ManualClock();
    SkymeldUiStateTracker uiStateTracker = new SkymeldUiStateTracker(clock);
    String status = "status";
    String message = "hello";

    uiStateTracker.buildStarted();
    uiStateTracker.ok = true;
    LoggingTerminalWriter okTerminalWriter = new LoggingTerminalWriter(/*discardHighlight=*/ false);
    uiStateTracker.writeBaseProgress(
        status, message, new PositionAwareAnsiTerminalWriter(okTerminalWriter));
    assertOutputContainsBaseProgress(
        okTerminalWriter.getTranscript(), status, message, /*ok=*/ true);

    uiStateTracker.ok = false;
    LoggingTerminalWriter notOkTerminalWriter =
        new LoggingTerminalWriter(/*discardHighlight=*/ false);
    uiStateTracker.writeBaseProgress(
        status, message, new PositionAwareAnsiTerminalWriter(notOkTerminalWriter));
    assertOutputContainsBaseProgress(
        notOkTerminalWriter.getTranscript(), status, message, /*ok=*/ false);
  }

  @Test
  public void testWriteLoadingAnalysisPhaseProgress() throws IOException {
    ManualClock clock = new ManualClock();
    SkymeldUiStateTracker uiStateTracker = new SkymeldUiStateTracker(clock);
    uiStateTracker.ok = true;
    String status = "status";
    String message = "message";
    String loadingState = "42 packages loaded";
    String loadingActivity = "currently loading //src/foo/bar and 17 more";
    String configuredTargetProgressString = "5 targets configured";

    // Mock starting loading.
    LoggingTerminalWriter terminalWriter = new LoggingTerminalWriter(/*discardHighlight=*/ false);
    uiStateTracker.buildStatus = BuildStatus.TARGET_PATTERN_PARSING;
    uiStateTracker.packageProgressReceiver =
        mockPackageProgressReceiver(loadingState, loadingActivity);

    // Output should only contain loading-related output.
    uiStateTracker.writeLoadingAnalysisPhaseProgress(
        status,
        message,
        new PositionAwareAnsiTerminalWriter(terminalWriter),
        /*shortVersion=*/ false);
    String loadingOutput = terminalWriter.getTranscript();
    assertOutputContainsBaseProgress(loadingOutput, status, message, /*ok=*/ true);
    assertThat(loadingOutput).contains("(" + loadingState + ")");
    assertThat(loadingOutput).contains(loadingActivity);
    assertThat(loadingOutput).doesNotContain(configuredTargetProgressString);

    terminalWriter.reset();
    // When there is an empty message (only happens during target pattern parsing).
    uiStateTracker.writeLoadingAnalysisPhaseProgress(
        status,
        /*message=*/ "",
        new PositionAwareAnsiTerminalWriter(terminalWriter),
        /*shortVersion=*/ false);
    String emptyMessageLoadingOutput = terminalWriter.getTranscript();
    assertOutputContainsBaseProgress(
        emptyMessageLoadingOutput, status, /*message=*/ "", /*ok=*/ true);
    // The loading state should not be parenthesized.
    assertThat(emptyMessageLoadingOutput).doesNotContain("(" + loadingState + ")");
    assertThat(emptyMessageLoadingOutput).contains(loadingState);
    assertThat(emptyMessageLoadingOutput).contains(loadingActivity);
    assertThat(emptyMessageLoadingOutput).doesNotContain(configuredTargetProgressString);

    terminalWriter.reset();
    // When writing as a short version.
    uiStateTracker.writeLoadingAnalysisPhaseProgress(
        status,
        message,
        new PositionAwareAnsiTerminalWriter(terminalWriter),
        /*shortVersion=*/ true);
    String shortVersionLoadingOutput = terminalWriter.getTranscript();
    assertOutputContainsBaseProgress(shortVersionLoadingOutput, status, message, /*ok=*/ true);
    // Output should only contain the loading state but not the activity.
    assertThat(shortVersionLoadingOutput).contains(loadingState);
    assertThat(shortVersionLoadingOutput).doesNotContain(loadingActivity);
    assertThat(emptyMessageLoadingOutput).doesNotContain(configuredTargetProgressString);

    terminalWriter.reset();
    // Mock starting configuration.
    uiStateTracker.configuredTargetProgressReceiver =
        mockConfiguredTargetProgressReceiver(configuredTargetProgressString);
    uiStateTracker.buildStatus = BuildStatus.CONFIGURATION;

    // Output should contain both loading and analysis related output.
    uiStateTracker.writeLoadingAnalysisPhaseProgress(
        status,
        message,
        new PositionAwareAnsiTerminalWriter(terminalWriter),
        /*shortVersion=*/ false);
    String loadingAnalysisOutput = terminalWriter.getTranscript();
    assertOutputContainsBaseProgress(loadingAnalysisOutput, status, message, /*ok=*/ true);
    assertThat(loadingAnalysisOutput).contains(loadingState);
    assertThat(loadingAnalysisOutput).contains(loadingActivity);
    assertThat(loadingAnalysisOutput).contains(configuredTargetProgressString);
  }

  private static void assertOutputContainsBaseProgress(
      String output, String status, String message, boolean ok) {
    String okIndicator = ok ? LoggingTerminalWriter.OK : LoggingTerminalWriter.FAIL;
    assertThat(output)
        .contains(okIndicator + status + ":" + LoggingTerminalWriter.NORMAL + " " + message);
  }

  private static PackageProgressReceiver mockPackageProgressReceiver(
      String state, String activity) {
    PackageProgressReceiver packageProgressReceiver = mock(PackageProgressReceiver.class);
    when(packageProgressReceiver.progressState()).thenReturn(new Pair<>(state, activity));
    return packageProgressReceiver;
  }

  private static ConfiguredTargetProgressReceiver mockConfiguredTargetProgressReceiver(
      String progress) {
    ConfiguredTargetProgressReceiver configuredTargetProgressReceiver =
        mock(ConfiguredTargetProgressReceiver.class);
    when(configuredTargetProgressReceiver.getProgressString()).thenReturn(progress);
    return configuredTargetProgressReceiver;
  }
}
