// Copyright (c) 2020, 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 static com.android.tools.r8.ir.desugar.DesugaredLibraryAPIConverter.DESCRIPTOR_VIVIFIED_PREFIX;
import static com.android.tools.r8.ir.desugar.DesugaredLibraryRetargeter.getRetargetPackageAndClassPrefixDescriptor;
import static com.android.tools.r8.ir.desugar.InterfaceMethodRewriter.EMULATE_LIBRARY_CLASS_NAME_SUFFIX;
import static com.android.tools.r8.utils.collections.IdentityHashSetFromMap.newProgramDerivedContextSet;

import com.android.tools.r8.diagnostic.MissingDefinitionsDiagnostic;
import com.android.tools.r8.diagnostic.internal.MissingClassInfoImpl;
import com.android.tools.r8.diagnostic.internal.MissingDefinitionContextUtils;
import com.android.tools.r8.diagnostic.internal.MissingDefinitionsDiagnosticImpl;
import com.android.tools.r8.errors.dontwarn.DontWarnConfiguration;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexReference;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.ProgramDerivedContext;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.synthesis.CommittedItems;
import com.android.tools.r8.synthesis.SyntheticItems.SynthesizingContextOracle;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.SetUtils;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import java.util.Collection;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.function.Predicate;

public class MissingClasses {

  private final Set<DexType> missingClasses;

  private MissingClasses(Set<DexType> missingClasses) {
    this.missingClasses = missingClasses;
  }

  public Builder builder() {
    return new Builder(missingClasses);
  }

  public static MissingClasses empty() {
    return new MissingClasses(Sets.newIdentityHashSet());
  }

  public MissingClasses commitSyntheticItems(CommittedItems committedItems) {
    return builder()
        // TODO(b/175542052): Synthetic types should not be reported as missing in the first place.
        .removeAlreadyMissingClasses(committedItems.getLegacySyntheticTypes())
        .build();
  }

  public boolean contains(DexType type) {
    return missingClasses.contains(type);
  }

  public static class Builder {

    private final Set<DexType> alreadyMissingClasses;
    private final Map<DexType, Set<ProgramDerivedContext>> newMissingClasses =
        new IdentityHashMap<>();

    // Set of missing types that are not to be reported as missing. This does not hide reports
    // if the same type is in newMissingClasses in which case it is reported regardless.
    private final Set<DexType> newIgnoredMissingClasses = Sets.newIdentityHashSet();

    private Builder() {
      this(Sets.newIdentityHashSet());
    }

    private Builder(Set<DexType> alreadyMissingClasses) {
      this.alreadyMissingClasses = alreadyMissingClasses;
    }

    public void addNewMissingClass(DexType type, ProgramDerivedContext context) {
      assert context != null;
      assert context.getContext().getContextType() != type;
      if (!alreadyMissingClasses.contains(type)) {
        newMissingClasses
            .computeIfAbsent(type, ignore -> newProgramDerivedContextSet())
            .add(context);
      }
    }

    public void legacyAddNewMissingClass(DexType type) {
      if (!alreadyMissingClasses.contains(type)) {
        // The legacy reporting is context insensitive, so we just use an empty set of contexts.
        newMissingClasses.computeIfAbsent(type, ignore -> newProgramDerivedContextSet());
      }
    }

    @Deprecated
    public Builder legacyAddNewMissingClasses(Collection<DexType> types) {
      types.forEach(this::legacyAddNewMissingClass);
      return this;
    }

    public void ignoreNewMissingClass(DexType type) {
      newIgnoredMissingClasses.add(type);
    }

    public boolean contains(DexType type) {
      return alreadyMissingClasses.contains(type)
          || newMissingClasses.containsKey(type)
          || newIgnoredMissingClasses.contains(type);
    }

    Builder removeAlreadyMissingClasses(Iterable<DexType> types) {
      for (DexType type : types) {
        alreadyMissingClasses.remove(type);
      }
      return this;
    }

    public MissingClasses assertNoMissingClasses(AppView<?> appView) {
      assert getMissingClassesToBeReported(appView, clazz -> ImmutableSet.of(clazz.getType()))
          .isEmpty();
      return build();
    }

