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

import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.position.Position;
import com.android.tools.r8.position.TextPosition;
import com.android.tools.r8.position.TextRange;
import com.android.tools.r8.utils.StringUtils;
import com.google.common.collect.ImmutableList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;

public abstract class ProguardClassSpecification {

  public abstract static class
  Builder<C extends ProguardClassSpecification, B extends Builder<C, B>> {

    protected Origin origin;
    protected Position start;
    protected Position end;
    protected String source;
    private final ImmutableList.Builder<ProguardTypeMatcher> classAnnotations =
        ImmutableList.builder();
    protected ProguardAccessFlags classAccessFlags = new ProguardAccessFlags();
    protected ProguardAccessFlags negatedClassAccessFlags = new ProguardAccessFlags();
    protected boolean classTypeNegated = false;
    protected ProguardClassType classType = ProguardClassType.UNSPECIFIED;
    protected ProguardClassNameList classNames;
    private final ImmutableList.Builder<ProguardTypeMatcher> inheritanceAnnotations =
        ImmutableList.builder();
    protected ProguardTypeMatcher inheritanceClassName;
    protected boolean inheritanceIsExtends = false;
    protected List<ProguardMemberRule> memberRules = new LinkedList<>();

    protected Builder() {
      this(Origin.unknown(), Position.UNKNOWN);
    }

    protected Builder(Origin origin, Position start) {
      this.origin = origin;
      this.start = start;
    }

    public abstract C build();

    public abstract B self();

    public B setOrigin(Origin origin) {
      this.origin = origin;
      return self();
    }

    public B setStart(Position start) {
      this.start = start;
      return self();
    }

    public B setEnd(Position end) {
      this.end = end;
      return self();
    }

    public B setSource(String source) {
      this.source = source;
      return self();
    }

    public Position getPosition() {
      if (start == null) {
        return Position.UNKNOWN;
      }
      if (end == null || !((start instanceof TextPosition) && (end instanceof TextPosition))) {
        return start;
      }
      return new TextRange((TextPosition) start, (TextPosition) end);
    }

    public List<ProguardMemberRule> getMemberRules() {
      return memberRules;
    }

    public B setMemberRules(List<ProguardMemberRule> memberRules) {
      this.memberRules = memberRules;
      return self();
    }

    public boolean getInheritanceIsExtends() {
      return inheritanceIsExtends;
    }

    public B setInheritanceIsExtends(boolean inheritanceIsExtends) {
      this.inheritanceIsExtends = inheritanceIsExtends;
      return self();
    }

    public boolean hasInheritanceClassName() {
      return inheritanceClassName != null;
    }

    public ProguardTypeMatcher getInheritanceClassName() {
      return inheritanceClassName;
    }

    public B setInheritanceClassName(ProguardTypeMatcher inheritanceClassName) {
      this.inheritanceClassName = inheritanceClassName;
      return self();
    }

    public B addInheritanceAnnotations(List<ProguardTypeMatcher> inheritanceAnnotations) {
      assert inheritanceAnnotations != null;
      this.inheritanceAnnotations.addAll(inheritanceAnnotations);
      return self();
    }

    public List<ProguardTypeMatcher> buildInheritanceAnnotations() {
      return inheritanceAnnotations.build();
    }

    public ProguardClassNameList getClassNames() {
      return classNames;
    }

    public B setClassNames(ProguardClassNameList classNames) {
      this.classNames = classNames;
      return self();
    }

    public ProguardClassType getClassType() {
      return classType;
    }

    public B setClassType(ProguardClassType classType) {
      this.classType = classType;
      return self();
    }

    public boolean getClassTypeNegated() {
      return classTypeNegated;
    }

    public B setClassTypeNegated(boolean classTypeNegated) {
      this.classTypeNegated = classTypeNegated;
      return self();
    }

    public ProguardAccessFlags getClassAccessFlags() {
      return classAccessFlags;
    }

    public B setClassAccessFlags(ProguardAccessFlags flags) {
      classAccessFlags = flags;
      return self();
    }

    public ProguardAccessFlags getNegatedClassAccessFlags() {
      return negatedClassAccessFlags;
    }

    public B setNegatedClassAccessFlags(ProguardAccessFlags flags) {
      negatedClassAccessFlags = flags;
      return self();
    }

    public B addClassAnnotation(ProguardTypeMatcher classAnnotation) {
      classAnnotations.add(classAnnotation);
      return self();
    }

    public B addClassAnnotations(List<ProguardTypeMatcher> classAnnotations) {
      assert classAnnotations != null;
      this.classAnnotations.addAll(classAnnotations);
      return self();
    }

    public List<ProguardTypeMatcher> buildClassAnnotations() {
      return classAnnotations.build();
    }

    protected void matchAllSpecification() {
      setClassNames(ProguardClassNameList.singletonList(ProguardTypeMatcher.defaultAllMatcher()));
      setMemberRules(ImmutableList.of(ProguardMemberRule.defaultKeepAllRule()));
    }
  }

