// 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, 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, false);

  // 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, false);

  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;
  public final boolean removeInnerFrameIfThrowingNpe;

  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);
  }

  private Position(
      int line,
      DexString file,
      DexMethod method,
      Position callerPosition,
      boolean synthetic,
      boolean removeInnerFrameIfThrowingNpe) {
    this.line = line;
    this.file = file;
    this.synthetic = synthetic;
    this.method = method;
    this.callerPosition = callerPosition;
    this.removeInnerFrameIfThrowingNpe = removeInnerFrameIfThrowingNpe;
    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, false);
  }

  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, 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 withOutermostCallerPosition(Position newOutermostCallerPosition) {
    return builderWithCopy()
        .setCallerPosition(
            hasCallerPosition()
                ? getCallerPosition().withOutermostCallerPosition(newOutermostCallerPosition)
                : newOutermostCallerPosition)
        .build();
  }

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

  @Override
  public int hashCode() {
    return Objects.hash(
        line, file, synthetic, method, callerPosition, removeInnerFrameIfThrowingNpe);
  }

  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);
  }

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

  public Builder builderWithCopy() {
    return new Builder()
        .setLine(line)
        .setFile(file)
        .setMethod(method)
        .setCallerPosition(callerPosition)
        .setSynthetic(synthetic)
        .setRemoveInnerFramesIfThrowingNpe(removeInnerFrameIfThrowingNpe);
  }

  public static class Builder {

    public int line;
    public DexString file;
    public boolean synthetic;
    public DexMethod method;
    public Position callerPosition;
    public boolean removeInnerFrameIfThrowingNpe;

    public Builder setLine(int line) {
      this.line = line;
      return this;
    }

    public Builder setFile(DexString file) {
      this.file = file;
      return this;
    }

    public Builder setSynthetic(boolean synthetic) {
      this.synthetic = synthetic;
      return this;
    }

    public Builder setMethod(DexMethod method) {
      this.method = method;
      return this;
    }

    public Builder setCallerPosition(Position callerPosition) {
      this.callerPosition = callerPosition;
      return this;
    }

    public Builder setRemoveInnerFramesIfThrowingNpe(boolean removeInnerFramesIfThrowingNpe) {
      this.removeInnerFrameIfThrowingNpe = removeInnerFramesIfThrowingNpe;
      return this;
    }

    public Position build() {
      assert line >= 0;
      assert method != null;
      return new Position(
          line, file, method, callerPosition, synthetic, removeInnerFrameIfThrowingNpe);
    }
  }
}
