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

import static kotlinx.metadata.FlagsKt.flagsOf;

import com.android.tools.r8.dex.Constants;
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.List;
import java.util.function.BooleanSupplier;
import kotlinx.metadata.Flag;

/** Access flags common to classes, methods and fields. */
public abstract class AccessFlags<T extends AccessFlags<T>> {

  protected Flag[] EMPTY_FLAG = {};

  protected static final int BASE_FLAGS
      = Constants.ACC_PUBLIC
      | Constants.ACC_PRIVATE
      | Constants.ACC_PROTECTED
      | Constants.ACC_STATIC
      | Constants.ACC_FINAL
      | Constants.ACC_SYNTHETIC;

  // Ordered list of flag names. Must be consistent with getPredicates.
  private static final List<String> NAMES = ImmutableList.of(
      "public",
      "private",
      "protected",
      "static",
      "final",
      "synthetic"
  );

  // Get ordered list of flag predicates. Must be consistent with getNames.
  protected List<BooleanSupplier> getPredicates() {
    return ImmutableList.of(
        this::isPublic,
        this::isPrivate,
        this::isProtected,
        this::isStatic,
        this::isFinal,
        this::isSynthetic);
  }

  // Get ordered list of flag names. Must be consistent with getPredicates.
  protected List<String> getNames() {
    return NAMES;
  }

  protected int originalFlags;
  protected int modifiedFlags;

  protected AccessFlags(int originalFlags, int modifiedFlags) {
    this.originalFlags = originalFlags;
    this.modifiedFlags = modifiedFlags;
  }

  public abstract T copy();

  public abstract T self();

  public int materialize() {
    return modifiedFlags;
  }

  public abstract int getAsCfAccessFlags();

  public abstract int getAsDexAccessFlags();

  public int getAsKotlinFlags() {
    List<Flag> flags = new ArrayList<>();
    if (isPrivate()) {
      flags.add(Flag.IS_PRIVATE);
    }
    if (isProtected()) {
      flags.add(Flag.IS_PROTECTED);
    }
    if (isPublic()) {
      flags.add(Flag.IS_PUBLIC);
    }
    if (isFinal()) {
      flags.add(Flag.IS_FINAL);
    }
    if (isOpen()) {
      flags.add(Flag.IS_OPEN);
    }
    return flagsOf(flags.toArray(EMPTY_FLAG));
  }

  public final int getOriginalAccessFlags() {
    return originalFlags;
  }

  @Override
  public boolean equals(Object object) {
    if (object instanceof AccessFlags) {
      AccessFlags other = (AccessFlags) object;
      return originalFlags == other.originalFlags && modifiedFlags == other.modifiedFlags;
    }
    return false;
  }

  @Override
  public int hashCode() {
    return originalFlags | modifiedFlags;
  }

  public boolean isMoreVisibleThan(
      AccessFlags other, String packageNameThis, String packageNameOther) {
    int visibilityOrdinal = visibilityOrdinal();
    if (visibilityOrdinal > other.visibilityOrdinal()) {
      return true;
    }
    if (visibilityOrdinal == other.visibilityOrdinal()
        && isVisibilityDependingOnPackage()
        && !packageNameThis.equals(packageNameOther)) {
      return true;
    }
    return false;
  }

  public boolean isAtLeastAsVisibleAs(AccessFlags other) {
    return visibilityOrdinal() >= other.visibilityOrdinal();
  }

  public boolean isSameVisibility(AccessFlags other) {
    return visibilityOrdinal() == other.visibilityOrdinal();
  }

  private int visibilityOrdinal() {
    // public > protected > package > private
    if (isPublic()) {
      return 3;
    }
    if (isProtected()) {
      return 2;
    }
    if (isPrivate()) {
      return 0;
    }
    // Package-private
    return 1;
  }

  public boolean isVisibilityDependingOnPackage() {
    return visibilityOrdinal() == 1 || visibilityOrdinal() == 2;
  }

  public boolean isPackagePrivate() {
    return !isPublic() && !isPrivate() && !isProtected();
  }

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

  public void setPublic() {
    assert !isPrivate() && !isProtected();
    set(Constants.ACC_PUBLIC);
  }

  public void unsetPublic() {
    unset(Constants.ACC_PUBLIC);
  }

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

  public void setPrivate() {
    assert !isPublic() && !isProtected();
    set(Constants.ACC_PRIVATE);
  }

  public void unsetPrivate() {
    unset(Constants.ACC_PRIVATE);
  }

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

  public void setProtected() {
    assert !isPublic() && !isPrivate();
    set(Constants.ACC_PROTECTED);
  }

  public void unsetProtected() {
    unset(Constants.ACC_PROTECTED);
  }

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

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

  public boolean isOpen() {
    return !isFinal();
  }

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

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

  public void unsetFinal() {
    unset(Constants.ACC_FINAL);
  }

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

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

  public void unsetSynthetic() {
    unset(Constants.ACC_SYNTHETIC);
  }

  public void demoteFromSynthetic() {
    demote(Constants.ACC_SYNTHETIC);
  }

  public void promoteToFinal() {
    promote(Constants.ACC_FINAL);
  }

  public void demoteFromFinal() {
    demote(Constants.ACC_FINAL);
  }

  public boolean isPromotedToPublic() {
    return isPromoted(Constants.ACC_PUBLIC);
  }

  public void promoteToPublic() {
    demote(Constants.ACC_PRIVATE | Constants.ACC_PROTECTED);
    promote(Constants.ACC_PUBLIC);
  }

  public void promoteToStatic() {
    promote(Constants.ACC_STATIC);
  }

  private boolean wasSet(int flag) {
    return (originalFlags & flag) != 0;
  }

  protected boolean isSet(int flag) {
    return (modifiedFlags & flag) != 0;
  }

  protected void set(int flag) {
    originalFlags |= flag;
    modifiedFlags |= flag;
  }

  protected void unset(int flag) {
    originalFlags &= ~flag;
    modifiedFlags &= ~flag;
  }

  protected boolean isPromoted(int flag) {
    return !wasSet(flag) && isSet(flag);
  }

  protected void promote(int flag) {
    modifiedFlags |= flag;
  }

  protected void demote(int flag) {
    modifiedFlags &= ~flag;
  }

  public String toSmaliString() {
    return toStringInternal(true);
  }

  @Override
  public String toString() {
    return toStringInternal(false);
  }

  private String toStringInternal(boolean ignoreSuper) {
    List<String> names = getNames();
    List<BooleanSupplier> predicates = getPredicates();
    StringBuilder builder = new StringBuilder();
    for (int i = 0; i < names.size(); i++) {
      if (predicates.get(i).getAsBoolean()) {
        if (!ignoreSuper || !names.get(i).equals("super")) {
          if (builder.length() > 0) {
            builder.append(' ');
          }
          builder.append(names.get(i));
        }
      }
    }
    return builder.toString();
  }
}
