// 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.dex.code;

import com.android.tools.r8.cf.code.CfInstruction;
import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.errors.InternalCompilerError;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexCallSite;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.IndexedDexItem;
import com.android.tools.r8.graph.ObjectToOffsetMapping;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.IRBuilder;
import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
import com.android.tools.r8.naming.ClassNameMapper;
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 java.nio.ShortBuffer;
import java.util.function.BiPredicate;

public abstract class DexInstruction implements CfOrDexInstruction, StructuralItem<DexInstruction> {
  public static final DexInstruction[] EMPTY_ARRAY = {};

  public static final int[] NO_TARGETS = null;
  public static final int[] EXIT_TARGET = {};

  private int offset;

  DexInstruction(BytecodeStream stream) {
    // When this constructor is invoked, we have already read 1 ushort from the stream.
    this.offset = stream.getOffset() - 1;
  }

  protected DexInstruction() {
    this.offset = -1;
  }

  static byte readSigned8BitValue(BytecodeStream stream) {
    return (byte) stream.nextByte();
  }

  static short read8BitValue(BytecodeStream stream) {
    return (short) stream.nextByte();
  }

  static short readSigned16BitValue(BytecodeStream stream) {
    // Convert to signed.
    return (short) stream.nextShort();
  }

  static char read16BitValue(BytecodeStream stream) {
    return (char) (stream.nextShort() & 0xffff);
  }

  static int readSigned32BitValue(BytecodeStream stream) {
    int low = read16BitValue(stream);
    int high = read16BitValue(stream);
    int result = ((high << 16) & 0xffff0000) | (low & 0xffff);
    return result;
  }

  static long read32BitValue(BytecodeStream stream) {
    long low = read16BitValue(stream);
    long high = read16BitValue(stream);
    long result = ((high & 0xffff) << 16) | (low & 0xffff);
    return result;
  }

  static long read64BitValue(BytecodeStream stream) {
    long low = read32BitValue(stream);
    long high = read32BitValue(stream);
    long result = (high << 32) | low;
    return result;
  }

  protected static short combineBytes(int high, int low) {
    return (short) (((high & 0xff) << 8) | (low & 0xff));
  }

  protected static int makeByte(int high, int low) {
    return ((high & 0xf) << 4) | (low & 0xf);
  }

  protected void writeFirst(int aa, ShortBuffer dest) {
    writeFirst(aa, dest, getOpcode());
  }

  protected void writeFirst(int aa, ShortBuffer dest, int opcode) {
    dest.put((short) (((aa & 0xff) << 8) | (opcode & 0xff)));
  }

  protected void writeFirst(int a, int b, ShortBuffer dest) {
    writeFirst(a, b, dest, getOpcode());
  }

  protected void writeFirst(int a, int b, ShortBuffer dest, int opcode) {
    dest.put((short) (((a & 0xf) << 12) | ((b & 0xf) << 8) | (opcode & 0xff)));
  }

  protected void write16BitValue(int value, ShortBuffer dest) {
    dest.put((short) value);
  }

  protected void write32BitValue(long value, ShortBuffer dest) {
    dest.put((short) (value & 0xffff));
    dest.put((short) ((value >> 16) & 0xffff));
  }

  protected void write64BitValue(long value, ShortBuffer dest) {
    write32BitValue(value & 0xffffffff, dest);
    write32BitValue((value >> 32) & 0xffffffff, dest);
  }

  protected void write16BitReference(
      IndexedDexItem item, ShortBuffer dest, ObjectToOffsetMapping mapping) {
    int index = item.getOffset(mapping);
    assert index == (index & 0xffff);
    write16BitValue(index, dest);
  }

  protected void write32BitReference(
      IndexedDexItem item, ShortBuffer dest, ObjectToOffsetMapping mapping) {
    write32BitValue(item.getOffset(mapping), dest);
  }

  public boolean hasOffset() {
    return offset >= 0;
  }

  public int getOffset() {
    return offset;
  }

  public void setOffset(int offset) {
    this.offset = offset;
  }

  @Override
  public CfInstruction asCfInstruction() {
    return null;
  }

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

  @Override
  public DexInstruction asDexInstruction() {
    return this;
  }

  public DexCheckCast asCheckCast() {
    return null;
  }

  public boolean isCheckCast() {
    return false;
  }

  public DexInstanceOf asInstanceOf() {
    return null;
  }

  public boolean isInstanceOf() {
    return false;
  }

  public DexConstString asConstString() {
    return null;
  }

  public boolean isConstString() {
    return false;
  }

  public DexConstClass asConstClass() {
    return null;
  }

  public boolean isConstClass() {
    return false;
  }

  public boolean isRecordFieldValues() {
    return false;
  }

  public DexItemBasedConstString asDexItemBasedConstString() {
    return null;
  }

  public boolean isDexItemBasedConstString() {
    return false;
  }

