//========================================================================
//Copyright 2007-2010 David Yu dyuproject@gmail.com
//------------------------------------------------------------------------
//Licensed under the Apache License, Version 2.0 (the "License");
//you may not use this file except in compliance with the License.
//You may obtain a copy of the License at
//http://www.apache.org/licenses/LICENSE-2.0
//Unless required by applicable law or agreed to in writing, software
//distributed under the License is distributed on an "AS IS" BASIS,
//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//See the License for the specific language governing permissions and
//limitations under the License.
//========================================================================

package io.protostuff;

import static io.protostuff.WireFormat.TAG_TYPE_BITS;
import static io.protostuff.WireFormat.WIRETYPE_END_GROUP;
import static io.protostuff.WireFormat.WIRETYPE_FIXED32;
import static io.protostuff.WireFormat.WIRETYPE_FIXED64;
import static io.protostuff.WireFormat.WIRETYPE_LENGTH_DELIMITED;
import static io.protostuff.WireFormat.WIRETYPE_START_GROUP;
import static io.protostuff.WireFormat.WIRETYPE_VARINT;
import static io.protostuff.WireFormat.getTagFieldNumber;
import static io.protostuff.WireFormat.getTagWireType;
import static io.protostuff.WireFormat.makeTag;

import java.io.IOException;
import java.nio.ByteBuffer;

import com.fasterxml.jackson.databind.util.ArrayBuilders;

import io.protostuff.StringSerializer.STRING;

/**
 * Forked and modified from protostuff
 *
 * Reads and decodes protocol buffer message fields from an internal byte array buffer. This object is re-usable via
 * doing a reset on the byte array position and length. This is used internally by {@link IOUtil} where it catches
 * {@link ArrayIndexOutOfBoundsException} when a message is truncated.
 *
 * @author David Yu
 * @created Jun 22, 2010
 */
public final class ByteArrayInputEx implements InputEx {
  private final byte[] buffer;

  private int offset, limit, lastTag = 0;

  private int packedLimit = 0;

  private ArrayBuilders arrayBuilders;

  public ByteArrayInputEx(byte[] buffer) {
    this(buffer, 0, buffer.length);
  }

  public ByteArrayInputEx(byte[] buffer, int offset, int len) {
    this.buffer = buffer;
    this.offset = offset;
    this.limit = offset + len;
  }

  /**
   * Return true if currently reading packed field
   */
  public boolean isCurrentFieldPacked() {
    return packedLimit != 0 && packedLimit != offset;
  }

  /**
   * Attempt to read a field tag, returning zero if we have reached EOF. Protocol message parsers use this to read
   * tags, since a protocol message may legally end wherever a tag occurs, and zero is not a valid tag number.
   */
  public int readTag() throws IOException {
    if (offset == limit) {
      lastTag = 0;
      return 0;
    }

    final int tag = readRawVarint32();
    if (tag >>> TAG_TYPE_BITS == 0) {
      // If we actually read zero, that's not a valid tag.
      throw ProtobufException.invalidTag();
    }
    lastTag = tag;
    return tag;
  }

  /**
   * Verifies that the last call to readTag() returned the given tag value. This is used to verify that a nested group
   * ended with the correct end tag.
   *
   * @throws ProtobufException
   *             {@code value} does not match the last tag.
   */
  public void checkLastTagWas(final int value) throws ProtobufException {
    if (lastTag != value) {
      throw ProtobufException.invalidEndTag();
    }
  }

