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

import com.android.tools.r8.ByteBufferProvider;
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.graph.DexWritableCode;
import com.android.tools.r8.graph.ObjectToOffsetMapping;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.utils.EncodedValueUtils;
import com.android.tools.r8.utils.LebUtils;
import com.google.common.annotations.VisibleForTesting;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.ShortBuffer;

/**
 * Provides an abstraction around a {@link ByteBuffer} with write operations for
 * additional DEX specific formats, like Leb128.
 */
public class DexOutputBuffer {
  private static final int DEFAULT_BUFFER_SIZE = 256 * 1024;

  private final ByteBufferProvider byteBufferProvider;
  private CompatByteBuffer byteBuffer;

  @VisibleForTesting
  DexOutputBuffer() {
    this(new ByteBufferProvider() {});
  }

  public DexOutputBuffer(ByteBufferProvider byteBufferProvider) {
    this.byteBufferProvider = byteBufferProvider;
    byteBuffer = allocateByteBuffer(DEFAULT_BUFFER_SIZE);
  }

  private void ensureSpaceFor(int bytes) {
    if (byteBuffer.remaining() < bytes) {
      int newSize = byteBuffer.capacity() + Math.max(byteBuffer.capacity(), bytes * 2);
      CompatByteBuffer newBuffer = allocateByteBuffer(newSize);
      System.arraycopy(byteBuffer.array(), 0, newBuffer.array(), 0, byteBuffer.capacity());
      newBuffer.position(byteBuffer.position());
      freeByteBuffer(byteBuffer);
      byteBuffer = newBuffer;
    }
  }

  private CompatByteBuffer allocateByteBuffer(int size) {
    CompatByteBuffer buffer = new CompatByteBuffer(byteBufferProvider.acquireByteBuffer(size));
    if (!buffer.hasArray()) {
      throw new CompilationError(
          "Provided byte-buffer is required to have an array backing, but does not.");
    }
    if (buffer.capacity() < size) {
      throw new CompilationError(
          "Insufficient capacity of provided byte-buffer."
              + " Requested capacity "
              + size
              + ", actual capacity: "
              + buffer.capacity());
    }
    if (buffer.position() != 0) {
      throw new CompilationError(
          "Provided byte-buffer is required to start at position zero, but starts at "
              + buffer.position()
              + ".");
    }
    buffer.order(ByteOrder.LITTLE_ENDIAN);
    return buffer;
  }

  private void freeByteBuffer(CompatByteBuffer buffer) {
    assert buffer != null;
    byteBufferProvider.releaseByteBuffer(buffer.asByteBuffer());
  }

  public void putUleb128(int value) {
    LebUtils.putUleb128(this, value);
  }

  public void putSleb128(int value) {
    LebUtils.putSleb128(this, value);
  }

  public int putSignedEncodedValue(long value, int expectedSize) {
    return EncodedValueUtils.putSigned(this, value, expectedSize);
  }

  public int putUnsignedEncodedValue(long value, int expectedSize) {
    return EncodedValueUtils.putUnsigned(this, value, expectedSize);
  }

  public void putInstructions(
      DexWritableCode code,
      ProgramMethod context,
      ObjectToOffsetMapping mapping,
      CodeToKeep desugaredLibraryCodeToKeep) {
    int size = code.codeSizeInBytes();
    ensureSpaceFor(size * Short.BYTES);
    assert byteBuffer.position() % 2 == 0;
    ShortBuffer shortBuffer = byteBuffer.asShortBuffer();
    code.writeDex(
        shortBuffer, context, mapping.getGraphLens(), mapping.getLensCodeRewriter(), mapping);
    code.writeKeepRulesForDesugaredLibrary(desugaredLibraryCodeToKeep);
    byteBuffer.position(byteBuffer.position() + shortBuffer.position() * Short.BYTES);
  }

  public void putByte(byte aByte) {
    ensureSpaceFor(Byte.BYTES);
    byteBuffer.put(aByte);
  }

  public void putBytes(byte[] bytes) {
    ensureSpaceFor(bytes.length);
    byteBuffer.put(bytes);
  }

  public void putShort(short aShort) {
    ensureSpaceFor(Short.BYTES);
    byteBuffer.putShort(aShort);
  }

  public void putInt(int anInteger) {
    ensureSpaceFor(Integer.BYTES);
    byteBuffer.putInt(anInteger);
  }

  public short getShort() {
    return byteBuffer.getShort();
  }

  public int getInt() {
    return byteBuffer.getInt();
  }

  public boolean assertZero() {
    int pos = byteBuffer.position();
    int i = byteBuffer.getInt();
    assert i == 0;
    byteBuffer.position(pos);
    return true;
  }

  /**
   * Moves the position in the bytebuffer forward until it is aligned.
   *
   * @param bytes  alignment requirement in bytes
   * @return       the new position after alignment
   */
  public int align(int bytes) {
    assert bytes > 0;
    int mask = bytes - 1;
    int newPosition = (position() + mask) & ~mask;
    ensureSpaceFor(newPosition - position());
    byteBuffer.position(newPosition);
    return newPosition;
  }

  public int position() {
    return byteBuffer.position();
  }

  public void forward(int bytes) {
    ensureSpaceFor(bytes);
    byteBuffer.position(byteBuffer.position() + bytes);
  }

  public void rewind(int bytes) {
    forward(-bytes);
  }

  public void moveTo(int position) {
    ensureSpaceFor(position - byteBuffer.position());
    byteBuffer.position(position);
  }

  public boolean isAligned(int bytes) {
    return position() % bytes == 0;
  }

  public byte[] asArray() {
    return byteBuffer.array();
  }

  public CompatByteBuffer stealByteBuffer() {
    CompatByteBuffer buffer = byteBuffer;
    byteBuffer = null;
    return buffer;
  }
}
