// 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 static com.android.tools.r8.dex.Constants.DEX_FILE_MAGIC_PREFIX;

import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.utils.LebUtils;
import com.google.common.io.ByteStreams;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class DexFile {

  final String name;
  private final ByteBuffer buffer;
  private final int version;

  DexFile(String name) throws IOException {
    this.name = name;
    Path path = Paths.get(name);
    buffer = ByteBuffer.wrap(Files.readAllBytes(path));
    version = parseMagic(buffer);
  }

  public DexFile(InputStream input) throws IOException {
    // TODO(zerny): Remove dependencies on file names.
    name = "input-stream.dex";
    buffer = ByteBuffer.wrap(ByteStreams.toByteArray(input));
    version = parseMagic(buffer);
  }

  /**
   * Returns a File that contains the bytes provided as argument. Used for testing.
   *
   * @param bytes contents of the file
   */
  DexFile(byte[] bytes) {
    this.name = "mockfile.dex";
    buffer = ByteBuffer.wrap(bytes);
    version = parseMagic(buffer);
  }

  // Parse the magic header and determine the dex file version.
  private int parseMagic(ByteBuffer buffer) {
    int index = 0;
    for (byte prefixByte : DEX_FILE_MAGIC_PREFIX) {
      if (buffer.get(index++) != prefixByte) {
        throw new CompilationError("Dex file has invalid header: " + name);
      }
    }
    if (buffer.get(index++) != '0' || buffer.get(index++) != '3') {
      throw new CompilationError("Dex file has invalid version number: " + name);
    }
    byte versionByte = buffer.get(index++);
    int version;
    switch (versionByte) {
      case '8':
        version = Constants.ANDROID_O_DEX_VERSION;
        break;
      case '7':
        version = Constants.ANDROID_N_DEX_VERSION;
        break;
      case '5':
        version = Constants.ANDROID_PRE_N_DEX_VERSION;
        break;
      default:
        throw new CompilationError("Dex file has invalid version number: " + name);
    }
    if (buffer.get(index++) != '\0') {
      throw new CompilationError("Dex file has invalid header: " + name);
    }
    return version;
  }

  int getDexVersion() {
    return version;
  }

  byte[] getByteArray(int size) {
    byte[] result = new byte[size];
    buffer.get(result);
    return result;
  }

  int getUleb128() {
    return LebUtils.parseUleb128(this);
  }

  int getSleb128() {
    return LebUtils.parseSleb128(this);
  }

  int getUleb128p1() {
    return getUleb128() - 1;
  }

  int getUint() {
    int result = buffer.getInt();
    assert result >= 0;  // Ensure the java int didn't overflow.
    return result;
  }

  int getUshort() {
    int result = buffer.getShort() & 0xffff;
    assert result >= 0;  // Ensure we have a non-negative number.
    return result;
  }

  short getShort() {
    return buffer.getShort();
  }

  int getUint(int offset) {
    int result = buffer.getInt(offset);
    assert result >= 0;  // Ensure the java int didn't overflow.
    return result;
  }

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

  void setByteOrder() {
    // Make sure we set the right endian for reading.
    buffer.order(ByteOrder.LITTLE_ENDIAN);
    int endian = buffer.getInt(Constants.ENDIAN_TAG_OFFSET);
    if (endian == Constants.REVERSE_ENDIAN_CONSTANT) {
      buffer.order(ByteOrder.BIG_ENDIAN);
    } else {
      assert endian == Constants.ENDIAN_CONSTANT;
    }
  }

  int position() {
    return buffer.position();
  }

  void position(int position) {
    buffer.position(position);
  }

  void align(int alignment) {
    assert (alignment & (alignment - 1)) == 0;   // Check alignment is power of 2.
    int p = buffer.position();
    p += (alignment - (p % alignment)) & (alignment - 1);
    buffer.position(p);
  }

  public byte get() {
    return buffer.get();
  }

  int getUbyte() {
    int result = buffer.get() & 0xff;
    assert result >= 0;  // Ensure we have a non-negative result.
    return result;
  }

  int end() {
    return buffer.capacity();
  }
}