  /**
   * Reads and discards a single field, given its tag value.
   *
   * @return {@code false} if the tag is an endgroup tag, in which case nothing is skipped. Otherwise, returns
   *         {@code true}.
   */
  public boolean skipField(final int tag) throws IOException {
    switch (getTagWireType(tag)) {
      case WIRETYPE_VARINT:
        readInt32();
        return true;
      case WIRETYPE_FIXED64:
        readRawLittleEndian64();
        return true;
      case WIRETYPE_LENGTH_DELIMITED:
        final int size = readRawVarint32();
        if (size < 0) {
          throw ProtobufException.negativeSize();
        }
        offset += size;
        return true;
      case WIRETYPE_START_GROUP:
        skipMessage();
        checkLastTagWas(makeTag(getTagFieldNumber(tag), WIRETYPE_END_GROUP));
        return true;
      case WIRETYPE_END_GROUP:
        return false;
      case WIRETYPE_FIXED32:
        readRawLittleEndian32();
        return true;
      default:
        throw ProtobufException.invalidWireType();
    }
  }

  /**
   * Reads and discards an entire message. This will read either until EOF or until an endgroup tag, whichever comes
   * first.
   */
  public void skipMessage() throws IOException {
    while (true) {
      final int tag = readTag();
      if (tag == 0 || !skipField(tag)) {
        return;
      }
    }
  }

  @Override
  public void handleUnknownField(int fieldNumber) throws IOException {
    skipField(lastTag);
  }

  @Override
  public int readFieldNumber() throws IOException {
    if (offset == limit) {
      lastTag = 0;
      return 0;
    }

    // are we reading packed field?
    if (isCurrentFieldPacked()) {
      if (packedLimit < offset) {
        throw ProtobufException.misreportedSize();
      }

      // Return field number while reading packed field
      return lastTag >>> TAG_TYPE_BITS;
    }

    packedLimit = 0;
    final int tag = readRawVarint32();
    final int fieldNumber = tag >>> TAG_TYPE_BITS;
    if (fieldNumber == 0) {
      // If we actually read zero, that's not a valid tag.
      throw ProtobufException.invalidTag();
    }

    lastTag = tag;
    return fieldNumber;
  }

  /**
   * Check if this field have been packed into a length-delimited field. If so, update internal state to reflect that
   * packed fields are being read.
   *
   */
  private void checkIfPackedField() throws IOException {
    // Do we have the start of a packed field?
    if (packedLimit == 0 && getTagWireType(lastTag) == WIRETYPE_LENGTH_DELIMITED) {
      final int length = readRawVarint32();
      if (length < 0) {
        throw ProtobufException.negativeSize();
      }

      if (offset + length > limit) {
        throw ProtobufException.misreportedSize();
      }

      this.packedLimit = this.offset + length;
    }
  }

  /**
   * Read a {@code double} field value from the internal buffer.
   */
  @Override
  public double readDouble() {
    return Double.longBitsToDouble(readRawLittleEndian64());
  }

  /**
   * Read a {@code float} field value from the internal buffer.
   */
  @Override
  public float readFloat() {
    return Float.intBitsToFloat(readRawLittleEndian32());
  }

  /**
   * Read a {@code uint64} field value from the internal buffer.
   */
  @Override
  public long readUInt64() throws IOException {
    return readRawVarint64();
  }

  /**
   * Read an {@code int64} field value from the internal buffer.
   */
  @Override
  public long readInt64() throws IOException {
    return readRawVarint64();
  }

  /**
   * Read an {@code int32} field value from the internal buffer.
   */
  @Override
  public int readInt32() throws IOException {
    return readRawVarint32();
  }

  /**
   * Read a {@code fixed64} field value from the internal buffer.
   */
  @Override
  public long readFixed64() {
    return readRawLittleEndian64();
  }

  /**
   * Read a {@code fixed32} field value from the internal buffer.
   */
  @Override
  public int readFixed32() {
    return readRawLittleEndian32();
  }

  /**
   * Read a {@code bool} field value from the internal buffer.
   */
  @Override
  public boolean readBool() {
    return buffer[offset++] != 0;
  }

  /**
   * Read a {@code uint32} field value from the internal buffer.
   */
  @Override
  public int readUInt32() throws IOException {
    return readRawVarint32();
  }

