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

import com.android.tools.r8.debuginfo.DebugRepresentation;
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.dex.DebugBytecodeWriter;
import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.dex.MixedSectionCollection;
import com.android.tools.r8.dex.code.DexInstruction;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.utils.ArrayUtils;
import com.android.tools.r8.utils.LebUtils;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.structural.CompareToVisitor;
import com.android.tools.r8.utils.structural.Equatable;
import com.android.tools.r8.utils.structural.HashingVisitor;
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 java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

public abstract class DexDebugInfo extends CachedHashValueDexItem
    implements StructuralItem<DexDebugInfo> {

  private enum DebugInfoKind {
    EVENT_BASED,
    PC_BASED
  }

  abstract DebugInfoKind getKind();

  abstract int internalAcceptCompareTo(DexDebugInfo other, CompareToVisitor visitor);

  public abstract int getStartLine();

  public abstract int getParameterCount();

  public boolean isEventBasedInfo() {
    return getKind() == DebugInfoKind.EVENT_BASED;
  }

  public boolean isPcBasedInfo() {
    return getKind() == DebugInfoKind.PC_BASED;
  }

  public EventBasedDebugInfo asEventBasedInfo() {
    return null;
  }

  public PcBasedDebugInfo asPcBasedInfo() {
    return null;
  }

  @Override
  abstract void collectMixedSectionItems(MixedSectionCollection collection);

  @Override
  public abstract DexDebugInfo self();

  @Override
  public StructuralMapping<DexDebugInfo> getStructuralMapping() {
    throw new Unreachable();
  }

  @Override
  public abstract void acceptHashing(HashingVisitor visitor);

  @Override
  public int acceptCompareTo(DexDebugInfo other, CompareToVisitor visitor) {
    int diff = visitor.visitInt(getKind().ordinal(), other.getKind().ordinal());
    if (diff != 0) {
      return diff;
    }
    return internalAcceptCompareTo(other, visitor);
  }

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

  public static class PcBasedDebugInfo extends DexDebugInfo implements DexDebugInfoForWriting {
    public static final int START_LINE = 1;
    private final int parameterCount;
    private final int maxPc;

    private static void specify(StructuralSpecification<PcBasedDebugInfo, ?> spec) {
      spec.withInt(d -> d.parameterCount).withInt(d -> d.maxPc);
    }

    public PcBasedDebugInfo(int parameterCount, int maxPc) {
      this.parameterCount = parameterCount;
      this.maxPc = maxPc;
    }

    public int getMaxPc() {
      return maxPc;
    }

    @Override
    public int getStartLine() {
      return START_LINE;
    }

    @Override
    public int getParameterCount() {
      return parameterCount;
    }

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

    @Override
    public PcBasedDebugInfo asPcBasedInfo() {
      return this;
    }

    @Override
    DebugInfoKind getKind() {
      return DebugInfoKind.PC_BASED;
    }

    @Override
    protected int computeHashCode() {
      return Objects.hash(parameterCount, maxPc);
    }

    @Override
    public void acceptHashing(HashingVisitor visitor) {
      visitor.visit(this, PcBasedDebugInfo::specify);
    }

    @Override
    int internalAcceptCompareTo(DexDebugInfo other, CompareToVisitor visitor) {
      assert other.isPcBasedInfo();
      return visitor.visit(this, other.asPcBasedInfo(), PcBasedDebugInfo::specify);
    }

    @Override
    public void collectMixedSectionItems(MixedSectionCollection collection) {
      collection.add(this);
    }

    @Override
    public void collectIndexedItems(AppView<?> appView, IndexedItemCollection indexedItems) {
      // No indexed items to collect.
    }

    public static int estimatedWriteSize(int parameterCount, int maxPc) {
      return LebUtils.sizeAsUleb128(START_LINE)
          + LebUtils.sizeAsUleb128(parameterCount)
          + parameterCount * LebUtils.sizeAsUleb128(0)
          + 1
          + maxPc
          + 1;
    }

    @Override
    public int estimatedWriteSize() {
      return estimatedWriteSize(parameterCount, maxPc);
    }

    @Override
    public void write(
        DebugBytecodeWriter writer, ObjectToOffsetMapping mapping, GraphLens graphLens) {
      writer.putUleb128(START_LINE);
      writer.putUleb128(parameterCount);
      for (int i = 0; i < parameterCount; i++) {
        writer.putString(null);
      }
      mapping.dexItemFactory().zeroChangeDefaultEvent.writeOn(writer, mapping, graphLens);
      for (int i = 0; i < maxPc; i++) {
        mapping.dexItemFactory().oneChangeDefaultEvent.writeOn(writer, mapping, graphLens);
      }
      writer.putByte(Constants.DBG_END_SEQUENCE);
    }

    @Override
    public String toString() {
      return "PcBasedDebugInfo (params: "
          + parameterCount
          + ", max-pc: "
          + StringUtils.hexString(maxPc, 2)
          + ")";
    }
  }

  public static class EventBasedDebugInfo extends DexDebugInfo {

    public final int startLine;
    public final DexString[] parameters;
    public DexDebugEvent[] events;

    private static void specify(StructuralSpecification<EventBasedDebugInfo, ?> spec) {
      spec.withInt(d -> d.startLine)
          .withItemArrayAllowingNullMembers(d -> d.parameters)
          .withItemArray(d -> d.events);
    }

    public EventBasedDebugInfo(int startLine, DexString[] parameters, DexDebugEvent[] events) {
      assert startLine >= 0;
      this.startLine = startLine;
      this.parameters = parameters;
      this.events = events;
    }

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

    @Override
    public EventBasedDebugInfo asEventBasedInfo() {
      return this;
    }

    @Override
    DebugInfoKind getKind() {
      return DebugInfoKind.EVENT_BASED;
    }

    @Override
    public int getStartLine() {
      return startLine;
    }

    @Override
    public int getParameterCount() {
      return parameters.length;
    }

    public List<DexDebugEntry> computeEntries(DexMethod method) {
      DexDebugEntryBuilder builder = new DexDebugEntryBuilder(startLine, method);
      for (DexDebugEvent event : events) {
        event.accept(builder);
      }
      return builder.build();
    }

    @Override
    public int computeHashCode() {
      return startLine + Arrays.hashCode(parameters) * 7 + Arrays.hashCode(events) * 13;
    }

    @Override
    public void acceptHashing(HashingVisitor visitor) {
      visitor.visit(this, EventBasedDebugInfo::specify);
    }

    @Override
    int internalAcceptCompareTo(DexDebugInfo other, CompareToVisitor visitor) {
      assert other.isEventBasedInfo();
      return visitor.visit(this, other.asEventBasedInfo(), EventBasedDebugInfo::specify);
    }

    public void collectIndexedItems(AppView<?> appView, IndexedItemCollection indexedItems) {
      for (DexString parameter : parameters) {
        if (parameter != null) {
          parameter.collectIndexedItems(indexedItems);
        }
      }
      for (DexDebugEvent event : events) {
        event.collectIndexedItems(appView, indexedItems);
      }
    }

    @Override
    void collectMixedSectionItems(MixedSectionCollection collection) {
      // Only writable info should be iterated for collection.
      throw new Unreachable();
    }

    @Override
    public String toString() {
      StringBuilder builder = new StringBuilder();
      builder.append("DebugInfo (line " + startLine + ") events: [\n");
      for (DexDebugEvent event : events) {
        builder.append("  ").append(event).append("\n");
      }
      builder.append("  END_SEQUENCE\n");
      builder.append("]\n");
      return builder.toString();
    }
  }

  public static EventBasedDebugInfo convertToEventBased(DexCode code, DexItemFactory factory) {
    if (code.getDebugInfo() == null) {
      return null;
    }
    if (code.getDebugInfo().isEventBasedInfo()) {
      return code.getDebugInfo().asEventBasedInfo();
    }
    assert code.getDebugInfo().isPcBasedInfo();
    PcBasedDebugInfo pcBasedDebugInfo = code.getDebugInfo().asPcBasedInfo();
    assert DebugRepresentation.verifyLastExecutableInstructionWithinBound(
        code, pcBasedDebugInfo.maxPc);
    // Generate a line event at each throwing instruction.
    DexInstruction[] instructions = code.instructions;
    return forceConvertToEventBasedDebugInfo(pcBasedDebugInfo, instructions, factory);
  }

  public static EventBasedDebugInfo forceConvertToEventBasedDebugInfo(
      PcBasedDebugInfo pcBasedDebugInfo, DexInstruction[] instructions, DexItemFactory factory) {
    List<DexDebugEvent> events = new ArrayList<>(instructions.length);
    int delta = 0;
    for (DexInstruction instruction : instructions) {
      if (instruction.canThrow()) {
        DexDebugEventBuilder.addDefaultEventWithAdvancePcIfNecessary(delta, delta, events, factory);
        delta = 0;
      }
      delta += instruction.getSize();
    }
    return new EventBasedDebugInfo(
        PcBasedDebugInfo.START_LINE,
        new DexString[pcBasedDebugInfo.getParameterCount()],
        events.toArray(DexDebugEvent.EMPTY_ARRAY));
  }

  public static DexDebugInfoForWriting convertToWritable(DexDebugInfo debugInfo) {
    if (debugInfo == null) {
      return null;
    }
    if (debugInfo.isPcBasedInfo()) {
      return debugInfo.asPcBasedInfo();
    }
    EventBasedDebugInfo eventBasedInfo = debugInfo.asEventBasedInfo();
    DexDebugEvent[] writableEvents =
        ArrayUtils.filter(
            eventBasedInfo.events, DexDebugEvent::isWritableEvent, DexDebugEvent.EMPTY_ARRAY);
    return new WritableEventBasedDebugInfo(
        eventBasedInfo.startLine, eventBasedInfo.parameters, writableEvents);
  }

  private static class WritableEventBasedDebugInfo extends EventBasedDebugInfo
      implements DexDebugInfoForWriting {

    private WritableEventBasedDebugInfo(
        int startLine, DexString[] parameters, DexDebugEvent[] writableEvents) {
      super(startLine, parameters, writableEvents);
    }

    @Override
    public void collectIndexedItems(AppView<?> appView, IndexedItemCollection indexedItems) {
      super.collectIndexedItems(appView, indexedItems);
    }

    @Override
    public void collectMixedSectionItems(MixedSectionCollection collection) {
      collection.add(this);
    }

    @Override
    public int estimatedWriteSize() {
      return LebUtils.sizeAsUleb128(startLine)
          + LebUtils.sizeAsUleb128(parameters.length)
          // Estimate 4 bytes per parameter pointer.
          + parameters.length * 4
          + events.length
          + 1;
    }

    @Override
    public void write(
        DebugBytecodeWriter writer, ObjectToOffsetMapping mapping, GraphLens graphLens) {
      writer.putUleb128(startLine);
      writer.putUleb128(parameters.length);
      for (DexString name : parameters) {
        writer.putString(name);
      }
      for (DexDebugEvent event : events) {
        event.writeOn(writer, mapping, graphLens);
      }
      writer.putByte(Constants.DBG_END_SEQUENCE);
    }
  }
}
