// 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) {
    assert synthesizingContextType != null;
    // 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);
  }
}
