// Copyright (c) 2021, 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.contexts;

import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.utils.InternalOptions;
import com.google.common.hash.Hasher;
import com.google.common.hash.Hashing;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Consumer;

public class CompilationContext {

  // Internal contract to compute a unique suffix for synthetics.
  private abstract static class ContextDescriptorProvider {

    // Method to construct a fully qualified description of the context.
    // This is used to ensure that all contexts are unique during compilation.
    abstract StringBuilder buildContextDescriptorForTesting(StringBuilder builder);

    // Build a suffix to append to synthetic definitions.
    abstract StringBuilder buildSyntheticSuffix(StringBuilder builder);
  }

  /**
   * Create the initial compilation context.
   *
   * <p>This context should be a singleton for a given compilation allocated by AppView.
   */
  public static CompilationContext createInitialContext(InternalOptions options) {
    return new CompilationContext(options);
  }

  private final Consumer<String> testingConsumer;
  private final Set<String> seenSetForTesting = new HashSet<>();
  private int nextProcessorId = 0;

  private CompilationContext(InternalOptions options) {
    testingConsumer = options.testing.processingContextsConsumer;
  }

  private boolean verifyContext(ContextDescriptorProvider context) {
    String descriptor = context.buildContextDescriptorForTesting(new StringBuilder()).toString();
    String suffix = context.buildSyntheticSuffix(new StringBuilder()).toString();
    assert descriptor.endsWith(suffix);
    if (testingConsumer != null) {
      testingConsumer.accept(descriptor);
    }
    assert seenSetForTesting.add(descriptor)
        : "Duplicated use of context descriptor: " + descriptor;
    return true;
  }

  /**
   * Creates the context for a "processor".
   *
   * <p>A "processor" is just a compilation task but which is deterministically ordered as part of
   * the full compilation pipeline. Thus, this method should only be called on the main-thread
   * ensuring that the assigned ids are deterministic. The id itself has not particular meaning.
   */
  public ProcessorContext createProcessorContext() {
    ProcessorContext processorContext = new ProcessorContext(this, nextProcessorId++);
    assert verifyContext(processorContext);
    return processorContext;
  }

  public static class ProcessorContext extends ContextDescriptorProvider {
    private final CompilationContext parent;
    private final int processorId;

    private ProcessorContext(CompilationContext parent, int processorId) {
      this.parent = parent;
      this.processorId = processorId;
    }

    private boolean verifyContext(ContextDescriptorProvider context) {
      assert parent.verifyContext(context);
      return true;
    }

    /**
     * Create processing context for a single method.
     *
     * <p>There should only ever be a single allocation of the particular method-processing context.
     * This is generally ensured by, eg, a MethodProcessor, having private access to the processing
     * context and ensuring a safe single allocation of the individual method-processing contexts.
     */
    public MethodProcessingContext createMethodProcessingContext(ProgramMethod method) {
      MethodProcessingContext methodProcessingContext = new MethodProcessingContext(this, method);
      assert verifyContext(methodProcessingContext);
      return methodProcessingContext;
    }

    private StringBuilder buildSuffix(StringBuilder builder) {
      return builder.append('$').append(processorId);
    }

    @Override
    StringBuilder buildContextDescriptorForTesting(StringBuilder builder) {
      return buildSuffix(builder);
    }

    @Override
    StringBuilder buildSyntheticSuffix(StringBuilder builder) {
      return buildSuffix(builder);
    }
  }

  /** Description of the method context from which to synthesize. */
  public static class MethodProcessingContext extends ContextDescriptorProvider {
    private final ProcessorContext parent;
    private final ProgramMethod method;
    private int nextId = 0;

    private MethodProcessingContext(ProcessorContext parent, ProgramMethod method) {
      this.parent = parent;
      this.method = method;
    }

    /**
     * Create a unique processing context.
     *
     * <p>The uniqueness of the context requires that the parent, eg, method-context, is unique and
     * that the processing of that entity is such that the calls to this method happen in a
     * deterministic order, eg, by the processing of method instructions being single threaded.
     */
    public UniqueContext createUniqueContext() {
      UniqueContext uniqueContext = new UniqueContext(this, nextId++);
      assert parent.verifyContext(uniqueContext);
      return uniqueContext;
    }

    DexProgramClass getClassContext() {
      return method.getHolder();
    }

    private StringBuilder buildSuffix(StringBuilder builder) {
      // TODO(b/172194101): Sanitize the method descriptor instead of hashing.
      Hasher hasher = Hashing.sha256().newHasher();
      method.getReference().hash(hasher);
      return builder.append('$').append(hasher.hash().toString());
    }

    @Override
    StringBuilder buildContextDescriptorForTesting(StringBuilder builder) {
      // Put the type first in the context descriptor.
      builder.append(getClassContext().getType().toDescriptorString());
      return buildSuffix(parent.buildContextDescriptorForTesting(builder));
    }

    @Override
    StringBuilder buildSyntheticSuffix(StringBuilder builder) {
      return buildSuffix(parent.buildSyntheticSuffix(builder));
    }
  }

  public static class UniqueContext extends ContextDescriptorProvider {
    private final MethodProcessingContext parent;
    private final int positionId;

    private UniqueContext(MethodProcessingContext parent, int positionId) {
      this.parent = parent;
      this.positionId = positionId;
    }

    private StringBuilder buildSuffix(StringBuilder builder) {
      return builder.append('$').append(positionId);
    }

    @Override
    StringBuilder buildContextDescriptorForTesting(StringBuilder builder) {
      return buildSuffix(parent.buildContextDescriptorForTesting(builder));
    }

    @Override
    StringBuilder buildSyntheticSuffix(StringBuilder builder) {
      return buildSuffix(parent.buildSyntheticSuffix(builder));
    }

    public DexProgramClass getClassContext() {
      return parent.getClassContext();
    }

    public String getSyntheticSuffix() {
      return buildSyntheticSuffix(new StringBuilder()).toString();
    }
  }
}
