// 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.DexOutputBuffer;
import com.android.tools.r8.dex.FileWriter;
import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.dex.MixedSectionCollection;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.ir.code.ConstNumber;
import com.android.tools.r8.ir.code.ConstType;
import com.android.tools.r8.ir.code.Instruction;
import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.utils.EncodedValueUtils;
import java.util.Arrays;

public abstract class DexValue extends DexItem {

  public static final byte VALUE_BYTE = 0x00;
  public static final byte VALUE_SHORT = 0x02;
  public static final byte VALUE_CHAR = 0x03;
  public static final byte VALUE_INT = 0x04;
  public static final byte VALUE_LONG = 0x06;
  public static final byte VALUE_FLOAT = 0x10;
  public static final byte VALUE_DOUBLE = 0x11;
  public static final byte VALUE_METHOD_TYPE = 0x15;
  public static final byte VALUE_METHOD_HANDLE = 0x16;
  public static final byte VALUE_STRING = 0x17;
  public static final byte VALUE_TYPE = 0x18;
  public static final byte VALUE_FIELD = 0x19;
  public static final byte VALUE_METHOD = 0x1a;
  public static final byte VALUE_ENUM = 0x1b;
  public static final byte VALUE_ARRAY = 0x1c;
  public static final byte VALUE_ANNOTATION = 0x1d;
  public static final byte VALUE_NULL = 0x1e;
  public static final byte VALUE_BOOLEAN = 0x1f;

  private static void writeHeader(byte type, int arg, DexOutputBuffer dest) {
    dest.putByte((byte) ((arg << 5) | type));
  }

  @Override
  void collectMixedSectionItems(MixedSectionCollection mixedItems) {
    // Should never be visited.
    assert false;
  }

  public abstract void sort();

