// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.regress;

import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;

import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import java.io.IOException;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

@RunWith(Parameterized.class)
public class Regress160394262Test extends TestBase {

  static final String EXPECTED = StringUtils.lines("1;2;3");

  private final TestParameters parameters;

  @Parameterized.Parameters(name = "{0}")
  public static TestParametersCollection data() {
    return getTestParameters().withAllRuntimes().withAllApiLevels().build();
  }

  public Regress160394262Test(TestParameters parameters) {
    this.parameters = parameters;
  }

  @Test
  public void testReference() throws Exception {
    testForRuntime(parameters)
        .addInnerClasses(Regress160394262Test.class)
        .run(parameters.getRuntime(), TestClass.class)
        .assertSuccessWithOutput(EXPECTED);
  }

  @Test
  public void testR8() throws Exception {
    testForR8(parameters.getBackend())
        .allowAccessModification()
        .addKeepMainRule(TestClass.class)
        .addInnerClasses(Regress160394262Test.class)
        .setMinApi(parameters.getApiLevel())
        .run(parameters.getRuntime(), TestClass.class)
        .assertSuccessWithOutput(EXPECTED)
        .inspect(this::checkJoinerIsClassInlined);
  }

  private void checkJoinerIsClassInlined(CodeInspector inspector) {
    assertThat(inspector.clazz(Joiner.class.getTypeName() + "$1"), not(isPresent()));
    // TODO(b/160640028): When compiling to DEX the outer Joiner class is not inlined.
    if (parameters.isDexRuntime()) {
      assertThat(inspector.clazz(Joiner.class), isPresent());
    } else {
      assertThat(inspector.clazz(Joiner.class), not(isPresent()));
    }
  }

  static class TestClass {

    public void foo(List<?> items) {
      System.out.println(Joiner.on(";").skipNulls().join(items));
    }

    public static void main(String[] args) {
      new TestClass().foo(Arrays.asList("1", 2, 3l, null));
    }
  }

  // Minimized copy of com.google.common.base.Preconditions
  static class Preconditions {

    public static <T> T checkNotNull(T reference) {
      if (reference == null) {
        throw new NullPointerException();
      } else {
        return reference;
      }
    }

    public static <T> T checkNotNull(T reference, Object errorMessage) {
      if (reference == null) {
        throw new NullPointerException(String.valueOf(errorMessage));
      } else {
        return reference;
      }
    }
  }

  // Minimized copy of com.google.common.base.Joiner
  static class Joiner {

    private final String separator;

    public static Joiner on(String separator) {
      return new Joiner(separator);
    }

    private Joiner(String separator) {
      this.separator = Preconditions.checkNotNull(separator);
    }

    private Joiner(Joiner prototype) {
      this.separator = prototype.separator;
    }

    public <A extends Appendable> A appendTo(A appendable, Iterator<?> parts) throws IOException {
      Preconditions.checkNotNull(appendable);
      if (parts.hasNext()) {
        appendable.append(this.toString(parts.next()));
        while (parts.hasNext()) {
          appendable.append(this.separator);
          appendable.append(this.toString(parts.next()));
        }
      }
      return appendable;
    }

    public final String join(Iterable<?> parts) {
      return join(parts.iterator());
    }

    public final String join(Iterator<?> parts) {
      StringBuilder builder = new StringBuilder();
      try {
        appendTo((Appendable) builder, parts);
        return builder.toString();
      } catch (IOException e) {
        throw new AssertionError(e);
      }
    }

    public Joiner skipNulls() {
      return new Joiner(this) {
        public <A extends Appendable> A appendTo(A appendable, Iterator<?> parts)
            throws IOException {
          Preconditions.checkNotNull(appendable, "appendable");
          Preconditions.checkNotNull(parts, "parts");
          Object part;
          while (parts.hasNext()) {
            part = parts.next();
            if (part != null) {
              appendable.append(Joiner.this.toString(part));
              break;
            }
          }
          while (parts.hasNext()) {
            part = parts.next();
            if (part != null) {
              appendable.append(Joiner.this.separator);
              appendable.append(Joiner.this.toString(part));
            }
          }
          return appendable;
        }
      };
    }

    CharSequence toString(Object part) {
      Preconditions.checkNotNull(part);
      return part instanceof CharSequence ? (CharSequence) part : part.toString();
    }
  }
}
