// 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.dex.Constants;
import com.android.tools.r8.graph.AccessFlags;
import com.android.tools.r8.graph.ClassAccessFlags;
import com.google.common.collect.ImmutableList;
import java.util.List;
import java.util.function.BooleanSupplier;

public class ProguardAccessFlags {

  private final static int PPP_MASK =
      new ProguardAccessFlags().setPublic().setProtected().setPrivate().flags;

  private int flags = 0;

  // Ordered list of flag names. Must be consistent with getPredicates.
  private static final List<String> NAMES =
      ImmutableList.of(
          "public",
          "private",
          "protected",
          "static",
          "final",
          "abstract",
          "volatile",
          "transient",
          "synchronized",
          "native",
          "strictfp",
          "synthetic",
          "bridge",
          "constructor");

  // Get ordered list of flag predicates. Must be consistent with getNames.
  private List<BooleanSupplier> getPredicates() {
    return ImmutableList.of(
        this::isPublic,
        this::isPrivate,
        this::isProtected,
        this::isStatic,
        this::isFinal,
        this::isAbstract,
        this::isVolatile,
        this::isTransient,
        this::isSynchronized,
        this::isNative,
        this::isStrict,
        this::isSynthetic,
        this::isBridge,
        this::isConstructor);
  }

  private boolean containsAll(int other) {
    // ppp flags are the flags public, protected and private.
    return
        // All non-ppp flags set must match (a 0 in non-ppp flags means don't care).
        (((flags & ~PPP_MASK) & (other & ~PPP_MASK)) == (flags & ~PPP_MASK))
            // With no ppp flags any flags match, with ppp flags there must be an overlap to match.
            && (((flags & PPP_MASK) == 0) || ((flags & PPP_MASK) & (other & PPP_MASK)) != 0);
  }

  private boolean containsNone(int other) {
    return (flags & other) == 0;
  }

  public boolean containsAll(AccessFlags other) {
    return containsAll(other.getOriginalAccessFlags());
  }

  public boolean containsNone(AccessFlags other) {
    return containsNone(other.getOriginalAccessFlags());
  }

  public void setFlags(AccessFlags other) {
    this.flags = other.getOriginalAccessFlags();
  }

  public ProguardAccessFlags setPublic() {
    set(Constants.ACC_PUBLIC);
    return this;
  }

  public boolean isPublic() {
    return isSet(Constants.ACC_PUBLIC);
  }

  public ProguardAccessFlags setPrivate() {
    set(Constants.ACC_PRIVATE);
    return this;
  }

  public boolean isPrivate() {
    return isSet(Constants.ACC_PRIVATE);
  }

  public ProguardAccessFlags setProtected() {
    set(Constants.ACC_PROTECTED);
    return this;
  }

  public boolean isProtected() {
    return isSet(Constants.ACC_PROTECTED);
  }

  public void setVisibility(ClassAccessFlags classAccessFlags) {
    if (classAccessFlags.isPublic()) {
      setPublic();
    } else if (classAccessFlags.isProtected()) {
      setProtected();
    } else if (classAccessFlags.isPrivate()) {
      setPrivate();
    }
  }

  public void setStatic() {
    set(Constants.ACC_STATIC);
  }

  public boolean isStatic() {
    return isSet(Constants.ACC_STATIC);
  }

  public void setFinal() {
    set(Constants.ACC_FINAL);
  }

  public boolean isFinal() {
    return isSet(Constants.ACC_FINAL);
  }

  public ProguardAccessFlags setAbstract() {
    set(Constants.ACC_ABSTRACT);
    return this;
  }

  public boolean isAbstract() {
    return isSet(Constants.ACC_ABSTRACT);
  }

  public void setVolatile() {
    set(Constants.ACC_VOLATILE);
  }

  public boolean isVolatile() {
    return isSet(Constants.ACC_VOLATILE);
  }

  public void setTransient() {
    set(Constants.ACC_TRANSIENT);
  }

  public boolean isTransient() {
    return isSet(Constants.ACC_TRANSIENT);
  }

  public void setSynchronized() {
    set(Constants.ACC_SYNCHRONIZED);
  }

  public boolean isSynchronized() {
    return isSet(Constants.ACC_SYNCHRONIZED);
  }

  public void setNative() {
    set(Constants.ACC_NATIVE);
  }

  public boolean isNative() {
    return isSet(Constants.ACC_NATIVE);
  }

  public void setStrict() {
    set(Constants.ACC_STRICT);
  }

  public boolean isStrict() {
    return isSet(Constants.ACC_STRICT);
  }

  public void setSynthetic() {
    set(Constants.ACC_SYNTHETIC);
  }

  public boolean isSynthetic() {
    return isSet(Constants.ACC_SYNTHETIC);
  }

  public void setBridge() {
    set(Constants.ACC_BRIDGE);
  }

  public boolean isBridge() {
    return isSet(Constants.ACC_BRIDGE);
  }

  public void setConstructor() {
    set(Constants.ACC_CONSTRUCTOR);
  }

  public boolean isConstructor() {
    return isSet(Constants.ACC_CONSTRUCTOR);
  }

  private boolean isSet(int flag) {
    return (flags & flag) != 0;
  }

  private void set(int flag) {
    flags |= flag;
  }

  @Override
  public String toString() {
    List<BooleanSupplier> predicates = getPredicates();
    StringBuilder builder = new StringBuilder();
    boolean space = false;
    for (int i = 0; i < NAMES.size(); i++) {
      if (predicates.get(i).getAsBoolean()) {
        if (space) {
          builder.append(' ');
        } else {
          space = true;
        }
        builder.append(NAMES.get(i));
      }
    }
    return builder.toString();
  }

  @Override
  public boolean equals(Object obj) {
    if (!(obj instanceof ProguardAccessFlags)) {
      return false;
    }
    return this.flags == ((ProguardAccessFlags) obj).flags;
  }

  public boolean isDefaultFlags() {
    return flags == 0;
  }

  @Override
  public int hashCode() {
    return flags;
  }
}
