// 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 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"
  );

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

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

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

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

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

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

  public void setPublic() {
    set(Constants.ACC_PUBLIC);
  }

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

  public void setPrivate() {
    set(Constants.ACC_PRIVATE);
  }

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

  public void setProtected() {
    set(Constants.ACC_PROTECTED);
  }

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

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