// 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.Int2StructuralItemArrayMap;
import com.android.tools.r8.utils.structural.Equatable;
import com.android.tools.r8.utils.structural.HashCodeVisitor;
import com.android.tools.r8.utils.structural.StructuralItem;
import com.android.tools.r8.utils.structural.StructuralMapping;
import com.android.tools.r8.utils.structural.StructuralSpecification;

public abstract class Position implements StructuralItem<Position> {

  // Compare ID(s) for positions.
  private static final int SOURCE_POSITION_COMPARE_ID = 1;
  private static final int SYNTHETIC_POSITION_COMPARE_ID = 2;
  private static final int OUTLINE_POSITION_COMPARE_ID = 3;
  private static final int OUTLINE_CALLER_POSITION_COMPARE_ID = 4;

  protected final int line;
  protected final DexMethod method;

  // 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.
  protected final Position callerPosition;

  private final boolean removeInnerFramesIfThrowingNpe;

  private Position(
      int line, DexMethod method, Position callerPosition, boolean removeInnerFramesIfThrowingNpe) {
    this.line = line;
    this.method = method;
    this.callerPosition = callerPosition;
    this.removeInnerFramesIfThrowingNpe = removeInnerFramesIfThrowingNpe;
  }

  public boolean isSyntheticPosition() {
    return false;
  }

  public boolean isAdditionalMappingInfoPosition() {
    return false;
  }

  public boolean isRemoveInnerFramesIfThrowingNpe() {
    return removeInnerFramesIfThrowingNpe;
  }

  public boolean isOutline() {
    return false;
  }

  public DexMethod getOutlineCallee() {
    return null;
  }

  public Int2StructuralItemArrayMap<Position> getOutlinePositions() {
    return null;
  }

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

  public Position getCallerPosition() {
    return callerPosition;
  }

  public int getLine() {
    return line;
  }

  public DexMethod getMethod() {
    return method;
  }

  public static Position none() {
    return SourcePosition.NO_POSITION;
  }

  public boolean hasFile() {
    return false;
  }

  public DexString getFile() {
    return null;
  }

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

  // Unique id to determine the ordering of positions
  public abstract int getCompareToId();

  @Override
  public abstract StructuralMapping<Position> getStructuralMapping();

  private static void specifyBasePosition(StructuralSpecification<Position, ?> spec) {
    spec.withInt(Position::getCompareToId)
        .withInt(Position::getLine)
        .withNullableItem(Position::getMethod)
        .withNullableItem(Position::getCallerPosition)
        .withBool(Position::isRemoveInnerFramesIfThrowingNpe);
  }

  public static Position syntheticNone() {
    return SyntheticPosition.NO_POSITION_SYNTHETIC;
  }

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

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

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

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

  @Override
  public final boolean equals(Object other) {
    return Equatable.equalsImpl(this, other);
  }

  @Override
  public final int hashCode() {
    return HashCodeVisitor.run(this);
  }

