// 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 void setAbstract() {
    set(Constants.ACC_ABSTRACT);
  }

  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;
  }

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