  private final Origin origin;
  private final Position position;
  private final String source;
  private final List<ProguardTypeMatcher> classAnnotations;
  private final ProguardAccessFlags classAccessFlags;
  private final ProguardAccessFlags negatedClassAccessFlags;
  private final boolean classTypeNegated;
  private final ProguardClassType classType;
  private final ProguardClassNameList classNames;
  private final List<ProguardTypeMatcher> inheritanceAnnotations;
  private final ProguardTypeMatcher inheritanceClassName;
  private final boolean inheritanceIsExtends;
  private final List<ProguardMemberRule> memberRules;

  protected ProguardClassSpecification(
      Origin origin,
      Position position,
      String source,
      List<ProguardTypeMatcher> classAnnotations,
      ProguardAccessFlags classAccessFlags,
      ProguardAccessFlags negatedClassAccessFlags,
      boolean classTypeNegated,
      ProguardClassType classType,
      ProguardClassNameList classNames,
      List<ProguardTypeMatcher> inheritanceAnnotations,
      ProguardTypeMatcher inheritanceClassName,
      boolean inheritanceIsExtends,
      List<ProguardMemberRule> memberRules) {
    assert origin != null;
    assert position != null;
    assert source != null || origin != Origin.unknown();
    this.origin = origin;
    this.position = position;
    this.source = source;
    this.classAnnotations = classAnnotations;
    this.classAccessFlags = classAccessFlags;
    this.negatedClassAccessFlags = negatedClassAccessFlags;
    this.classTypeNegated = classTypeNegated;
    this.classType = classType;
    assert classType != null;
    this.classNames = classNames;
    this.inheritanceAnnotations = inheritanceAnnotations;
    this.inheritanceClassName = inheritanceClassName;
    this.inheritanceIsExtends = inheritanceIsExtends;
    this.memberRules = memberRules;
  }

  public Origin getOrigin() {
    return origin;
  }

  public Position getPosition() {
    return position;
  }

  public String getSource() {
    return source;
  }

  public List<ProguardMemberRule> getMemberRules() {
    return memberRules;
  }

  public boolean getInheritanceIsExtends() {
    return inheritanceIsExtends;
  }

  public boolean getInheritanceIsImplements() {
    return !inheritanceIsExtends;
  }

  public boolean hasInheritanceClassName() {
    return inheritanceClassName != null;
  }

  public ProguardTypeMatcher getInheritanceClassName() {
    return inheritanceClassName;
  }

  public List<ProguardTypeMatcher> getInheritanceAnnotations() {
    return inheritanceAnnotations;
  }

  public ProguardClassNameList getClassNames() {
    return classNames;
  }

  public ProguardClassType getClassType() {
    return classType;
  }