    public MissingClasses reportMissingClasses(
        AppView<?> appView, SynthesizingContextOracle synthesizingContextOracle) {
      Map<DexType, Set<ProgramDerivedContext>> missingClassesToBeReported =
          getMissingClassesToBeReported(appView, synthesizingContextOracle);
      if (!missingClassesToBeReported.isEmpty()) {
        MissingDefinitionsDiagnostic diagnostic = createDiagnostic(missingClassesToBeReported);
        InternalOptions options = appView.options();
        // TODO(b/180903899): Remove L8 special handling when -dontwarn sun.misc.Unsafe is in place.
        if (options.ignoreMissingClasses || options.isDesugaredLibraryCompilation()) {
          appView.reporter().warning(diagnostic);
        } else {
          throw appView.reporter().fatalError(diagnostic);
        }
      }
      return build();
    }

    private MissingDefinitionsDiagnostic createDiagnostic(
        Map<DexType, Set<ProgramDerivedContext>> missingClassesToBeReported) {
      MissingDefinitionsDiagnosticImpl.Builder diagnosticBuilder =
          MissingDefinitionsDiagnosticImpl.builder();
      missingClassesToBeReported.forEach(
          (missingClass, programDerivedContexts) -> {
            MissingClassInfoImpl.Builder missingClassInfoBuilder =
                MissingClassInfoImpl.builder().setClass(missingClass.asClassReference());
            for (ProgramDerivedContext programDerivedContext : programDerivedContexts) {
              missingClassInfoBuilder.addReferencedFromContext(
                  MissingDefinitionContextUtils.create(programDerivedContext));
            }
            diagnosticBuilder.addMissingDefinitionInfo(missingClassInfoBuilder.build());
          });
      return diagnosticBuilder.build();
    }

    private void rewriteMissingClassContexts(
        AppView<?> appView, SynthesizingContextOracle synthesizingContextOracle) {
      Iterator<Entry<DexType, Set<ProgramDerivedContext>>> newMissingClassesIterator =
          newMissingClasses.entrySet().iterator();
      while (newMissingClassesIterator.hasNext()) {
        Entry<DexType, Set<ProgramDerivedContext>> entry = newMissingClassesIterator.next();
        entry.setValue(
            rewriteMissingClassContextsForSingleMissingClass(
                appView, entry.getValue(), synthesizingContextOracle));
      }
    }

    private static Set<ProgramDerivedContext> rewriteMissingClassContextsForSingleMissingClass(
        AppView<?> appView,
        Set<ProgramDerivedContext> contexts,
        SynthesizingContextOracle synthesizingContextOracle) {
      if (contexts.isEmpty()) {
        // Legacy reporting does not have any contexts.
        return contexts;
      }

      Set<ProgramDerivedContext> rewrittenContexts = newProgramDerivedContextSet();
      for (ProgramDerivedContext context : contexts) {
        if (!context.isProgramContext()) {
          rewrittenContexts.add(context);
          continue;
        }

        DexProgramClass clazz = context.getContext().asProgramDefinition().getContextClass();
        if (!appView.getSyntheticItems().isSyntheticClass(clazz)) {
          rewrittenContexts.add(context);
          continue;
        }

        // Rewrite the synthetic context to its synthesizing contexts.
        Set<DexReference> synthesizingContextReferences =
            appView.getSyntheticItems().getSynthesizingContexts(clazz, synthesizingContextOracle);
        assert synthesizingContextReferences != null;
        assert !synthesizingContextReferences.isEmpty();
        for (DexReference synthesizingContextReference : synthesizingContextReferences) {
          if (synthesizingContextReference.isDexMethod()) {
            DexProgramClass holder =
                appView
                    .definitionFor(synthesizingContextReference.getContextType())
                    .asProgramClass();
            ProgramMethod synthesizingContext =
                holder.lookupProgramMethod(synthesizingContextReference.asDexMethod());
            assert synthesizingContext != null;
            rewrittenContexts.add(synthesizingContext);
          } else {
            assert false
                : "Unexpected synthesizing context: "
                    + synthesizingContextReference.toSourceString();
          }
        }
      }
      return rewrittenContexts;
    }