  /**
   * Read an enum field value from the internal buffer. Caller is responsible for converting the numeric value to an
   * actual enum.
   */
  @Override
  public int readEnum() throws IOException {
    return readRawVarint32();
  }

  /**
   * Read an {@code sfixed32} field value from the internal buffer.
   */
  @Override
  public int readSFixed32() {
    return readRawLittleEndian32();
  }

  /**
   * Read an {@code sfixed64} field value from the internal buffer.
   */
  @Override
  public long readSFixed64() {
    return readRawLittleEndian64();
  }

  /**
   * Read an {@code sint32} field value from the internal buffer.
   */
  @Override
  public int readSInt32() throws IOException {
    final int n = readRawVarint32();
    return (n >>> 1) ^ -(n & 1);
  }

  /**
   * Read an {@code sint64} field value from the internal buffer.
   */
  @Override
  public long readSInt64() throws IOException {
    final long n = readRawVarint64();
    return (n >>> 1) ^ -(n & 1);
  }

  @Override
  public String readString() throws IOException {
    final int length = readRawVarint32();
    if (length < 0) {
      throw ProtobufException.negativeSize();
    }

    if (offset + length > limit) {
      throw ProtobufException.misreportedSize();
    }

    final int offset = this.offset;

    this.offset += length;

    return STRING.deser(buffer, offset, length);
  }

  @Override
  public ByteString readBytes() throws IOException {
    return ByteString.wrap(readByteArray());
  }

  @Override
  public byte[] readByteArray() throws IOException {
    final int length = readRawVarint32();
    if (length < 0) {
      throw ProtobufException.negativeSize();
    }

    if (offset + length > limit) {
      throw ProtobufException.misreportedSize();
    }

    final byte[] copy = new byte[length];
    System.arraycopy(buffer, offset, copy, 0, length);

    offset += length;

    return copy;
  }

  @Override
  public <T> T mergeObject(T value, final SchemaReader<T> schema) throws IOException {
    final int length = readRawVarint32();
    if (length < 0) {
      throw ProtobufException.negativeSize();
    }

    // save old limit
    final int oldLimit = this.limit;

    this.limit = offset + length;

    if (value == null) {
      value = schema.newMessage();
    }
    schema.mergeFrom(this, value);
    checkLastTagWas(0);

    // restore old limit
    this.limit = oldLimit;

    return value;
  }

  /**
   * Reads a var int 32 from the internal byte buffer.
   */
  public int readRawVarint32() throws IOException {
    byte tmp = buffer[offset++];
    if (tmp >= 0) {
      return tmp;
    }
    int result = tmp & 0x7f;
    if ((tmp = buffer[offset++]) >= 0) {
      result |= tmp << 7;
    } else {
      result |= (tmp & 0x7f) << 7;
      if ((tmp = buffer[offset++]) >= 0) {
        result |= tmp << 14;
      } else {
        result |= (tmp & 0x7f) << 14;
        if ((tmp = buffer[offset++]) >= 0) {
          result |= tmp << 21;
        } else {
          result |= (tmp & 0x7f) << 21;
          result |= (tmp = buffer[offset++]) << 28;
          if (tmp < 0) {
            // Discard upper 32 bits.
            for (int i = 0; i < 5; i++) {
              if (buffer[offset++] >= 0) {
                return result;
              }
            }
            throw ProtobufException.malformedVarint();
          }
        }
      }
    }
    return result;
  }

  /**
   * Reads a var int 64 from the internal byte buffer.
   */
  public long readRawVarint64() throws IOException {
    final byte[] buffer = this.buffer;
    int offset = this.offset;

    int shift = 0;
    long result = 0;
    while (shift < 64) {
      final byte b = buffer[offset++];
      result |= (long) (b & 0x7F) << shift;
      if ((b & 0x80) == 0) {
        this.offset = offset;
        return result;
      }
      shift += 7;
    }
    throw ProtobufException.malformedVarint();
  }