  public DexConstStringJumbo asConstStringJumbo() {
    return null;
  }

  public boolean isConstStringJumbo() {
    return false;
  }

  public boolean isInvokeVirtual() {
    return false;
  }

  public DexInvokeVirtual asInvokeVirtual() {
    return null;
  }

  public boolean isInvokeVirtualRange() {
    return false;
  }

  public DexInvokeVirtualRange asInvokeVirtualRange() {
    return null;
  }

  public boolean isSimpleNop() {
    return !isPayload() && this instanceof DexNop;
  }

  public boolean isPayload() {
    return false;
  }

  public boolean isSwitchPayload() {
    return false;
  }

  public boolean hasPayload() {
    return false;
  }

  public boolean isIntSwitch() {
    return false;
  }

  public boolean isThrow() {
    return false;
  }

  public int getPayloadOffset() {
    return 0;
  }

  public boolean ignoreCompatRules() {
    return false;
  }

  static String formatOffset(int offset) {
    return StringUtils.hexString(offset, 2);
  }

  static String formatDecimalOffset(int offset) {
    return offset >= 0 ? ("+" + offset) : Integer.toString(offset);
  }

  String formatRelativeOffset(int offset) {
    return formatOffset(getOffset() + offset) + " (" + formatDecimalOffset(offset) + ")";
  }

  String formatString(String left) {
    StringBuilder builder = new StringBuilder();
    StringUtils.appendLeftPadded(builder, formatOffset(getOffset()), 6);
    builder.append(": ");
    StringUtils.appendRightPadded(builder, getName(), 20);
    builder.append(left == null ? "" : left);
    return builder.toString();
  }

  String formatSmaliString(String left) {
    StringBuilder builder = new StringBuilder();
    builder.append("    ");
    if (left != null) {
      StringUtils.appendRightPadded(builder, getSmaliName(), 20);
      builder.append(left);
    } else {
      builder.append(getSmaliName());
    }
    return builder.toString();
  }

  public int[] getTargets() {
    return NO_TARGETS;
  }

  public abstract void buildIR(IRBuilder builder);

  public DexCallSite getCallSite() {
    return null;
  }

  public DexMethod getMethod() {
    return null;
  }

  public DexProto getProto() {
    return null;
  }

  public DexField getField() {
    return null;
  }

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

  @Override
  public abstract int hashCode();

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

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

  int getCompareToId() {
    return getOpcode();
  }

  // Abstract compare-to called only if the opcode/compare-id of the instruction matches.
  abstract int internalAcceptCompareTo(DexInstruction other, CompareToVisitor visitor);

  @Override
  public final int acceptCompareTo(DexInstruction other, CompareToVisitor visitor) {
    int opcodeDiff = visitor.visitInt(getCompareToId(), other.getCompareToId());
    if (opcodeDiff != 0) {
      return opcodeDiff;
    }
    opcodeDiff = visitor.visitInt(getOffset(), other.getOffset());
    return opcodeDiff != 0 ? opcodeDiff : internalAcceptCompareTo(other, visitor);
  }

  abstract void internalAcceptHashing(HashingVisitor visitor);

  @Override
  public final void acceptHashing(HashingVisitor visitor) {
    visitor.visitInt(getCompareToId());
    visitor.visitInt(getOffset());
    internalAcceptHashing(visitor);
  }

  public abstract String getName();

  public abstract String getSmaliName();

  public abstract int getOpcode();

  public abstract int getSize();

  public String toSmaliString(DexInstruction payloadUser) {
    throw new InternalCompilerError("Instruction " + payloadUser + " is not a payload user");
  }

  public abstract String toSmaliString(ClassNameMapper naming);

  public String toSmaliString() {
    return toSmaliString((ClassNameMapper) null);
  }

  public abstract String toString(ClassNameMapper naming);

  public String toString(ClassNameMapper naming, DexInstruction payloadUser) {
    throw new InternalCompilerError("Instruction " + payloadUser + " is not a payload user");
  }

  @Override
  public String toString() {
    return toString(null);
  }

  public abstract void write(
      ShortBuffer buffer,
      ProgramMethod context,
      GraphLens graphLens,
      ObjectToOffsetMapping mapping,
      LensCodeRewriterUtils rewriter);

  public abstract void collectIndexedItems(
      AppView<?> appView,
      IndexedItemCollection indexedItems,
      ProgramMethod context,
      LensCodeRewriterUtils rewriter);

  public boolean equals(
      DexInstruction other, BiPredicate<IndexedDexItem, IndexedDexItem> equality) {
    // In the default case, there is nothing to substitute.
    return this.equals(other);
  }

  public void registerUse(UseRegistry<?> registry) {
    // Intentionally empty
  }

  public boolean canThrow() {
    return false;
  }

  @Override
  public final boolean instructionTypeCanThrow() {
    return canThrow();
  }
}
