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

import com.android.tools.r8.errors.Unimplemented;
import com.android.tools.r8.utils.Pair;
import com.android.tools.r8.utils.ThrowingConsumer;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.google.common.base.Predicates;
import com.google.common.base.Strings;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.function.Consumer;
import java.util.function.Predicate;
import org.hamcrest.Matcher;

/** Checking container for checking the same properties of multiple run results. */
public abstract class TestRunResultCollection<
        C extends Enum<C>, RR extends TestRunResultCollection<C, RR>>
    extends TestRunResult<RR> {

  private final List<Pair<C, TestRunResult<?>>> runs;

  public TestRunResultCollection(List<Pair<C, TestRunResult<?>>> runs) {
    this.runs = runs;
  }

  private RR forEach(Consumer<TestRunResult<?>> fn) {
    runs.forEach(r -> fn.accept(r.getSecond()));
    return self();
  }

  @Override
  public RR assertSuccess() {
    return forEach(TestRunResult::assertSuccess);
  }

  @Override
  public RR assertFailure() {
    return forEach(TestRunResult::assertFailure);
  }

  @Override
  public RR assertStdoutMatches(Matcher<String> matcher) {
    return forEach(r -> r.assertStdoutMatches(matcher));
  }

  @Override
  public RR assertStderrMatches(Matcher<String> matcher) {
    return forEach(r -> r.assertStderrMatches(matcher));
  }

  @Override
  public <E extends Throwable> RR inspect(ThrowingConsumer<CodeInspector, E> consumer)
      throws IOException, ExecutionException, E {
    return inspectIf(Predicates.alwaysTrue(), consumer);
  }

  @Override
  public <E extends Throwable> RR inspectFailure(ThrowingConsumer<CodeInspector, E> consumer)
      throws IOException, E {
    throw new Unimplemented();
  }

  public RR applyIf(Predicate<C> filter, Consumer<TestRunResult<?>> thenConsumer) {
    return applyIf(filter, thenConsumer, r -> {});
  }

  public RR applyIf(
      Predicate<C> filter,
      Consumer<TestRunResult<?>> thenConsumer,
      Consumer<TestRunResult<?>> elseConsumer) {
    return applyIf(
        filter,
        thenConsumer,
        c -> true,
        elseConsumer,
        r -> {
          assert false;
        });
  }

  public RR applyIf(
      Predicate<C> filter1,
      Consumer<TestRunResult<?>> thenConsumer1,
      Predicate<C> filter2,
      Consumer<TestRunResult<?>> thenConsumer2,
      Consumer<TestRunResult<?>> elseConsumer) {
    return applyIf(
        filter1,
        thenConsumer1,
        filter2,
        thenConsumer2,
        c -> true,
        elseConsumer,
        r -> {
          assert false;
        });
  }

  public RR applyIf(
      Predicate<C> filter1,
      Consumer<TestRunResult<?>> thenConsumer1,
      Predicate<C> filter2,
      Consumer<TestRunResult<?>> thenConsumer2,
      Predicate<C> filter3,
      Consumer<TestRunResult<?>> thenConsumer3,
      Consumer<TestRunResult<?>> elseConsumer) {
    for (Pair<C, TestRunResult<?>> run : runs) {
      if (filter1.test(run.getFirst())) {
        thenConsumer1.accept(run.getSecond());
      } else if (filter2.test(run.getFirst())) {
        thenConsumer2.accept(run.getSecond());
      } else if (filter3.test(run.getFirst())) {
        thenConsumer3.accept(run.getSecond());
      } else {
        elseConsumer.accept(run.getSecond());
      }
    }
    return self();
  }

  public <E extends Throwable> RR inspectIf(
      Predicate<C> filter, ThrowingConsumer<CodeInspector, E> consumer)
      throws IOException, ExecutionException, E {
    for (Pair<C, TestRunResult<?>> run : runs) {
      if (filter.test(run.getFirst())) {
        run.getSecond().inspect(consumer);
      }
    }
    return self();
  }

  @Override
  public RR disassemble() throws IOException, ExecutionException {
    for (Pair<C, TestRunResult<?>> run : runs) {
      String name = run.getFirst().name();
      System.out.println(name + " " + Strings.repeat("=", 80 - name.length() - 1));
      run.getSecond().disassemble();
    }
    return self();
  }
}
