// Copyright (c) 2016, 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.shaking;

import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.shaking.ProguardConfigurationParser.IdentifierPatternWithWildcards;
import com.android.tools.r8.utils.StringUtils;
import com.google.common.collect.Iterables;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

public class ProguardMemberRule {

  public static class Builder {

    private List<ProguardTypeMatcher> annotations = Collections.emptyList();
    private ProguardAccessFlags accessFlags = new ProguardAccessFlags();
    private ProguardAccessFlags negatedAccessFlags = new ProguardAccessFlags();
    private ProguardMemberType ruleType;
    private ProguardTypeMatcher type;
    private ProguardNameMatcher name;
    private List<ProguardTypeMatcher> arguments;
    private ProguardMemberRuleReturnValue returnValue;

    private Builder() {}

    public void setAnnotations(List<ProguardTypeMatcher> annotations) {
      assert annotations != null;
      this.annotations = annotations;
    }

    public ProguardAccessFlags getAccessFlags() {
      return accessFlags;
    }

    public Builder setAccessFlags(ProguardAccessFlags flags) {
      accessFlags = flags;
      return this;
    }

    public ProguardAccessFlags getNegatedAccessFlags() {
      return negatedAccessFlags;
    }

    public void setNegatedAccessFlags(ProguardAccessFlags flags) {
      negatedAccessFlags = flags;
    }

    public Builder setRuleType(ProguardMemberType ruleType) {
      this.ruleType = ruleType;
      return this;
    }

    public ProguardTypeMatcher getTypeMatcher() {
      return type;
    }

    public Builder setTypeMatcher(ProguardTypeMatcher type) {
      this.type = type;
      return this;
    }

    public Builder setName(IdentifierPatternWithWildcards identifierPatternWithWildcards) {
      this.name = ProguardNameMatcher.create(identifierPatternWithWildcards);
      return this;
    }

    public Builder setArguments(List<ProguardTypeMatcher> arguments) {
      this.arguments = arguments;
      return this;
    }

    public Builder setReturnValue(ProguardMemberRuleReturnValue value) {
      returnValue = value;
      return this;
    }

    public boolean isValid() {
      return ruleType != null;
    }

    public ProguardMemberRule build() {
      assert isValid();
      return new ProguardMemberRule(
          annotations,
          accessFlags,
          negatedAccessFlags,
          ruleType,
          type,
          name,
          arguments,
          returnValue);
    }
  }

  private final List<ProguardTypeMatcher> annotations;
  private final ProguardAccessFlags accessFlags;
  private final ProguardAccessFlags negatedAccessFlags;
  private final ProguardMemberType ruleType;
  private final ProguardTypeMatcher type;
  private final ProguardNameMatcher name;
  private final List<ProguardTypeMatcher> arguments;
  private final ProguardMemberRuleReturnValue returnValue;

  private ProguardMemberRule(
      List<ProguardTypeMatcher> annotations,
      ProguardAccessFlags accessFlags,
      ProguardAccessFlags negatedAccessFlags,
      ProguardMemberType ruleType,
      ProguardTypeMatcher type,
      ProguardNameMatcher name,
      List<ProguardTypeMatcher> arguments,
      ProguardMemberRuleReturnValue returnValue) {
    this.annotations = annotations;
    this.accessFlags = accessFlags;
    this.negatedAccessFlags = negatedAccessFlags;
    this.ruleType = ruleType;
    this.type = type;
    this.name = name;
    this.arguments = arguments != null ? Collections.unmodifiableList(arguments) : null;
    this.returnValue = returnValue;
  }

  /**
   * Create a new empty builder.
   */
  public static Builder builder() {
    return new Builder();
  }

  public List<ProguardTypeMatcher> getAnnotations() {
    return annotations;
  }

  public ProguardAccessFlags getAccessFlags() {
    return accessFlags;
  }

  public ProguardAccessFlags getNegatedAccessFlags() {
    return negatedAccessFlags;
  }

  public ProguardMemberType getRuleType() {
    return ruleType;
  }

  public ProguardTypeMatcher getType() {
    return type;
  }

