// 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.graph;

import com.android.tools.r8.graph.DexDebugEvent.SetPositionFrame;
import com.android.tools.r8.graph.DexDebugInfo.EventBasedDebugInfo;
import com.android.tools.r8.ir.code.ValueType;
import com.google.common.collect.ImmutableMap;
import it.unimi.dsi.fastutil.ints.Int2ReferenceArrayMap;
import it.unimi.dsi.fastutil.ints.Int2ReferenceMap;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

/**
 * Builder to construct a "per position" representation of the debug information.
 *
 * <p>This builder is relatively relaxed about the stream of build operations and should accept any
 * stream from any input file we expect to process correctly.
 */
public class DexDebugEntryBuilder implements DexDebugEventVisitor {

  private static class LocalEntry {
    DebugLocalInfo current;
    DebugLocalInfo last;

    void set(DebugLocalInfo value) {
      current = value;
      last = value;
    }

    void unset() {
      current = null;
    }

    void reset() {
      current = last;
    }
  }

  // The variables of the state machine.
  private boolean prologueEnd = false;
  private boolean epilogueBegin = false;
  private final Map<Integer, LocalEntry> locals = new HashMap<>();
  private final Int2ReferenceMap<DebugLocalInfo> arguments = new Int2ReferenceArrayMap<>();

  // Delayed construction of an entry. Is finalized once locals information has been collected.
  private DexDebugEntry pending = null;

  // Canonicalization of locals (the IR/Dex builders assume identity of locals).
  private final Map<DebugLocalInfo, DebugLocalInfo> canonicalizedLocals = new HashMap<>();

  // Resulting debug entries.
  private List<DexDebugEntry> entries = new ArrayList<>();
  private final DexDebugPositionState positionState;

  public DexDebugEntryBuilder(int startLine, DexMethod method) {
    assert method != null;
    positionState = new DexDebugPositionState(startLine, method);
  }

  public DexDebugEntryBuilder(DexEncodedMethod method, DexItemFactory factory) {
    assert method != null && method.getReference() != null;
    DexCode code = method.getCode().asDexCode();
    EventBasedDebugInfo info = code.getDebugInfo().asEventBasedInfo();
    // Only event based debug info supports conversion to entries.
    assert info != null;
    positionState = new DexDebugPositionState(info.startLine, method.getReference());
    int argumentRegister = code.registerSize - code.incomingRegisterSize;
    if (!method.accessFlags.isStatic()) {
      DexString name = factory.thisName;
      DexType type = method.getHolderType();
      startArgument(argumentRegister, name, type);
      argumentRegister += ValueType.fromDexType(type).requiredRegisters();
    }
    DexType[] types = method.getReference().proto.parameters.values;
    DexString[] names = info.parameters;
    for (int i = 0; i < types.length; i++) {
      // If null, the parameter has a parameterized type and the local is introduced in the stream.
      // TODO(114704754): The check 'i < names.length' is a bug workaround which should be removed.
      if (i < names.length && names[i] != null) {
        startArgument(argumentRegister, names[i], types[i]);
      }
      argumentRegister += ValueType.fromDexType(types[i]).requiredRegisters();
    }
    for (DexDebugEvent event : info.events) {
      event.accept(this);
    }
  }

  public Int2ReferenceMap<DebugLocalInfo> getArguments() {
    return arguments;
  }

  @Override
  public void visit(DexDebugEvent.AdvancePC advancePC) {
    positionState.visit(advancePC);
    entryEventReceived(false);
  }

  @Override
  public void visit(DexDebugEvent.AdvanceLine advanceLine) {
    positionState.visit(advanceLine);
  }

  @Override
  public void visit(SetPositionFrame setPositionFrame) {
    positionState.visit(setPositionFrame);
  }

  @Override
  public void visit(DexDebugEvent.Default defaultEvent) {
    positionState.visit(defaultEvent);
    entryEventReceived(true);
  }

  @Override
  public void visit(DexDebugEvent.SetFile setFile) {
    positionState.visit(setFile);
  }

  @Override
  public void visit(DexDebugEvent.SetPrologueEnd setPrologueEnd) {
    prologueEnd = true;
  }

  @Override
  public void visit(DexDebugEvent.SetEpilogueBegin setEpilogueBegin) {
    epilogueBegin = true;
  }

  public void startArgument(int register, DexString name, DexType type) {
    DebugLocalInfo argument = canonicalize(name, type, null);
    arguments.put(register, argument);
    getEntry(register).set(argument);
  }

  @Override
  public void visit(DexDebugEvent.StartLocal setStartLocal) {
    getEntry(setStartLocal.registerNum)
        .set(canonicalize(setStartLocal.name, setStartLocal.type, setStartLocal.signature));
  }

  @Override
  public void visit(DexDebugEvent.EndLocal endLocal) {
    getEntry(endLocal.registerNum).unset();
  }

  @Override
  public void visit(DexDebugEvent.RestartLocal restartLocal) {
    getEntry(restartLocal.registerNum).reset();
  }

  private void entryEventReceived(boolean lineEntry) {
    if (pending != null) {
      // Local changes contribute to the pending position entry.
      entries.add(
          new DexDebugEntry(
              pending.lineEntry,
              pending.address,
              pending.sourceFile,
              pending.prologueEnd,
              pending.epilogueBegin,
              getLocals(),
              pending.getPosition()));
    }
    pending =
        new DexDebugEntry(
            lineEntry,
            positionState.getCurrentPc(),
            null,
            prologueEnd,
            epilogueBegin,
            null,
            positionState.getPosition());
    prologueEnd = false;
    epilogueBegin = false;
  }

  public List<DexDebugEntry> build() {
    // Flush any pending entry.
    if (pending != null) {
      entryEventReceived(false); // To flush 'pending'.
      pending = null;
    }
    List<DexDebugEntry> result = entries;
    entries = null;
    return result;
  }

  private DebugLocalInfo canonicalize(DexString name, DexType type, DexString signature) {
    DebugLocalInfo local = new DebugLocalInfo(name, type, signature);
    DebugLocalInfo canonical = canonicalizedLocals.putIfAbsent(local, local);
    return canonical != null ? canonical : local;
  }

  private LocalEntry getEntry(int register) {
    LocalEntry entry = locals.get(register);
    if (entry == null) {
      entry = new LocalEntry();
      locals.put(register, entry);
    }
    return entry;
  }

  private ImmutableMap<Integer, DebugLocalInfo> getLocals() {
    ImmutableMap.Builder<Integer, DebugLocalInfo> builder = ImmutableMap.builder();
    for (Entry<Integer, LocalEntry> mapEntry : locals.entrySet()) {
      Integer register = mapEntry.getKey();
      LocalEntry entry = mapEntry.getValue();
      if (entry.current != null) {
        builder.put(register, entry.current);
      }
    }
    return builder.build();
  }
}
