// Copyright (c) 2017, 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.R8RunArtTestsTest.CompilerUnderTest;
import com.android.tools.r8.R8RunArtTestsTest.DexTool;
import com.android.tools.r8.ToolHelper.DexVm;
import com.android.tools.r8.errors.Unreachable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.List;
import java.util.stream.Collectors;

public class TestCondition {

  enum Runtime {
    ART_V4_0_4,
    ART_V4_4_4,
    ART_V5_1_1,
    ART_V6_0_1,
    ART_V7_0_0,
    ART_V8_1_0,
    ART_V9_0_0,
    ART_V10_0_0,
    ART_V12_0_0,
    ART_V13_0_0,
    ART_V14_0_0,
    ART_DEFAULT,
    ART_MASTER,
    JAVA;

    static final Runtime LOWEST_ART_VERSION = ART_V4_0_4;
    static final Runtime HIGHEST_ART_VERSION = ART_DEFAULT;

    static Runtime fromDexVmVersion(DexVm.Version version) {
      switch (version) {
        case V4_0_4:
          return ART_V4_0_4;
        case V4_4_4:
          return ART_V4_4_4;
        case V5_1_1:
          return ART_V5_1_1;
        case V6_0_1:
          return ART_V6_0_1;
        case V7_0_0:
          return ART_V7_0_0;
        case V8_1_0:
          return ART_V8_1_0;
        case V9_0_0:
          return ART_V9_0_0;
        case V10_0_0:
          return ART_V10_0_0;
        case V12_0_0:
          return ART_V12_0_0;
        case V13_0_0:
          return ART_V13_0_0;
        case V14_0_0:
          return ART_V14_0_0;
        case DEFAULT:
          return ART_DEFAULT;
        case MASTER:
          return ART_MASTER;
        default:
          throw new Unreachable();
      }
    }
  }

  static class ToolSet {

    final EnumSet<DexTool> set;

    public ToolSet(EnumSet<DexTool> set) {
      this.set = set;
    }
  }

  static class CompilerSet {

    final EnumSet<CompilerUnderTest> set;

    public CompilerSet(EnumSet<CompilerUnderTest> set) {
      this.set = set;
    }
  }

  static class RuntimeSet {

    private final EnumSet<Runtime> set;

    public RuntimeSet(EnumSet<Runtime> set) {
      this.set = set;
    }

    public static RuntimeSet fromDexVmVersionSet(EnumSet<DexVm.Version> dexVmSet) {
      List<Runtime> list = new ArrayList<>(dexVmSet.size());
      for (DexVm.Version version : dexVmSet) {
        list.add(Runtime.fromDexVmVersion(version));
      }
      return new RuntimeSet(EnumSet.copyOf(list));
    }

    boolean contains(Runtime runtime) {
      return set.contains(runtime);
    }
  }

  static class CompilationModeSet {

    final EnumSet<CompilationMode> set;

    public CompilationModeSet(EnumSet<CompilationMode> set) {
      this.set = set;
    }
  }

  public static final CompilerSet D8_COMPILER =
      compilers(CompilerUnderTest.D8, CompilerUnderTest.D8_AFTER_R8CF);
  public static final CompilerSet D8_NOT_AFTER_R8CF_COMPILER = compilers(CompilerUnderTest.D8);
  public static final CompilerSet D8_AFTER_R8CF_COMPILER =
      compilers(CompilerUnderTest.D8_AFTER_R8CF);
  // R8_COMPILER refers to R8 both in the standalone setting and after D8
  // R8_NOT_AFTER_D8_COMPILER and R8_AFTER_D8_COMPILER refers to the standalone and the combined
  // settings, respectively
  public static final CompilerSet R8_COMPILER =
      compilers(
          CompilerUnderTest.R8,
          CompilerUnderTest.R8_AFTER_D8,
          CompilerUnderTest.D8_AFTER_R8CF,
          CompilerUnderTest.R8CF);
  public static final CompilerSet R8DEX_COMPILER =
      compilers(CompilerUnderTest.R8, CompilerUnderTest.R8_AFTER_D8);
  public static final CompilerSet R8CF = compilers(CompilerUnderTest.R8CF);

  public static final CompilationModeSet DEBUG_MODE =
      new CompilationModeSet(EnumSet.of(CompilationMode.DEBUG));
  public static final CompilationModeSet RELEASE_MODE =
      new CompilationModeSet(EnumSet.of(CompilationMode.RELEASE));

  private static final ToolSet ANY_TOOL = new ToolSet(EnumSet.allOf(DexTool.class));
  private static final CompilerSet ANY_COMPILER =
      new CompilerSet(EnumSet.allOf(CompilerUnderTest.class));
  private static final RuntimeSet ANY_RUNTIME = new RuntimeSet(EnumSet.allOf(Runtime.class));
  private static final RuntimeSet ANY_DEX_VM_RUNTIME =
      RuntimeSet.fromDexVmVersionSet(EnumSet.allOf(ToolHelper.DexVm.Version.class));
  public static final RuntimeSet JAVA_RUNTIME = new RuntimeSet(EnumSet.of(Runtime.JAVA));
  private static final CompilationModeSet ANY_MODE =
      new CompilationModeSet(EnumSet.allOf(CompilationMode.class));

  private final EnumSet<DexTool> dexTools;
  private final EnumSet<CompilerUnderTest> compilers;
  private final EnumSet<Runtime> runtimes;
  private final EnumSet<CompilationMode> compilationModes;

