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

import static com.android.tools.r8.utils.DescriptorUtils.getBinaryNameFromDescriptor;
import static com.android.tools.r8.utils.DescriptorUtils.getDescriptorFromClassBinaryName;

import com.android.tools.r8.FeatureSplit;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.ClasspathOrLibraryClass;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLens.NonIdentityGraphLens;
import com.android.tools.r8.graph.ProgramDefinition;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.shaking.MainDexInfo;
import java.util.Comparator;

/**
 * A synthesizing context is a description of the context that gives rise to a synthetic item.
 *
 * <p>Note that a context can only itself be a synthetic item if it was provided as an input that
 * was marked as synthetic already, in which case the context consists of the synthetic input type
 * as well as the original synthesizing context type specified in it synthesis annotation.
 *
 * <p>This class is internal to the synthetic items collection, thus package-protected.
 */
class SynthesizingContext implements Comparable<SynthesizingContext> {

  // The synthesizing context is the type used for ensuring a hygienic placement of a synthetic.
  // Thus this type will potentially be used as the prefix of a synthetic class.
  private final DexType synthesizingContextType;

  // The input context is the program input type that is the actual context of a synthetic.
  // In particular, if the synthetic type is itself a program input, then it will be its own
  // input context but it will have a distinct synthesizing context (encoded in its annotation).
  private final DexType inputContextType;
  private final Origin inputContextOrigin;

  private final FeatureSplit featureSplit;

  static SynthesizingContext fromNonSyntheticInputContext(ClasspathOrLibraryClass context) {
    // A context that is itself non-synthetic is the single context, thus both the input context
    // and synthesizing context coincide.
    return new SynthesizingContext(
        context.getContextType(),
        context.getContextType(),
        context.getOrigin(),
        // Synthesizing from a non-program context is just considered to be "base".
        FeatureSplit.BASE);
  }

  static SynthesizingContext fromType(DexType type) {
    // This method should only be used for synthesizing from a non-program context!
    // Thus we have no origin info and place the context in the "base" feature.
    return new SynthesizingContext(type, type, Origin.unknown(), FeatureSplit.BASE);
  }

  static SynthesizingContext fromNonSyntheticInputContext(
      ProgramDefinition context, FeatureSplit featureSplit) {
    // A context that is itself non-synthetic is the single context, thus both the input context
    // and synthesizing context coincide.
    return new SynthesizingContext(
        context.getContextType(), context.getContextType(), context.getOrigin(), featureSplit);
  }

  static SynthesizingContext fromSyntheticInputClass(
      DexProgramClass clazz, DexType synthesizingContextType, AppView<?> appView) {
    // A context that is itself synthetic must denote a synthesizing context from which to ensure
    // hygiene. This synthesizing context type is encoded on the synthetic for intermediate builds.
    FeatureSplit featureSplit =
        appView
            .appInfoForDesugaring()
            .getClassToFeatureSplitMap()
            .getFeatureSplit(clazz, appView.getSyntheticItems());
    return new SynthesizingContext(synthesizingContextType, clazz.type, clazz.origin, featureSplit);
  }

  private SynthesizingContext(
      DexType synthesizingContextType,
      DexType inputContextType,
      Origin inputContextOrigin,
      FeatureSplit featureSplit) {
    this.synthesizingContextType = synthesizingContextType;
    this.inputContextType = inputContextType;
    this.inputContextOrigin = inputContextOrigin;
    this.featureSplit = featureSplit;
  }

  @Override
  public int compareTo(SynthesizingContext other) {
    return Comparator
        // The first item to compare is the synthesizing context type. This is the type used to
        // choose the context prefix for items.
        .comparing(SynthesizingContext::getSynthesizingContextType)
        // To ensure that equals coincides with compareTo == 0, we then compare 'type'.
        .thenComparing(c -> c.inputContextType)
        .compare(this, other);
  }

  DexType getSynthesizingContextType() {
    return synthesizingContextType;
  }

  Origin getInputContextOrigin() {
    return inputContextOrigin;
  }

  FeatureSplit getFeatureSplit() {
    return featureSplit;
  }

  SynthesizingContext rewrite(NonIdentityGraphLens lens) {
    DexType rewrittenInputeContextType = lens.lookupType(inputContextType);
    DexType rewrittenSynthesizingContextType = lens.lookupType(synthesizingContextType);
    return rewrittenInputeContextType == inputContextType
            && rewrittenSynthesizingContextType == synthesizingContextType
        ? this
        : new SynthesizingContext(
            rewrittenSynthesizingContextType,
            rewrittenInputeContextType,
            inputContextOrigin,
            featureSplit);
  }

  void registerPrefixRewriting(DexType hygienicType, AppView<?> appView) {
    if (!appView.options().isDesugaredLibraryCompilation()) {
      return;
    }
    assert hygienicType.toSourceString().startsWith(synthesizingContextType.toSourceString());
    DexType rewrittenContext =
        appView
            .options()
            .desugaredLibraryConfiguration
            .getEmulateLibraryInterface()
            .get(synthesizingContextType);
    if (rewrittenContext == null) {
      return;
    }
    String contextPrefix =
        getBinaryNameFromDescriptor(synthesizingContextType.toDescriptorString());
    String rewrittenPrefix = getBinaryNameFromDescriptor(rewrittenContext.toDescriptorString());
    String suffix =
        getBinaryNameFromDescriptor(hygienicType.toDescriptorString())
            .substring(contextPrefix.length());
    DexType rewrittenType =
        appView
            .dexItemFactory()
            .createType(getDescriptorFromClassBinaryName(rewrittenPrefix + suffix));
    appView.rewritePrefix.rewriteType(hygienicType, rewrittenType);
  }

  @Override
  public String toString() {
    return "SynthesizingContext{"
        + getSynthesizingContextType()
        + (featureSplit != FeatureSplit.BASE ? ", feature:" + featureSplit : "")
        + "}";
  }

  // TODO(b/181858113): Remove once deprecated main-dex-list is removed.
  boolean isDerivedFromMainDexList(MainDexInfo mainDexInfo) {
    return mainDexInfo.isSyntheticContextOnMainDexList(inputContextType);
  }
}