  public ProguardNameMatcher getName() {
    return name;
  }

  public List<ProguardTypeMatcher> getArguments() {
    return arguments;
  }

  public boolean hasReturnValue() {
    return returnValue != null;
  }

  public ProguardMemberRuleReturnValue getReturnValue() {
    return returnValue;
  }

  public ProguardTypeMatcher getTypeMatcher() {
    return type;
  }

  public boolean matches(
      DexEncodedField field,
      AppView<?> appView,
      Consumer<AnnotationMatchResult> matchedAnnotationsConsumer,
      DexStringCache stringCache) {
    DexField originalSignature = appView.graphLens().getOriginalFieldSignature(field.field);
    switch (getRuleType()) {
      case ALL:
      case ALL_FIELDS:
        {
          // Access flags check.
          if (!getAccessFlags().containsAll(field.accessFlags)
              || !getNegatedAccessFlags().containsNone(field.accessFlags)) {
            break;
          }
          // Annotations check.
          return RootSetBuilder.containsAllAnnotations(
              annotations, field, matchedAnnotationsConsumer);
        }

      case FIELD:
        {
          // Name check.
          String name = stringCache.lookupString(originalSignature.name);
          if (!getName().matches(name)) {
            break;
          }
          // Access flags check.
          if (!getAccessFlags().containsAll(field.accessFlags)
              || !getNegatedAccessFlags().containsNone(field.accessFlags)) {
            break;
          }
          // Type check.
          if (!getType().matches(originalSignature.type, appView)) {
            break;
          }
          // Annotations check
          return RootSetBuilder.containsAllAnnotations(
              annotations, field, matchedAnnotationsConsumer);
        }

      case ALL_METHODS:
      case CLINIT:
      case INIT:
      case CONSTRUCTOR:
      case METHOD:
        break;
    }
    return false;
  }

  public boolean matches(
      DexEncodedMethod method,
      AppView<?> appView,
      Consumer<AnnotationMatchResult> matchedAnnotationsConsumer,
      DexStringCache stringCache) {
    DexMethod originalSignature = appView.graphLens().getOriginalMethodSignature(method.method);
    switch (getRuleType()) {
      case ALL_METHODS:
        if (method.isClassInitializer()) {
          break;
        }
        // Fall through for all other methods.

      case ALL:
        {
          // Access flags check.
          if (!getAccessFlags().containsAll(method.accessFlags)
              || !getNegatedAccessFlags().containsNone(method.accessFlags)) {
            break;
          }
          // Annotations check.
          return RootSetBuilder.containsAllAnnotations(
              annotations, method, matchedAnnotationsConsumer);
        }

      case METHOD:
        // Check return type.
        if (!type.matches(originalSignature.proto.returnType, appView)) {
          break;
        }
        // Fall through for access flags, name and arguments.

      case CONSTRUCTOR:
      case INIT:
      case CLINIT:
        {
          // Name check.
          String name = stringCache.lookupString(originalSignature.name);
          if (!getName().matches(name)) {
            break;
          }
          // Access flags check.
          if (!getAccessFlags().containsAll(method.accessFlags)
              || !getNegatedAccessFlags().containsNone(method.accessFlags)) {
            break;
          }
          // Annotations check.
          if (!RootSetBuilder.containsAllAnnotations(
              annotations, method, matchedAnnotationsConsumer)) {
            return false;
          }
          // Parameter types check.
          List<ProguardTypeMatcher> arguments = getArguments();
          if (arguments.size() == 1 && arguments.get(0).isTripleDotPattern()) {
            return true;
          }
          DexType[] parameters = originalSignature.proto.parameters.values;
          if (parameters.length != arguments.size()) {
            break;
          }
          for (int i = 0; i < parameters.length; i++) {
            if (!arguments.get(i).matches(parameters[i], appView)) {
              return false;
            }
          }
          // All parameters matched.
          return true;
        }

      case ALL_FIELDS:
      case FIELD:
        break;
    }
    return false;
  }

  public boolean isSpecific() {
    switch (getRuleType()) {
      case ALL:
        // fall through
      case ALL_FIELDS:
        // fall through
      case ALL_METHODS:
        return false;
      default:
        return Iterables.size(getWildcards()) == 0;
    }
  }

