// Copyright 2020 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.analysis.starlark;

import static com.google.common.truth.Truth.assertThat;
import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.common.collect.ImmutableList;
import com.google.common.io.CharStreams;
import com.google.devtools.build.lib.actions.ParameterFile;
import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStreamReader;
import net.starlark.java.eval.Mutability;
import net.starlark.java.eval.Starlark;
import net.starlark.java.eval.StarlarkList;
import net.starlark.java.eval.StarlarkThread;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/**
 * Checks the result of each variant {@code Args.add*} call, in flag_per_line format. Note, writes
 * the
 */
@RunWith(JUnit4.class)
public class FlagPerLineTest extends BuildViewTestCase {

  // Initially empty, with "flag_per_line" format.
  private Args args;
  private final Mutability mutability = Mutability.create();
  private StarlarkThread thread;

  @Before
  public void initArgs() throws Exception {
    args = Args.newArgs(mutability, getStarlarkSemantics());
    args.setParamFileFormat("flag_per_line");
    thread = new StarlarkThread(mutability, getStarlarkSemantics());
  }

  @Test
  public void add_noname() throws Exception {
    args.addArgument("--foo", Starlark.UNBOUND, /* format= */ Starlark.NONE, thread);
    expectLines("--foo");
  }

  @Test
  public void add_name() throws Exception {
    args.addArgument("--foo", "bar", /* format= */ Starlark.NONE, thread);
    expectLines("--foo=bar");
  }

  @Test
  public void add_all_noname() throws Exception {
    args.addAll(
        /* argNameOrValue= */ "", // ignored
        /* values= */ StarlarkList.of(null, "--foo", "bar", "baz"),
        /* mapEach= */ Starlark.NONE,
        /* formatEach= */ Starlark.NONE,
        /* beforeEach= */ Starlark.NONE,
        /* omitIfEmpty= */ true, // the default
        /* uniquify= */ false,
        /* expandDirectories= */ false,
        /* terminateWith= */ Starlark.NONE,
        thread);
    // Absl would reject this line, but it's what we generate.
    expectLines("--foo bar baz");
  }

  @Test
  public void add_all_name() throws Exception {
    args.addAll(
        /* argNameOrValue= */ "--foo",
        /* values= */ StarlarkList.of(null, "bar", "baz"),
        /* mapEach= */ Starlark.NONE,
        /* formatEach= */ Starlark.NONE,
        /* beforeEach= */ Starlark.NONE,
        /* omitIfEmpty= */ true, // the default
        /* uniquify= */ false,
        /* expandDirectories= */ false,
        /* terminateWith= */ Starlark.NONE,
        thread);
    // Absl interprets this as a single value "bar baz" for the flag "--foo",
    // which is probably not what was intended.
    expectLines("--foo=bar baz");
  }

  @Test
  public void add_joined_noname() throws Exception {
    args.addJoined(
        /* argNameOrValue= */ "", // ignored
        /* values= */ StarlarkList.of(null, "--foo", "bar", "baz"),
        /* joinWith= */ ",",
        /* mapEach= */ Starlark.NONE,
        /* formatEach= */ Starlark.NONE,
        /* formatJoined= */ Starlark.NONE,
        /* omitIfEmpty= */ true, // the default
        /* uniquify= */ false,
        /* expandDirectories= */ false,
        thread);
    // Absl would reject this line, but it's what we generate.
    expectLines("--foo,bar,baz");
  }

  @Test
  public void add_joined_name() throws Exception {
    args.addJoined(
        /* argNameOrValue= */ "--foo",
        /* values= */ StarlarkList.of(null, "bar", "baz", "woof"),
        /* joinWith= */ ",",
        /* mapEach= */ Starlark.NONE,
        /* formatEach= */ Starlark.NONE,
        /* formatJoined= */ Starlark.NONE,
        /* omitIfEmpty= */ true,
        /* uniquify= */ false,
        /* expandDirectories= */ false,
        thread);
    expectLines("--foo=bar,baz,woof");
  }

  private void expectLines(String... lines) throws Exception {
    assertThat(toParamFile(args)).containsExactly((Object[]) lines).inOrder();
  }

  /** Writes out the Args using ParameterFile, returns the output broken down as lines. */
  private static ImmutableList<String> toParamFile(Args args) throws Exception {
    byte[] bytes;
    try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
      ParameterFile.writeParameterFile(
          outputStream, args.build().arguments(), args.getParameterFileType(), UTF_8);
      bytes = outputStream.toByteArray();
    }
    try (ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
        InputStreamReader reader = new InputStreamReader(inputStream, UTF_8)) {
      return ImmutableList.copyOf(CharStreams.readLines(reader));
    }
  }
}
