// Copyright (c) 2017, 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.ir.code;

import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.utils.structural.StructuralItem;
import com.android.tools.r8.utils.structural.StructuralMapping;
import com.android.tools.r8.utils.structural.StructuralSpecification;
import com.google.common.annotations.VisibleForTesting;
import java.util.Objects;

public class Position implements StructuralItem<Position> {

  // A no-position marker. Not having a position means the position is implicitly defined by the
  // context, e.g., the marker does not materialize anything concrete.
  private static final Position NO_POSITION = new Position(-1, null, null, null, false);

  // A synthetic marker position that should never materialize.
  // This is used specifically to mark exceptional exit blocks from synchronized methods in release.
  private static final Position NO_POSITION_SYNTHETIC = new Position(-1, null, null, null, true);

  // Fake position to use for representing an actual position in testing code.
  private static final Position TESTING_POSITION = new Position(0, null, null, null, true);

  public final int line;
  public final DexString file;
  public final boolean synthetic;

  // If there's no inlining, callerPosition is null.
  //
  // For an inlined instruction its Position contains the inlinee's line and method and
  // callerPosition is the position of the invoke instruction in the caller.

  public final DexMethod method;
  public final Position callerPosition;

  private static void specify(StructuralSpecification<Position, ?> spec) {
    spec.withInt(p -> p.line)
        .withNullableItem(p -> p.file)
        .withBool(p -> p.synthetic)
        .withNullableItem(p -> p.method)
        .withNullableItem(p -> p.callerPosition);
  }

  public Position(int line, DexString file, DexMethod method, Position callerPosition) {
    this(line, file, method, callerPosition, false);
    assert line >= 0;
    assert method != null;
  }

  private Position(
      int line, DexString file, DexMethod method, Position callerPosition, boolean synthetic) {
    this.line = line;
    this.file = file;
    this.synthetic = synthetic;
    this.method = method;
    this.callerPosition = callerPosition;
    assert callerPosition == null || callerPosition.method != null;
  }

  public static Position synthetic(int line, DexMethod method, Position callerPosition) {
    assert line >= 0;
    assert method != null;
    return new Position(line, null, method, callerPosition, true);
  }

  public static Position none() {
    return NO_POSITION;
  }

  public static Position syntheticNone() {
    return NO_POSITION_SYNTHETIC;
  }

  @VisibleForTesting
  public static Position testingPosition() {
    return TESTING_POSITION;
  }

  // This factory method is used by the Inliner to create Positions when the caller has no valid
  // positions. Since the callee still may have valid positions we need a non-null Position to set
  // it as the caller of the inlined Positions.
  public static Position noneWithMethod(DexMethod method, Position callerPosition) {
    assert method != null;
    return new Position(-1, null, method, callerPosition, false);
  }

  public static Position getPositionForInlining(
      AppView<?> appView, InvokeMethod invoke, ProgramMethod context) {
    Position position = invoke.getPosition();
    if (position.method == null) {
      assert position.isNone();
      position = Position.noneWithMethod(context.getReference(), null);
    }
    assert position.getOutermostCaller().method
        == appView.graphLens().getOriginalMethodSignature(context.getReference());
    return position;
  }

  public boolean hasCallerPosition() {
    return callerPosition != null;
  }

  @Override
  public Position self() {
    return this;
  }

  @Override
  public StructuralMapping<Position> getStructuralMapping() {
    return Position::specify;
  }

  public boolean isNone() {
    return line == -1;
  }

  public boolean isSyntheticNone() {
    return this == NO_POSITION_SYNTHETIC;
  }

  public boolean isSome() {
    return !isNone();
  }

  // Follow the linked list of callerPositions and return the last.
  // Return this if no inliner.
  public Position getOutermostCaller() {
    Position lastPosition = this;
    while (lastPosition.callerPosition != null) {
      lastPosition = lastPosition.callerPosition;
    }
    return lastPosition;
  }

  public Position getCallerPosition() {
    return callerPosition;
  }

  public Position withCallerPosition(Position callerPosition) {
    return new Position(line, file, method, callerPosition, synthetic);
  }

  public Position withOutermostCallerPosition(Position newOutermostCallerPosition) {
    return withCallerPosition(
        hasCallerPosition()
            ? getCallerPosition().withOutermostCallerPosition(newOutermostCallerPosition)
            : newOutermostCallerPosition);
  }

  @Override
  public boolean equals(Object other) {
    return other instanceof Position && compareTo((Position) other) == 0;
  }

  @Override
  public int hashCode() {
    int result = line;
    result = 31 * result + Objects.hashCode(file);
    result = 31 * result + (synthetic ? 1 : 0);
    result = 31 * result + Objects.hashCode(method);
    result = 31 * result + Objects.hashCode(callerPosition);
    return result;
  }

  private String toString(boolean forceMethod) {
    if (isNone()) {
      return "--";
    }
    StringBuilder builder = new StringBuilder();
    if (file != null) {
      builder.append(file).append(":");
    }
    builder.append("#").append(line);
    if (method != null && (forceMethod || callerPosition != null)) {
      builder.append(":").append(method.name);
    }
    if (callerPosition != null) {
      Position caller = callerPosition;
      while (caller != null) {
        builder.append(";").append(caller.line).append(":").append(caller.method.name);
        caller = caller.callerPosition;
      }
    }
    return builder.toString();
  }

  @Override
  public String toString() {
    return toString(false);
  }
}