  public TestCondition(
      EnumSet<DexTool> dexTools,
      EnumSet<CompilerUnderTest> compilers,
      EnumSet<Runtime> runtimes,
      EnumSet<CompilationMode> compilationModes) {
    this.dexTools = dexTools;
    this.compilers = compilers;
    this.runtimes = runtimes;
    this.compilationModes = compilationModes;
  }

  public static ToolSet tools(DexTool... tools) {
    assert tools.length > 0;
    return new ToolSet(EnumSet.copyOf(Arrays.asList(tools)));
  }

  public static CompilerSet compilers(CompilerUnderTest... compilers) {
    assert compilers.length > 0;
    return new CompilerSet(EnumSet.copyOf(Arrays.asList(compilers)));
  }

  public static RuntimeSet runtimes(DexVm.Version... runtimes) {
    assert runtimes.length > 0;
    return RuntimeSet.fromDexVmVersionSet(EnumSet.copyOf(Arrays.asList(runtimes)));
  }

  public static RuntimeSet runtimes(Runtime... runtimes) {
    assert runtimes.length > 0;
    return new RuntimeSet(EnumSet.copyOf(Arrays.asList(runtimes)));
  }

  public static RuntimeSet runtimesUpTo(DexVm.Version upto) {
    return RuntimeSet.fromDexVmVersionSet(EnumSet.range(DexVm.Version.first(), upto));
  }

  public static RuntimeSet and(RuntimeSet... sets) {
    return new RuntimeSet(
        EnumSet.copyOf(
            Arrays.stream(sets)
                .flatMap(runtimeSet -> runtimeSet.set.stream())
                .collect(Collectors.toSet())));
  }

  public static TestCondition or(TestCondition... conditions) {
    return new OrTestCondition(conditions);
  }

  public static TestCondition match(
      ToolSet tools,
      CompilerSet compilers,
      RuntimeSet runtimes,
      CompilationModeSet compilationModes) {
    return new TestCondition(tools.set, compilers.set, runtimes.set, compilationModes.set);
  }

  public static TestCondition match(ToolSet tools, CompilerSet compilers, RuntimeSet runtimes) {
    return match(tools, compilers, runtimes, TestCondition.ANY_MODE);
  }

  public static TestCondition any() {
    return match(TestCondition.ANY_TOOL, TestCondition.ANY_COMPILER, TestCondition.ANY_RUNTIME);
  }

  public static TestCondition anyDexVm() {
    return match(
        TestCondition.ANY_TOOL, TestCondition.ANY_COMPILER, TestCondition.ANY_DEX_VM_RUNTIME);
  }

  public static TestCondition cf() {
    return match(TestCondition.ANY_TOOL, R8CF, JAVA_RUNTIME);
  }

  public static TestCondition match(ToolSet tools) {
    return match(tools, TestCondition.ANY_COMPILER, TestCondition.ANY_RUNTIME);
  }

  public static TestCondition match(ToolSet tools, CompilerSet compilers) {
    return match(tools, compilers, TestCondition.ANY_RUNTIME);
  }

  public static TestCondition match(ToolSet tools, RuntimeSet runtimes) {
    return match(tools, TestCondition.ANY_COMPILER, runtimes);
  }

  public static TestCondition match(CompilerSet compilers) {
    return match(TestCondition.ANY_TOOL, compilers, TestCondition.ANY_RUNTIME);
  }

  public static TestCondition match(CompilerSet compilers, CompilationModeSet compilationModes) {
    return match(TestCondition.ANY_TOOL, compilers, TestCondition.ANY_RUNTIME, compilationModes);
  }

  public static TestCondition match(CompilerSet compilers, RuntimeSet runtimes) {
    return match(TestCondition.ANY_TOOL, compilers, runtimes);
  }

  public static TestCondition match(RuntimeSet runtimes) {
    return match(TestCondition.ANY_TOOL, TestCondition.ANY_COMPILER, runtimes);
  }

  public boolean test(
      DexTool dexTool,
      CompilerUnderTest compilerUnderTest,
      Runtime runtime,
      CompilationMode compilationMode) {
    return dexTools.contains(dexTool)
        && compilers.contains(compilerUnderTest)
        && runtimes.contains(runtime)
        && compilationModes.contains(compilationMode);
  }

  public boolean test(
      DexTool dexTool,
      CompilerUnderTest compilerUnderTest,
      DexVm.Version version,
      CompilationMode compilationMode) {
    return test(dexTool, compilerUnderTest, Runtime.fromDexVmVersion(version), compilationMode);
  }

  public static class OrTestCondition extends TestCondition {

    private final TestCondition[] conditions;

    public OrTestCondition(TestCondition[] conditions) {
      super(null, null, null, null);
      this.conditions = conditions;
    }

    @Override
    public boolean test(
        DexTool dexTool,
        CompilerUnderTest compilerUnderTest,
        Runtime runtime,
        CompilationMode compilationMode) {
      for (TestCondition condition : conditions) {
        if (condition.test(dexTool, compilerUnderTest, runtime, compilationMode)) {
          return true;
        }
      }
      return false;
    }

    @Override
    public boolean test(
        DexTool dexTool,
        CompilerUnderTest compilerUnderTest,
        DexVm.Version version,
        CompilationMode compilationMode) {
      for (TestCondition condition : conditions) {
        if (condition.test(dexTool, compilerUnderTest, version, compilationMode)) {
          return true;
        }
      }
      return false;
    }
  }
}