  /**
   * Read a 32-bit little-endian integer from the internal buffer.
   */
  public int readRawLittleEndian32() {
    final byte[] buffer = this.buffer;
    int offset = this.offset;

    final byte b1 = buffer[offset++];
    final byte b2 = buffer[offset++];
    final byte b3 = buffer[offset++];
    final byte b4 = buffer[offset++];

    this.offset = offset;

    return (((int) b1 & 0xff)) |
        (((int) b2 & 0xff) << 8) |
        (((int) b3 & 0xff) << 16) |
        (((int) b4 & 0xff) << 24);
  }

  /**
   * Read a 64-bit little-endian integer from the internal byte buffer.
   */
  public long readRawLittleEndian64() {
    final byte[] buffer = this.buffer;
    int offset = this.offset;

    final byte b1 = buffer[offset++];
    final byte b2 = buffer[offset++];
    final byte b3 = buffer[offset++];
    final byte b4 = buffer[offset++];
    final byte b5 = buffer[offset++];
    final byte b6 = buffer[offset++];
    final byte b7 = buffer[offset++];
    final byte b8 = buffer[offset++];

    this.offset = offset;

    return (((long) b1 & 0xff)) |
        (((long) b2 & 0xff) << 8) |
        (((long) b3 & 0xff) << 16) |
        (((long) b4 & 0xff) << 24) |
        (((long) b5 & 0xff) << 32) |
        (((long) b6 & 0xff) << 40) |
        (((long) b7 & 0xff) << 48) |
        (((long) b8 & 0xff) << 56);
  }

  /**
   * Reads a byte array/ByteBuffer value.
   */
  @Override
  public ByteBuffer readByteBuffer() throws IOException {
    return ByteBuffer.wrap(readByteArray());
  }

  @Override
  public ArrayBuilders getArrayBuilders() {
    if (arrayBuilders == null) {
      arrayBuilders = new ArrayBuilders();
    }
    return arrayBuilders;
  }

  @Override
  public int readPackedInt32() throws IOException {
    checkIfPackedField();
    return readRawVarint32();
  }

  @Override
  public int readPackedUInt32() throws IOException {
    checkIfPackedField();
    return readRawVarint32();
  }

  @Override
  public int readPackedSInt32() throws IOException {
    checkIfPackedField();
    final int n = readRawVarint32();
    return (n >>> 1) ^ -(n & 1);
  }

  @Override
  public int readPackedFixed32() throws IOException {
    checkIfPackedField();
    return readRawLittleEndian32();
  }

  @Override
  public int readPackedSFixed32() throws IOException {
    checkIfPackedField();
    return readRawLittleEndian32();
  }

  @Override
  public long readPackedInt64() throws IOException {
    checkIfPackedField();
    return readRawVarint64();
  }

  @Override
  public long readPackedUInt64() throws IOException {
    checkIfPackedField();
    return readRawVarint64();
  }

  @Override
  public long readPackedSInt64() throws IOException {
    checkIfPackedField();
    final long n = readRawVarint64();
    return (n >>> 1) ^ -(n & 1);
  }

  @Override
  public long readPackedFixed64() throws IOException {
    checkIfPackedField();
    return readRawLittleEndian64();
  }

  @Override
  public long readPackedSFixed64() throws IOException {
    checkIfPackedField();
    return readRawLittleEndian64();
  }

  @Override
  public float readPackedFloat() throws IOException {
    checkIfPackedField();
    return Float.intBitsToFloat(readRawLittleEndian32());
  }

  @Override
  public double readPackedDouble() throws IOException {
    checkIfPackedField();
    return Double.longBitsToDouble(readRawLittleEndian64());
  }

  @Override
  public boolean readPackedBool() throws IOException {
    checkIfPackedField();
    return buffer[offset++] != 0;
  }

  @Override
  public int readPackedEnum() throws IOException {
    checkIfPackedField();
    return readRawVarint32();
  }
}
