// Copyright (c) 2016, 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 com.android.tools.r8.ProgramResource;
import com.android.tools.r8.ProgramResource.Kind;
import com.android.tools.r8.dex.MixedSectionCollection;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.GenericSignature.ClassSignature;
import com.android.tools.r8.kotlin.KotlinClassLevelInfo;
import com.android.tools.r8.origin.Origin;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.Supplier;

public class DexLibraryClass extends DexClass implements LibraryClass, Supplier<DexLibraryClass> {

  public DexLibraryClass(
      DexType type,
      ProgramResource.Kind kind,
      Origin origin,
      ClassAccessFlags accessFlags,
      DexType superType,
      DexTypeList interfaces,
      DexString sourceFile,
      NestHostClassAttribute nestHost,
      List<NestMemberClassAttribute> nestMembers,
      EnclosingMethodAttribute enclosingMember,
      List<InnerClassAttribute> innerClasses,
      ClassSignature classSignature,
      DexAnnotationSet annotations,
      DexEncodedField[] staticFields,
      DexEncodedField[] instanceFields,
      DexEncodedMethod[] directMethods,
      DexEncodedMethod[] virtualMethods,
      boolean skipNameValidationForTesting) {
    super(
        sourceFile,
        interfaces,
        accessFlags,
        superType,
        type,
        staticFields,
        instanceFields,
        directMethods,
        virtualMethods,
        nestHost,
        nestMembers,
        enclosingMember,
        innerClasses,
        classSignature,
        annotations,
        origin,
        skipNameValidationForTesting);
    assert Arrays.stream(directMethods).allMatch(DexLibraryClass::verifyLibraryMethod);
    assert Arrays.stream(virtualMethods).allMatch(DexLibraryClass::verifyLibraryMethod);
    assert Arrays.stream(staticFields).allMatch(DexLibraryClass::verifyLibraryField);
    assert Arrays.stream(instanceFields).allMatch(DexLibraryClass::verifyLibraryField);
    // Set all static field values to unknown. We don't want to use the value from the library
    // at compile time, as it can be different at runtime.
    for (DexEncodedField staticField : staticFields) {
      staticField.clearStaticValue();
    }
    assert kind == Kind.CF : "Invalid kind " + kind + " for library-path class " + type;
  }

  public static Builder builder(DexItemFactory dexItemFactory) {
    return new Builder(dexItemFactory);
  }

  public static DexLibraryClass asLibraryClassOrNull(DexClass clazz) {
    return clazz != null ? clazz.asLibraryClass() : null;
  }

  private static boolean verifyLibraryMethod(DexEncodedMethod method) {
    assert !method.isClassInitializer();
    assert !method.isPrivateMethod();
    assert !method.hasCode();
    return true;
  }

  private static boolean verifyLibraryField(DexEncodedField field) {
    assert !field.isPrivate();
    assert !field.isStatic() || !field.hasExplicitStaticValue();
    return true;
  }

  @Override
  public void accept(
      Consumer<DexProgramClass> programClassConsumer,
      Consumer<DexClasspathClass> classpathClassConsumer,
      Consumer<DexLibraryClass> libraryClassConsumer) {
    libraryClassConsumer.accept(this);
  }

  @Override
  public String toString() {
    return type.toString() + "(library class)";
  }

  @Override
  public String toSourceString() {
    return type.toSourceString() + "(library class)";
  }

  @Override
  public void addDependencies(MixedSectionCollection collector) {
    // Should never happen but does not harm.
    assert false;
  }

  @Override
  public boolean isNotProgramClass() {
    return true;
  }

  @Override
  public boolean isLibraryClass() {
    return true;
  }

  @Override
  public DexLibraryClass asLibraryClass() {
    return this;
  }

  @Override
  public DexLibraryClass asClasspathOrLibraryClass() {
    return this;
  }

  @Override
  public KotlinClassLevelInfo getKotlinInfo() {
    throw new Unreachable("We should never consider metadata for library classes");
  }

  @Override
  public DexLibraryClass get() {
    return this;
  }

  @Override
  boolean internalClassOrInterfaceMayHaveInitializationSideEffects(
      AppView<?> appView,
      DexClass initialAccessHolder,
      Predicate<DexType> ignore,
      Set<DexType> seen) {
    if (!seen.add(getType()) || ignore.test(getType())) {
      return false;
    }
    return isInterface()
        ? appView.options().libraryInterfacesMayHaveStaticInitialization
        : !appView.dexItemFactory().libraryClassesWithoutStaticInitialization.contains(type);
  }

  public static class Builder {

    // Required.
    private DexType type;
    private ClassAccessFlags accessFlags;

    // Optional.
    private Origin origin = Origin.unknown();
    private DexType superType;
    private DexTypeList interfaces = DexTypeList.empty();
    private DexString sourceFile = null;
    private NestHostClassAttribute nestHost = null;
    private List<NestMemberClassAttribute> nestMembers = Collections.emptyList();
    private EnclosingMethodAttribute enclosingMember = null;
    private List<InnerClassAttribute> innerClasses = Collections.emptyList();
    private ClassSignature classSignature = ClassSignature.noSignature();
    private DexAnnotationSet annotations = DexAnnotationSet.empty();
    private DexEncodedField[] staticFields = DexEncodedField.EMPTY_ARRAY;
    private DexEncodedField[] instanceFields = DexEncodedField.EMPTY_ARRAY;
    private DexEncodedMethod[] directMethods = DexEncodedMethod.EMPTY_ARRAY;
    private DexEncodedMethod[] virtualMethods = DexEncodedMethod.EMPTY_ARRAY;
    private boolean skipNameValidationForTesting;

    private Builder(DexItemFactory dexItemFactory) {
      this.superType = dexItemFactory.objectType;
      this.skipNameValidationForTesting = dexItemFactory.getSkipNameValidationForTesting();
    }

    public Builder setAccessFlags(ClassAccessFlags accessFlags) {
      this.accessFlags = accessFlags;
      return this;
    }

    public Builder setDirectMethods(Collection<DexEncodedMethod> directMethods) {
      this.directMethods = directMethods.toArray(DexEncodedMethod.EMPTY_ARRAY);
      return this;
    }

    public Builder setType(DexType type) {
      this.type = type;
      return this;
    }

    public DexLibraryClass build() {
      assert validate();
      return new DexLibraryClass(
          type,
          ProgramResource.Kind.CF,
          origin,
          accessFlags,
          superType,
          interfaces,
          sourceFile,
          nestHost,
          nestMembers,
          enclosingMember,
          innerClasses,
          classSignature,
          annotations,
          staticFields,
          instanceFields,
          directMethods,
          virtualMethods,
          skipNameValidationForTesting);
    }

    private boolean validate() {
      assert type != null;
      assert accessFlags != null;
      return true;
    }
  }
}
