// 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());
    var unused = 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;
  }
}