    private Map<DexType, Set<ProgramDerivedContext>> getMissingClassesToBeReported(
        AppView<?> appView, SynthesizingContextOracle synthesizingContextOracle) {
      // Rewrite synthetic program contexts into their synthesizing contexts, to avoid reporting
      // any synthetic contexts.
      rewriteMissingClassContexts(appView, synthesizingContextOracle);
      Predicate<DexType> allowedMissingClassesPredicate =
          getIsAllowedMissingClassesPredicate(appView);
      Map<DexType, Set<ProgramDerivedContext>> missingClassesToBeReported =
          new IdentityHashMap<>(newMissingClasses.size());
      newMissingClasses.forEach(
          (missingClass, contexts) -> {
            // Don't report "allowed" missing classes (e.g., classes matched by -dontwarn).
            if (allowedMissingClassesPredicate.test(missingClass)) {
              return;
            }

            // Remove all contexts that are matched by a -dontwarn rule (a missing class should not
            // be reported if it os only referenced from contexts that are matched by a -dontwarn).
            contexts.removeIf(
                context ->
                    appView
                        .getDontWarnConfiguration()
                        .matches(context.getContext().getContextType()));

            // If there are any contexts not matched by a -dontwarn rule, then report.
            if (!contexts.isEmpty()) {
              missingClassesToBeReported.put(missingClass, contexts);
            }
          });
      return missingClassesToBeReported;
    }

    private static Predicate<DexType> getIsAllowedMissingClassesPredicate(AppView<?> appView) {
      Set<DexType> allowedMissingClasses = getAllowedMissingClasses(appView.dexItemFactory());
      Predicate<DexType> compilerSynthesizedAllowingMissingClassPredicate =
          getIsCompilerSynthesizedAllowedMissingClassesPredicate(appView);
      DontWarnConfiguration dontWarnConfiguration = appView.getDontWarnConfiguration();
      return type ->
          allowedMissingClasses.contains(type)
              || compilerSynthesizedAllowingMissingClassPredicate.test(type)
              || dontWarnConfiguration.matches(type);
    }

    private static Set<DexType> getAllowedMissingClasses(DexItemFactory dexItemFactory) {
      return ImmutableSet.<DexType>builder()
          .add(
              dexItemFactory.annotationDefault,
              dexItemFactory.annotationMethodParameters,
              dexItemFactory.annotationSourceDebugExtension,
              dexItemFactory.annotationSynthesizedClass,
              dexItemFactory.annotationThrows,
              dexItemFactory.serializedLambdaType)
          .addAll(dexItemFactory.getJavaConversionTypes())
          .addAll(dexItemFactory.getJ$ConversionTypes())
          .build();
    }

    private static Predicate<DexType> getIsCompilerSynthesizedAllowedMissingClassesPredicate(
        AppView<?> appView) {
      DexItemFactory dexItemFactory = appView.dexItemFactory();
      InternalOptions options = appView.options();
      DexString emulatedLibraryClassNameSuffix =
          dexItemFactory.createString(EMULATE_LIBRARY_CLASS_NAME_SUFFIX + ";");
      DexString retargetPackageAndClassPrefixDescriptor =
          dexItemFactory.createString(
              getRetargetPackageAndClassPrefixDescriptor(options.desugaredLibraryConfiguration));
      DexString vivifiedClassNamePrefix = dexItemFactory.createString(DESCRIPTOR_VIVIFIED_PREFIX);
      return type -> {
        DexString descriptor = type.getDescriptor();
        return descriptor.startsWith(retargetPackageAndClassPrefixDescriptor)
            || descriptor.startsWith(vivifiedClassNamePrefix)
            || descriptor.endsWith(emulatedLibraryClassNameSuffix);
      };
    }



    /** Intentionally private, use {@link Builder#reportMissingClasses(AppView)}. */
    private MissingClasses build() {
      // Return the new set of missing classes.
      //
      // We also add newIgnoredMissingClasses to newMissingClasses to be able to assert that we have
      // a closed world after the first round of tree shaking: we should never lookup a class that
      // was not live or missing during the first round of tree shaking.
      // See also AppInfoWithLiveness.definitionFor().
      //
      // Note: At this point, all missing classes in newMissingClasses have already been reported.
      // Thus adding newIgnoredMissingClasses to newMissingClasses will not lead to reports for the
      // classes in newIgnoredMissingClasses.
      return new MissingClasses(
          SetUtils.newIdentityHashSet(
              alreadyMissingClasses, newMissingClasses.keySet(), newIgnoredMissingClasses));
    }

    public boolean wasAlreadyMissing(DexType type) {
      return alreadyMissingClasses.contains(type);
    }
  }
}