  Iterable<ProguardWildcard> getWildcards() {
    return Iterables.concat(
        ProguardTypeMatcher.getWildcardsOrEmpty(annotations),
        ProguardTypeMatcher.getWildcardsOrEmpty(type),
        ProguardNameMatcher.getWildcardsOrEmpty(name),
        arguments != null
            ? arguments.stream()
                    .map(ProguardTypeMatcher::getWildcards)
                    .flatMap(it -> StreamSupport.stream(it.spliterator(), false))
                ::iterator
            : Collections::emptyIterator);
  }

  ProguardMemberRule materialize(DexItemFactory dexItemFactory) {
    return new ProguardMemberRule(
        ProguardTypeMatcher.materializeList(getAnnotations(), dexItemFactory),
        getAccessFlags(),
        getNegatedAccessFlags(),
        getRuleType(),
        getType() == null ? null : getType().materialize(dexItemFactory),
        getName() == null ? null : getName().materialize(),
        getArguments() == null
            ? null
            : getArguments().stream()
                .map(argument -> argument.materialize(dexItemFactory))
                .collect(Collectors.toList()),
        getReturnValue());
  }

  @Override
  public boolean equals(Object o) {
    if (!(o instanceof ProguardMemberRule)) {
      return false;
    }

    ProguardMemberRule that = (ProguardMemberRule) o;

    if (!annotations.equals(that.annotations)) {
      return false;
    }
    if (!accessFlags.equals(that.accessFlags)) {
      return false;
    }
    if (!negatedAccessFlags.equals(that.negatedAccessFlags)) {
      return false;
    }
    if (ruleType != that.ruleType) {
      return false;
    }
    if (name != null ? !name.equals(that.name) : that.name != null) {
      return false;
    }
    if (type != null ? !type.equals(that.type) : that.type != null) {
      return false;
    }
    return arguments != null ? arguments.equals(that.arguments) : that.arguments == null;
  }

  @Override
  public int hashCode() {
    int result = annotations.hashCode();
    result = 31 * result + accessFlags.hashCode();
    result = 31 * result + negatedAccessFlags.hashCode();
    result = 31 * result + (ruleType != null ? ruleType.hashCode() : 0);
    result = 31 * result + (type != null ? type.hashCode() : 0);
    result = 31 * result + (name != null ? name.hashCode() : 0);
    result = 31 * result + (arguments != null ? arguments.hashCode() : 0);
    return result;
  }

  @Override
  public String toString() {
    StringBuilder result = new StringBuilder();
    for (ProguardTypeMatcher annotation : annotations) {
      ProguardKeepRule.appendNonEmpty(result, "@", annotation, " ");
    }
    ProguardKeepRule.appendNonEmpty(result, null, accessFlags, " ");
    ProguardKeepRule
        .appendNonEmpty(result, null, negatedAccessFlags.toString().replace(" ", " !"), " ");
    switch (getRuleType()) {
      case ALL_FIELDS:
        result.append("<fields>");
        break;
      case ALL_METHODS:
        result.append("<methods>");
        break;
      case METHOD:
        result.append(getType());
        result.append(' ');
        // Fall through for rest of method signature.
      case CONSTRUCTOR:
      case CLINIT:
      case INIT: {
        result.append(getName());
        result.append('(');
        result.append(StringUtils.join(getArguments(), ","));
        result.append(')');
        break;
      }
      case FIELD: {
        result.append(getType());
        result.append(' ');
        result.append(getName());
        break;
      }
      case ALL: {
        result.append("*");
        break;
      }
      default:
        throw new Unreachable("Unknown kind of member rule");
    }
    if (hasReturnValue()) {
      result.append(returnValue.toString());
    }
    return result.toString();
  }

  public static ProguardMemberRule defaultKeepAllRule() {
    ProguardMemberRule.Builder ruleBuilder = new ProguardMemberRule.Builder();
    ruleBuilder.setRuleType(ProguardMemberType.ALL);
    return ruleBuilder.build();
  }
}
