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

import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.ObjectToOffsetMapping;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
import com.android.tools.r8.naming.ClassNameMapper;
import com.android.tools.r8.utils.ComparatorUtils;
import com.android.tools.r8.utils.StringUtils;
import java.nio.ShortBuffer;
import java.util.Arrays;
import java.util.Comparator;

public class SparseSwitchPayload extends SwitchPayload {

  public final int size;
  public final int[] keys;
  public final /* offset */ int[] targets;

  public SparseSwitchPayload(int high, BytecodeStream stream) {
    super(high, stream);
    size = read16BitValue(stream);
    keys = new int[size];
    for (int i = 0; i < size; i++) {
      keys[i] = readSigned32BitValue(stream);
    }

    targets = new int[size];
    for (int i = 0; i < size; i++) {
      targets[i] = readSigned32BitValue(stream);
    }
  }

  public SparseSwitchPayload(int[] keys, int[] targets) {
    assert targets.length > 0;  // Empty switches should be eliminated.
    this.size = targets.length;
    this.keys = keys;
    this.targets = targets;
  }

  @Override
  public boolean isPayload() {
    return true;
  }

  @Override
  public void write(
      ShortBuffer dest,
      ProgramMethod context,
      GraphLens graphLens,
      ObjectToOffsetMapping mapping,
      LensCodeRewriterUtils rewriter) {
    writeFirst(2, dest);  // Pseudo-opcode = 0x0200
    write16BitValue(size, dest);
    for (int i = 0; i < size; i++) {
      write32BitValue(keys[i], dest);
    }
    for (int i = 0; i < size; i++) {
      write32BitValue(targets[i], dest);
    }
  }

  @Override
  final int internalCompareTo(Instruction other) {
    return Comparator.comparingInt((SparseSwitchPayload i) -> i.size)
        .thenComparing(i -> i.keys, ComparatorUtils::compareIntArray)
        .thenComparing(i -> i.targets, ComparatorUtils::compareIntArray)
        .compare(this, (SparseSwitchPayload) other);
  }

  @Override
  public int hashCode() {
    int result = super.hashCode();
    result = 31 * result + size;
    result = 31 * result + Arrays.hashCode(keys);
    result = 31 * result + Arrays.hashCode(targets);
    return result;
  }

  @Override
  public int getSize() {
    return 2 + (2 * keys.length) + (2 * targets.length);
  }

  @Override
  public int numberOfKeys() {
    return size;
  }

  @Override
  public int[] keys() {
    return keys;
  }

  @Override
  public int[] switchTargetOffsets() {
    return targets;
  }

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

  @Override
  public String toString(ClassNameMapper naming, Instruction payloadUser) {
    StringBuilder builder = new StringBuilder("[SparseSwitchPayload");
    if (payloadUser == null) {
      builder.append(" offsets relative to associated SparseSwitch");
    }
    builder.append("]\n");
    for (int i = 0; i < size; i++) {
      String offsetString;
      if (payloadUser != null) {
        // Don't show the decimal offset, as these are relative to the associated switch.
        offsetString = StringUtils.hexString(targets[i] + payloadUser.getOffset(), 2);
      } else {
        offsetString = targets[i] >= 0 ? ("+" + targets[i]) : Integer.toString(targets[i]);
      }
      StringUtils.appendLeftPadded(builder, keys[i] + " -> " + offsetString + "\n", 20);
    }
    return super.toString(naming) + builder.toString();
  }

  @Override
  public String toSmaliString(Instruction payloadUser) {
    StringBuilder builder = new StringBuilder();
    builder.append("    ");
    builder.append(".sparse-switch");
    builder.append("\n");
    for (int i = 0; i < keys.length; i++) {
      builder.append("      ");
      builder.append(StringUtils.hexString(keys[i], 8));
      builder.append(" -> :label_");
      builder.append(payloadUser.getOffset() + targets[i]);
      builder.append("  # ");
      builder.append(keys[i]);
      builder.append("\n");
    }
    builder.append("    ");
    builder.append(".end sparse-switch");
    return builder.toString();
  }
}
