// 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.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 {
    private static final int START_LINE = 0;
    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;
    }

    @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();
    // Generate a line event at each throwing instruction.
    List<DexDebugEvent> events = new ArrayList<>(code.instructions.length);
    int pc = 0;
    int delta = 0;
    for (DexInstruction instruction : code.instructions) {
      if (instruction.canThrow()) {
        DexDebugEventBuilder.addDefaultEventWithAdvancePcIfNecessary(delta, delta, events, factory);
        pc += delta;
        delta = 0;
      }
      delta += instruction.getSize();
    }
    assert pc + delta - ArrayUtils.last(code.instructions).getSize() <= pcBasedDebugInfo.maxPc;
    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);
    }
  }
}