  private String toString(boolean forceMethod) {
    if (isNone()) {
      return "--";
    }
    StringBuilder builder = new StringBuilder();
    if (hasFile()) {
      builder.append(getFile()).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 abstract PositionBuilder<?, ?> builderWithCopy();

  public abstract static class PositionBuilder<
      P extends Position, B extends PositionBuilder<P, B>> {

    protected int line = -1;
    protected DexMethod method;
    protected Position callerPosition;
    protected boolean removeInnerFramesIfThrowingNpe;

    protected boolean noCheckOfPosition;
    protected boolean noCheckOfMethod;

    abstract B self();

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

    public boolean hasLine() {
      return line > -1;
    }

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

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

    public B setRemoveInnerFramesIfThrowingNpe(boolean removeInnerFramesIfThrowingNpe) {
      this.removeInnerFramesIfThrowingNpe = removeInnerFramesIfThrowingNpe;
      return self();
    }

    public B disableLineCheck() {
      noCheckOfPosition = true;
      return self();
    }

    public B disableMethodCheck() {
      noCheckOfMethod = true;
      return self();
    }

    public abstract P build();
  }

  public static class SourcePosition extends 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 SourcePosition NO_POSITION =
        new SourcePosition(-1, null, null, false, null);

    public final DexString file;

    private static void specify(StructuralSpecification<Position, ?> spec) {
      spec.withSpec(Position::specifyBasePosition).withNullableItem(Position::getFile);
    }

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

    @Override
    public boolean hasFile() {
      return file != null;
    }

    @Override
    public DexString getFile() {
      return file;
    }

    @Override
    public int getCompareToId() {
      return SOURCE_POSITION_COMPARE_ID;
    }

    @Override
    public PositionBuilder<?, ?> builderWithCopy() {
      return builder()
          .setLine(line)
          .setFile(file)
          .setMethod(method)
          .setCallerPosition(callerPosition);
    }

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

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

    public static class SourcePositionBuilder
        extends PositionBuilder<SourcePosition, SourcePositionBuilder> {

      private DexString file;

      @Override
      SourcePositionBuilder self() {
        return this;
      }

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

      @Override
      public SourcePosition build() {
        assert noCheckOfPosition || line >= 0;
        assert noCheckOfMethod || method != null;
        return new SourcePosition(
            line, method, callerPosition, removeInnerFramesIfThrowingNpe, file);
      }
    }
  }

  public static class SyntheticPosition extends Position {

    // 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 SyntheticPosition(-1, null, null, false);

    private SyntheticPosition(
        int line,
        DexMethod method,
        Position callerPosition,
        boolean removeInnerFramesIfThrowingNpe) {
      super(line, method, callerPosition, removeInnerFramesIfThrowingNpe);
    }

    @Override
    public boolean isSyntheticPosition() {
      return true;
    }

    @Override
    public int getCompareToId() {
      return SYNTHETIC_POSITION_COMPARE_ID;
    }

    @Override
    public PositionBuilder<?, ?> builderWithCopy() {
      return builder().setLine(line).setMethod(method).setCallerPosition(callerPosition);
    }

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

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

    public static class SyntheticPositionBuilder
        extends PositionBuilder<SyntheticPosition, SyntheticPositionBuilder> {

      private SyntheticPositionBuilder() {}

      @Override
      SyntheticPositionBuilder self() {
        return this;
      }

      @Override
      public SyntheticPosition build() {
        assert noCheckOfPosition || line >= 0;
        assert noCheckOfMethod || method != null;
        return new SyntheticPosition(line, method, callerPosition, removeInnerFramesIfThrowingNpe);
      }
    }
  }

  public static class OutlinePosition extends Position {

    private OutlinePosition(
        int line,
        DexMethod method,
        Position callerPosition,
        boolean removeInnerFramesIfThrowingNpe) {
      super(line, method, callerPosition, removeInnerFramesIfThrowingNpe);
    }

    @Override
    public boolean isOutline() {
      return true;
    }

    @Override
    public int getCompareToId() {
      return OUTLINE_POSITION_COMPARE_ID;
    }

    @Override
    public PositionBuilder<?, ?> builderWithCopy() {
      return builder().setLine(line).setMethod(method).setCallerPosition(callerPosition);
    }

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

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

    public static class OutlinePositionBuilder
        extends PositionBuilder<OutlinePosition, OutlinePositionBuilder> {

      private OutlinePositionBuilder() {}

      @Override
      OutlinePositionBuilder self() {
        return this;
      }

      @Override
      public OutlinePosition build() {
        return new OutlinePosition(line, method, callerPosition, removeInnerFramesIfThrowingNpe);
      }
    }
  }

  public static class OutlineCallerPosition extends Position {

    private final Int2StructuralItemArrayMap<Position> outlinePositions;
    private final DexMethod outlineCallee;
    private final boolean isOutline;

    public static void specify(StructuralSpecification<Position, ?> spec) {
      spec.withSpec(Position::specifyBasePosition)
          .withBool(Position::isOutline)
          .withItem(Position::getOutlineCallee)
          .withItem(Position::getOutlinePositions);
    }

    private OutlineCallerPosition(
        int line,
        DexMethod method,
        Position callerPosition,
        boolean removeInnerFramesIfThrowingNpe,
        Int2StructuralItemArrayMap<Position> outlinePositions,
        DexMethod outlineCallee,
        boolean isOutline) {
      super(line, method, callerPosition, removeInnerFramesIfThrowingNpe);
      this.outlinePositions = outlinePositions;
      this.outlineCallee = outlineCallee;
      this.isOutline = isOutline;
    }

    @Override
    public boolean isNone() {
      return false;
    }

    @Override
    public int getCompareToId() {
      return OUTLINE_CALLER_POSITION_COMPARE_ID;
    }

    @Override
    public PositionBuilder<?, ?> builderWithCopy() {
      OutlineCallerPositionBuilder outlineCallerPositionBuilder =
          builder()
              .setLine(line)
              .setMethod(method)
              .setCallerPosition(callerPosition)
              .setOutlineCallee(outlineCallee)
              .setIsOutline(isOutline);
      outlinePositions.forEach(outlineCallerPositionBuilder::addOutlinePosition);
      return outlineCallerPositionBuilder;
    }

    @Override
    public boolean isOutline() {
      return isOutline;
    }

    @Override
    public DexMethod getOutlineCallee() {
      return outlineCallee;
    }

    @Override
    public Int2StructuralItemArrayMap<Position> getOutlinePositions() {
      return outlinePositions;
    }

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

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

    public static class OutlineCallerPositionBuilder
        extends PositionBuilder<OutlineCallerPosition, OutlineCallerPositionBuilder> {

      private final Int2StructuralItemArrayMap.Builder<Position> outlinePositionsBuilder =
          Int2StructuralItemArrayMap.builder();
      private DexMethod outlineCallee;
      private boolean isOutline;

      private OutlineCallerPositionBuilder() {}

      @Override
      OutlineCallerPositionBuilder self() {
        return this;
      }

      public OutlineCallerPositionBuilder setOutlineCallee(DexMethod outlineCallee) {
        this.outlineCallee = outlineCallee;
        return this;
      }

      public OutlineCallerPositionBuilder addOutlinePosition(int line, Position callerPosition) {
        outlinePositionsBuilder.put(line, callerPosition);
        return this;
      }

      public OutlineCallerPositionBuilder setIsOutline(boolean isOutline) {
        this.isOutline = isOutline;
        return this;
      }

      public boolean hasOutlinePositions() {
        return !outlinePositionsBuilder.isEmpty();
      }

      @Override
      public OutlineCallerPosition build() {
        assert noCheckOfPosition || line >= 0;
        assert noCheckOfMethod || method != null;
        return new OutlineCallerPosition(
            line,
            method,
            callerPosition,
            removeInnerFramesIfThrowingNpe,
            outlinePositionsBuilder.build(),
            outlineCallee,
            isOutline);
      }
    }
  }
}
