// 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.cmdline.RepositoryMapping;
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);

    assertThat(uiStateTracker.buildStatus).isEqualTo(BuildStatus.BUILD_NOT_STARTED);
    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(), RepositoryMapping.ALWAYS_FALLBACK));

    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;
  }
}