  public abstract void writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping);

  @Override
  public abstract int hashCode();

  @Override
  public abstract boolean equals(Object other);

  @Override
  public abstract String toString();

  public static DexValue defaultForType(DexType type, DexItemFactory factory) {
    if (type == factory.booleanType) {
      return DexValueBoolean.DEFAULT;
    }
    if (type == factory.byteType) {
      return DexValueByte.DEFAULT;
    }
    if (type == factory.charType) {
      return DexValueChar.DEFAULT;
    }
    if (type == factory.shortType) {
      return DexValueShort.DEFAULT;
    }
    if (type == factory.intType) {
      return DexValueInt.DEFAULT;
    }
    if (type == factory.longType) {
      return DexValueLong.DEFAULT;
    }
    if (type == factory.floatType) {
      return DexValueFloat.DEFAULT;
    }
    if (type == factory.doubleType) {
      return DexValueDouble.DEFAULT;
    }
    if (type.isArrayType() || type.isClassType()) {
      return DexValueNull.NULL;
    }
    throw new Unreachable("No default value for unexpected type " + type);
  }

  // Returns a const instruction for the non default value.
  public Instruction asConstInstruction(boolean hasClassInitializer, Value dest) {
    return null;
  }

  public boolean isDefault(DexType type, DexItemFactory factory) {
    return this == defaultForType(type, factory);
  }

  /**
   * Whether creating this value as a default value for a field might trigger an allocation.
   * <p>
   * This is conservative.
   */
  public boolean mayTriggerAllocation() {
    return true;
  }

  static private abstract class SimpleDexValue extends DexValue {

    @Override
    public void collectIndexedItems(IndexedItemCollection indexedItems) {
      // Intentionally left empty
    }

    @Override
    public void sort() {
      // Intentionally empty
    }

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

    protected static void writeIntegerTo(byte type, long value, int expected,
        DexOutputBuffer dest) {
      // Leave space for header.
      dest.forward(1);
      int length = dest.putSignedEncodedValue(value, expected);
      dest.rewind(length + 1);
      writeHeader(type, length - 1, dest);
      dest.forward(length);
    }

  }

  static public class DexValueByte extends SimpleDexValue {

    public static final DexValueByte DEFAULT = new DexValueByte((byte) 0);

    final byte value;

    private DexValueByte(byte value) {
      this.value = value;
    }

    public static DexValueByte create(byte value) {
      return value == DEFAULT.value ? DEFAULT : new DexValueByte(value);
    }

    public byte getValue() {
      return value;
    }

    @Override
    public void writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping) {
      writeHeader(VALUE_BYTE, 0, dest);
      dest.putSignedEncodedValue(value, 1);
    }

    @Override
    public int hashCode() {
      return value * 3;
    }

    @Override
    public boolean equals(Object other) {
      if (other == this) {
        return true;
      }
      return other instanceof DexValueByte && value == ((DexValueByte) other).value;
    }

    @Override
    public String toString() {
      return "Byte " + value;
    }

    @Override
    public Instruction asConstInstruction(boolean hasClassInitializer, Value dest) {
      return (this == DEFAULT && hasClassInitializer)
          ? null
          : new ConstNumber(ConstType.INT, dest, value);
    }
  }

  static public class DexValueShort extends SimpleDexValue {

    public static final DexValueShort DEFAULT = new DexValueShort((short) 0);
    final short value;

    private DexValueShort(short value) {
      this.value = value;
    }

    public static DexValueShort create(short value) {
      return value == DEFAULT.value ? DEFAULT : new DexValueShort(value);
    }

    public short getValue() {
      return value;
    }

    @Override
    public void writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping) {
      writeIntegerTo(VALUE_SHORT, value, Short.BYTES, dest);
    }

    @Override
    public int hashCode() {
      return value * 7;
    }

    @Override
    public boolean equals(Object other) {
      if (other == this) {
        return true;
      }
      return other instanceof DexValueShort && value == ((DexValueShort) other).value;
    }

    @Override
    public String toString() {
      return "Short " + value;
    }

    @Override
    public Instruction asConstInstruction(boolean hasClassInitializer, Value dest) {
      return (this == DEFAULT && hasClassInitializer)
          ? null
          : new ConstNumber(ConstType.INT, dest, value);
    }
  }

  static public class DexValueChar extends SimpleDexValue {

    public static final DexValueChar DEFAULT = new DexValueChar((char) 0);
    final char value;

    private DexValueChar(char value) {
      this.value = value;
    }

    public static DexValueChar create(char value) {
      return value == DEFAULT.value ? DEFAULT : new DexValueChar(value);
    }

    public char getValue() {
      return value;
    }

    @Override
    public void writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping) {
      dest.forward(1);
      int length = dest.putUnsignedEncodedValue(value, 2);
      dest.rewind(length + 1);
      writeHeader(VALUE_CHAR, length - 1, dest);
      dest.forward(length);
    }

    @Override
    public int hashCode() {
      return value * 5;
    }

    @Override
    public boolean equals(Object other) {
      if (other == this) {
        return true;
      }
      return other instanceof DexValueChar && value == ((DexValueChar) other).value;
    }

    @Override
    public String toString() {
      return "Char " + value;
    }

    @Override
    public Instruction asConstInstruction(boolean hasClassInitializer, Value dest) {
      return (this == DEFAULT && hasClassInitializer)
          ? null
          : new ConstNumber(ConstType.INT, dest, value);
    }
  }

  static public class DexValueInt extends SimpleDexValue {

    public static final DexValueInt DEFAULT = new DexValueInt(0);
    public final int value;

    private DexValueInt(int value) {
      this.value = value;
    }

    public static DexValueInt create(int value) {
      return value == DEFAULT.value ? DEFAULT : new DexValueInt(value);
    }

    public int getValue() {
      return value;
    }

    @Override
    public void writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping) {
      writeIntegerTo(VALUE_INT, value, Integer.BYTES, dest);
    }

    @Override
    public int hashCode() {
      return value * 11;
    }

    @Override
    public boolean equals(Object other) {
      if (other == this) {
        return true;
      }
      return other instanceof DexValueInt && value == ((DexValueInt) other).value;
    }

    @Override
    public String toString() {
      return "Int " + value;
    }

    @Override
    public Instruction asConstInstruction(boolean hasClassInitializer, Value dest) {
      return (this == DEFAULT && hasClassInitializer)
          ? null
          : new ConstNumber(ConstType.INT, dest, value);
    }
  }

  static public class DexValueLong extends SimpleDexValue {

    public static final DexValueLong DEFAULT = new DexValueLong(0);
    final long value;

    private DexValueLong(long value) {
      this.value = value;
    }

    public static DexValueLong create(long value) {
      return value == DEFAULT.value ? DEFAULT : new DexValueLong(value);
    }

    public long getValue() {
      return value;
    }

    @Override
    public void writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping) {
      writeIntegerTo(VALUE_LONG, value, Long.BYTES, dest);
    }

    @Override
    public int hashCode() {
      return (int) value * 13;
    }

    @Override
    public boolean equals(Object other) {
      if (other == this) {
        return true;
      }
      return other instanceof DexValueLong && value == ((DexValueLong) other).value;
    }

    @Override
    public String toString() {
      return "Long " + value;
    }

    @Override
    public Instruction asConstInstruction(boolean hasClassInitializer, Value dest) {
      return (this == DEFAULT && hasClassInitializer)
          ? null
          : new ConstNumber(ConstType.LONG, dest, value);
    }
  }

  static public class DexValueFloat extends SimpleDexValue {

    public static final DexValueFloat DEFAULT = new DexValueFloat(0);
    final float value;

    private DexValueFloat(float value) {
      this.value = value;
    }

    public static DexValueFloat create(float value) {
      return Float.compare(value, DEFAULT.value) == 0 ? DEFAULT : new DexValueFloat(value);
    }

    public float getValue() {
      return value;
    }

    @Override
    public void writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping) {
      dest.forward(1);
      int length = EncodedValueUtils.putFloat(dest, value);
      dest.rewind(length + 1);
      writeHeader(VALUE_FLOAT, length - 1, dest);
      dest.forward(length);
    }

    @Override
    public int hashCode() {
      return (int) value * 19;
    }

    @Override
    public boolean equals(Object other) {
      if (other == this) {
        return true;
      }
      return (other instanceof DexValueFloat) &&
          (Float.compare(value, ((DexValueFloat) other).value) == 0);
    }

    @Override
    public String toString() {
      return "Float " + value;
    }

  }

  static public class DexValueDouble extends SimpleDexValue {

    public static final DexValueDouble DEFAULT = new DexValueDouble(0);

    final double value;

    private DexValueDouble(double value) {
      this.value = value;
    }

    public static DexValueDouble create(double value) {
      return Double.compare(value, DEFAULT.value) == 0 ? DEFAULT : new DexValueDouble(value);
    }

    public double getValue() {
      return value;
    }

    @Override
    public void writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping) {
      dest.forward(1);
      int length = EncodedValueUtils.putDouble(dest, value);
      dest.rewind(length + 1);
      writeHeader(VALUE_DOUBLE, length - 1, dest);
      dest.forward(length);
    }

    @Override
    public int hashCode() {
      return (int) value * 29;
    }

    @Override
    public boolean equals(Object other) {
      if (other == this) {
        return true;
      }
      return (other instanceof DexValueDouble) &&
          (Double.compare(value, ((DexValueDouble) other).value) == 0);
    }

    @Override
    public String toString() {
      return "Double " + value;
    }
  }

  static private abstract class NestedDexValue<T extends IndexedDexItem> extends DexValue {

    public final T value;

    private NestedDexValue(T value) {
      this.value = value;
    }

    protected abstract byte getValueKind();

    @Override
    public void writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping) {
      int offset = value.getOffset(mapping);
      dest.forward(1);
      int length = dest.putUnsignedEncodedValue(offset, 4);
      dest.rewind(length + 1);
      writeHeader(getValueKind(), length - 1, dest);
      dest.forward(length);
    }

    @Override
    public void collectIndexedItems(IndexedItemCollection indexedItems) {
      value.collectIndexedItems(indexedItems);
    }

    @Override
    public void sort() {
      // Intentionally empty.
    }

    @Override
    public int hashCode() {
      return value.hashCode() * 7 + getValueKind();
    }

    @Override
    public boolean equals(Object other) {
      if (other == this) {
        return true;
      }
      if (other instanceof NestedDexValue) {
        NestedDexValue<?> that = (NestedDexValue<?>) other;
        return that.getValueKind() == getValueKind() && that.value.equals(value);
      }
      return false;
    }

    @Override
    public String toString() {
      return "Item " + getValueKind() + " " + value;
    }
  }

  static public class DexValueString extends NestedDexValue<DexString> {

    public DexValueString(DexString value) {
      super(value);
    }

    public DexString getValue() {
      return value;
    }

    @Override
    protected byte getValueKind() {
      return VALUE_STRING;
    }
  }

  static public class DexValueType extends NestedDexValue<DexType> {

    public DexValueType(DexType value) {
      super(value);
    }

    @Override
    protected byte getValueKind() {
      return VALUE_TYPE;
    }

    @Override
    public void collectIndexedItems(IndexedItemCollection indexedItems) {
      value.collectIndexedItems(indexedItems);
    }
  }

  static public class DexValueField extends NestedDexValue<DexField> {

    public DexValueField(DexField value) {
      super(value);
    }

    @Override
    protected byte getValueKind() {
      return VALUE_FIELD;
    }

    @Override
    public void collectIndexedItems(IndexedItemCollection indexedItems) {
      value.collectIndexedItems(indexedItems);
    }
  }

  static public class DexValueMethod extends NestedDexValue<DexMethod> {

    public DexValueMethod(DexMethod value) {
      super(value);
    }

    @Override
    protected byte getValueKind() {
      return VALUE_METHOD;
    }

    @Override
    public void collectIndexedItems(IndexedItemCollection indexedItems) {
      value.collectIndexedItems(indexedItems);
    }
  }

  static public class DexValueEnum extends NestedDexValue<DexField> {

    public DexValueEnum(DexField value) {
      super(value);
    }

    @Override
    protected byte getValueKind() {
      return VALUE_ENUM;
    }

    @Override
    public void collectIndexedItems(IndexedItemCollection indexedItems) {
      value.collectIndexedItems(indexedItems);
    }
  }

  static public class DexValueMethodType extends NestedDexValue<DexProto> {

    public DexValueMethodType(DexProto value) {
      super(value);
    }

    @Override
    protected byte getValueKind() {
      return VALUE_METHOD_TYPE;
    }

    @Override
    public void collectIndexedItems(IndexedItemCollection indexedItems) {
      value.collectIndexedItems(indexedItems);
    }
  }

  static public class DexValueArray extends DexValue {

    final DexValue[] values;

    public DexValueArray(DexValue[] values) {
      this.values = values;
    }

    public DexValue[] getValues() {
      return values;
    }

    @Override
    public void collectIndexedItems(IndexedItemCollection indexedItems) {
      collectAll(indexedItems, values);
    }

    @Override
    public void writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping) {
      writeHeader(VALUE_ARRAY, 0, dest);
      dest.putUleb128(values.length);
      for (DexValue value : values) {
        value.writeTo(dest, mapping);
      }
    }

    @Override
    public void sort() {
      for (DexValue value : values) {
        value.sort();
      }
    }

    @Override
    public int hashCode() {
      return Arrays.hashCode(values);
    }

    @Override
    public boolean equals(Object other) {
      if (other == this) {
        return true;
      }
      if (other instanceof DexValueArray) {
        DexValueArray that = (DexValueArray) other;
        return Arrays.equals(that.values, values);
      }
      return false;
    }

    @Override
    public String toString() {
      return "Array " + Arrays.toString(values);
    }
  }

  static public class DexValueAnnotation extends DexValue {

    public final DexEncodedAnnotation value;

    public DexValueAnnotation(DexEncodedAnnotation value) {
      this.value = value;
    }

    @Override
    public void collectIndexedItems(IndexedItemCollection indexedItems) {
      value.collectIndexedItems(indexedItems);
    }

    @Override
    public void writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping) {
      writeHeader(VALUE_ANNOTATION, 0, dest);
      FileWriter.writeEncodedAnnotation(value, dest, mapping);
    }

    @Override
    public void sort() {
      value.sort();
    }

    @Override
    public int hashCode() {
      return value.hashCode() * 7;
    }

    @Override
    public boolean equals(Object other) {
      if (other == this) {
        return true;
      }
      if (other instanceof DexValueAnnotation) {
        DexValueAnnotation that = (DexValueAnnotation) other;
        return that.value.equals(value);
      }
      return false;
    }

    @Override
    public String toString() {
      return "Annotation " + value;
    }
  }

  static public class DexValueNull extends SimpleDexValue {

    public static final DexValue NULL = new DexValueNull();

    // See DexValueNull.NULL
    private DexValueNull() {
    }

    public Object getValue() {
      return null;
    }

    @Override
    public void writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping) {
      writeHeader(VALUE_NULL, 0, dest);
    }

    @Override
    public int hashCode() {
      return 42;
    }

    @Override
    public boolean equals(Object other) {
      if (other == this) {
        return true;
      }
      return (other instanceof DexValueNull);
    }

    @Override
    public String toString() {
      return "Null";
    }
  }

  static public class DexValueBoolean extends SimpleDexValue {

    private static final DexValueBoolean TRUE = new DexValueBoolean(true);
    private static final DexValueBoolean FALSE = new DexValueBoolean(false);
    // Use a separate instance for the default value to distinguish it from an explicit false value.
    private static final DexValueBoolean DEFAULT = new DexValueBoolean(false);

    final boolean value;

    private DexValueBoolean(boolean value) {
      this.value = value;
    }

    public static DexValueBoolean create(boolean value) {
      return value ? TRUE : FALSE;
    }

    public boolean getValue() {
      return value;
    }

    @Override
    public void writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping) {
      writeHeader(VALUE_BOOLEAN, value ? 1 : 0, dest);
    }

    @Override
    public int hashCode() {
      return value ? 1234 : 4321;
    }

    @Override
    public boolean equals(Object other) {
      if (other == this) {
        return true;
      }
      return (other instanceof DexValueBoolean) && ((DexValueBoolean) other).value == value;
    }

    @Override
    public String toString() {
      return value ? "True" : "False";
    }

    @Override
    public Instruction asConstInstruction(boolean hasClassInitializer, Value dest) {
      return (this == DEFAULT && hasClassInitializer)
          ? null
          : new ConstNumber(ConstType.INT, dest, value ? 1 : 0);
    }
  }

  static public class DexValueMethodHandle extends NestedDexValue<DexMethodHandle> {

    public DexValueMethodHandle(DexMethodHandle value) {
      super(value);
    }

    @Override
    protected byte getValueKind() {
      return VALUE_METHOD_HANDLE;
    }

    @Override
    public void collectIndexedItems(IndexedItemCollection indexedItems) {
      value.collectIndexedItems(indexedItems);
    }
  }
}
