// Copyright (c) 2019, 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.utils.codeinspector;

import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexMethod;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;

public class CodeMatchers {

  public static Matcher<MethodSubject> accessesField(FieldSubject targetSubject) {
    if (!targetSubject.isPresent()) {
      throw new IllegalArgumentException();
    }
    DexField target = targetSubject.getField().getReference();
    return new TypeSafeMatcher<MethodSubject>() {
      @Override
      protected boolean matchesSafely(MethodSubject subject) {
        if (!subject.isPresent()) {
          return false;
        }
        if (!subject.getMethod().hasCode()) {
          return false;
        }
        return subject.streamInstructions().anyMatch(isFieldAccessWithTarget(target));
      }

      @Override
      public void describeTo(Description description) {
        description.appendText("accesses field `" + target.toSourceString() + "`");
      }

      @Override
      public void describeMismatchSafely(final MethodSubject subject, Description description) {
        description.appendText("method did not");
      }
    };
  }

  public static Matcher<MethodSubject> containsThrow() {
    return new TypeSafeMatcher<MethodSubject>() {
      @Override
      protected boolean matchesSafely(MethodSubject subject) {
        return subject.isPresent()
            && subject.getMethod().hasCode()
            && subject.streamInstructions().anyMatch(InstructionSubject::isThrow);
      }

      @Override
      public void describeTo(Description description) {
        description.appendText("contains throw");
      }

      @Override
      public void describeMismatchSafely(final MethodSubject subject, Description description) {
        description.appendText("method did not");
      }
    };
  }

  public static Matcher<MethodSubject> instantiatesClass(Class<?> clazz) {
    return instantiatesClass(clazz.getTypeName());
  }

  public static Matcher<MethodSubject> instantiatesClass(String clazz) {
    return new TypeSafeMatcher<MethodSubject>() {
      @Override
      protected boolean matchesSafely(MethodSubject subject) {
        if (!subject.isPresent()) {
          return false;
        }
        if (!subject.getMethod().hasCode()) {
          return false;
        }
        return subject
            .streamInstructions()
            .anyMatch(instruction -> instruction.isNewInstance(clazz));
      }

      @Override
      public void describeTo(Description description) {
        description.appendText("instantiates class `" + clazz + "`");
      }

      @Override
      public void describeMismatchSafely(final MethodSubject subject, Description description) {
        description.appendText("method did not");
      }
    };
  }

  public static Matcher<MethodSubject> invokesMethod(MethodSubject targetSubject) {
    if (!targetSubject.isPresent()) {
      throw new IllegalArgumentException();
    }
    DexMethod target = targetSubject.getMethod().getReference();
    return new TypeSafeMatcher<MethodSubject>() {
      @Override
      protected boolean matchesSafely(MethodSubject subject) {
        if (!subject.isPresent()) {
          return false;
        }
        if (!subject.getMethod().hasCode()) {
          return false;
        }
        return subject.streamInstructions().anyMatch(isInvokeWithTarget(target));
      }

      @Override
      public void describeTo(Description description) {
        description.appendText("invokes method `" + target.toSourceString() + "`");
      }

      @Override
      public void describeMismatchSafely(final MethodSubject subject, Description description) {
        description.appendText("method did not");
      }
    };
  }

  public static Matcher<MethodSubject> invokesMethod(
      String returnType, String holderType, String methodName, List<String> parameterTypes) {
    return new TypeSafeMatcher<MethodSubject>() {
      @Override
      protected boolean matchesSafely(MethodSubject subject) {
        if (!subject.isPresent()) {
          return false;
        }
        if (!subject.getMethod().hasCode()) {
          return false;
        }
        return subject
            .streamInstructions()
            .anyMatch(isInvokeWithTarget(returnType, holderType, methodName, parameterTypes));
      }

      @Override
      public void describeTo(Description description) {
        StringBuilder text =
            new StringBuilder("invokes method `")
                .append(returnType != null ? returnType : "*")
                .append(" ")
                .append(holderType != null ? holderType : "*")
                .append(".")
                .append(methodName != null ? methodName : "*")
                .append("(");
        if (parameterTypes != null) {
          text.append(
              parameterTypes.stream()
                  .map(parameterType -> parameterType != null ? parameterType : "*")
                  .collect(Collectors.joining(", ")));
        } else {
          text.append("...");
        }
        text.append(")`");
        description.appendText(text.toString());
      }

      @Override
      public void describeMismatchSafely(final MethodSubject subject, Description description) {
        description.appendText("method did not");
      }
    };
  }

  public static Matcher<MethodSubject> invokesMethodWithHolderAndName(
      String holderType, String name) {
    return invokesMethod(null, holderType, name, null);
  }

  public static Matcher<MethodSubject> invokesMethodWithName(String name) {
    return invokesMethod(null, null, name, null);
  }

  public static Predicate<InstructionSubject> isInvokeWithTarget(MethodSubject target) {
    return isInvokeWithTarget(target.getMethod().getReference());
  }

  public static Predicate<InstructionSubject> isInvokeWithTarget(DexMethod target) {
    return instruction -> instruction.isInvoke() && instruction.getMethod() == target;
  }

  public static Predicate<InstructionSubject> isInvokeWithTarget(
      String returnType, String holderType, String methodName, String... parameterTypes) {
    return isInvokeWithTarget(returnType, holderType, methodName, Arrays.asList(parameterTypes));
  }

  public static Predicate<InstructionSubject> isInvokeWithTarget(
      String holderType, String methodName) {
    return isInvokeWithTarget(null, holderType, methodName, (List<String>) null);
  }

  public static Predicate<InstructionSubject> isInvokeWithTarget(
      String returnType, String holderType, String methodName, List<String> parameterTypes) {
    return instruction -> {
      if (!instruction.isInvoke()) {
        return false;
      }
      DexMethod invokedMethod = instruction.getMethod();
      if (returnType != null
          && !invokedMethod.getReturnType().toSourceString().equals(returnType)) {
        return false;
      }
      if (holderType != null
          && !invokedMethod.getHolderType().toSourceString().equals(holderType)) {
        return false;
      }
      if (methodName != null && !invokedMethod.getName().toSourceString().equals(methodName)) {
        return false;
      }
      if (parameterTypes != null) {
        if (parameterTypes.size() != invokedMethod.getArity()) {
          return false;
        }
        for (int i = 0; i < parameterTypes.size(); i++) {
          String parameterType = parameterTypes.get(i);
          if (parameterType != null
              && !invokedMethod.getParameter(i).toSourceString().equals(parameterType)) {
            return false;
          }
        }
      }
      return true;
    };
  }

  public static Predicate<InstructionSubject> isFieldAccessWithTarget(DexField target) {
    return instruction -> instruction.isFieldAccess() && instruction.getField() == target;
  }
}