  public boolean getClassTypeNegated() {
    return classTypeNegated;
  }

  public ProguardAccessFlags getClassAccessFlags() {
    return classAccessFlags;
  }

  public ProguardAccessFlags getNegatedClassAccessFlags() {
    return negatedClassAccessFlags;
  }

  public List<ProguardTypeMatcher> getClassAnnotations() {
    return classAnnotations;
  }

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

    if (classTypeNegated != that.classTypeNegated) {
      return false;
    }
    if (inheritanceIsExtends != that.inheritanceIsExtends) {
      return false;
    }
    if (!Objects.equals(classAnnotations, that.classAnnotations)) {
      return false;
    }
    if (!classAccessFlags.equals(that.classAccessFlags)) {
      return false;
    }
    if (!negatedClassAccessFlags.equals(that.negatedClassAccessFlags)) {
      return false;
    }
    if (classType != that.classType) {
      return false;
    }
    if (!classNames.equals(that.classNames)) {
      return false;
    }
    if (!Objects.equals(inheritanceAnnotations, that.inheritanceAnnotations)) {
      return false;
    }
    if (!Objects.equals(inheritanceClassName, that.inheritanceClassName)) {
      return false;
    }
    return memberRules.equals(that.memberRules);
  }

  @Override
  public int hashCode() {
    // Used multiplier 3 to avoid too much overflow when computing hashCode.
    int result = classAnnotations.hashCode();
    result = 3 * result + classAccessFlags.hashCode();
    result = 3 * result + negatedClassAccessFlags.hashCode();
    result = 3 * result + (classTypeNegated ? 1 : 0);
    result = 3 * result + (classType != null ? classType.hashCode() : 0);
    result = 3 * result + classNames.hashCode();
    result = 3 * result + inheritanceAnnotations.hashCode();
    result = 3 * result + (inheritanceClassName != null ? inheritanceClassName.hashCode() : 0);
    result = 3 * result + (inheritanceIsExtends ? 1 : 0);
    result = 3 * result + memberRules.hashCode();
    return result;
  }

  protected StringBuilder append(StringBuilder builder, boolean includeMemberRules) {
    appendAnnotations(classAnnotations, builder);
    boolean needsSpaceBeforeClassType =
        StringUtils.appendNonEmpty(builder, null, classAccessFlags, null)
            | StringUtils.appendNonEmpty(
                builder, "!", negatedClassAccessFlags.toString().replace(" ", " !"), null);
    if (needsSpaceBeforeClassType) {
      builder.append(' ');
    }
    if (classTypeNegated) {
      builder.append('!');
    }
    builder.append(classType);
    builder.append(' ');
    classNames.writeTo(builder);
    if (hasInheritanceClassName()) {
      builder.append(' ').append(inheritanceIsExtends ? "extends" : "implements").append(' ');
      appendAnnotations(inheritanceAnnotations, builder);
      builder.append(inheritanceClassName);
    }
    if (includeMemberRules && !memberRules.isEmpty()) {
      builder.append(" {").append(System.lineSeparator());
      memberRules.forEach(memberRule -> {
        builder.append("  ");
        builder.append(memberRule);
        builder.append(";").append(System.lineSeparator());
      });
      builder.append("}");
    }
    return builder;
  }

  private static void appendAnnotations(
      List<ProguardTypeMatcher> annotations, StringBuilder builder) {
    if (!annotations.isEmpty()) {
      Iterator<ProguardTypeMatcher> annotationIterator = annotations.iterator();
      builder.append('@').append(annotationIterator.next());
      while (annotationIterator.hasNext()) {
        builder.append(" @").append(annotationIterator.next());
      }
      builder.append(' ');
    }
  }

  /**
   * Short String representation without member rules.
   */
  public String toShortString() {
    return append(new StringBuilder(), false).toString();
  }

  @Override
  public String toString() {
    return append(new StringBuilder(), true).toString();
  }
}
