/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.trevni;

import java.io.EOFException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;

/** Used to read values. */
class InputBuffer {
  private Input in;

  private long inLength;
  private long offset;                            // pos of next read from in

  private byte[] buf;                             // data from input
  private int pos;                                // position within buffer
  private int limit;                              // end of valid buffer data

  private CharsetDecoder utf8 = Charset.forName("UTF-8").newDecoder();

  private int bitCount;                           // position in booleans

  private int runLength;                          // length of run
  private int runValue;                           // value of run

  public InputBuffer(Input in) throws IOException { this(in, 0); }

  public InputBuffer(Input in, long position) throws IOException {
    this.in = in;
    this.inLength = in.length();
    this.offset = position;

    if (in instanceof InputBytes) {               // use buffer directly
      this.buf = ((InputBytes)in).getBuffer();
      this.limit = (int)in.length();
      this.offset = limit;
      this.pos = (int)position;
    } else {                                      // create new buffer
      this.buf = new byte[8192];                  // big enough for primitives
    }
  }

  public void seek(long position) throws IOException {
    runLength = 0;
    if (position >= (offset-limit) && position <= offset) {
      pos = (int)(limit - (offset - position));   // seek in buffer;
      return;
    }
    pos = 0;
    limit = 0;
    offset = position;
  }

  public long tell() { return (offset-limit)+pos; }

  public long length() { return inLength; }

  public <T extends Comparable> T readValue(ValueType type) throws IOException {
    switch (type) {
    case NULL:
      return (T)null;
    case BOOLEAN:
      return (T)Boolean.valueOf(readBoolean());
    case INT:
      return (T)Integer.valueOf(readInt());
    case LONG:
      return (T)Long.valueOf(readLong());
    case FIXED32:
      return (T)Integer.valueOf(readFixed32());
    case FIXED64:
      return (T)Long.valueOf(readFixed64());
    case FLOAT:
      return (T)Float.valueOf(readFloat());
    case DOUBLE:
      return (T)Double.valueOf(readDouble());
    case STRING:
      return (T)readString();
    case BYTES:
      return (T)readBytes(null);
    default:
      throw new TrevniRuntimeException("Unknown value type: "+type);
    }
  }

  public void skipValue(ValueType type) throws IOException {
    switch (type) {
    case NULL:
                    break;
    case BOOLEAN:
      readBoolean(); break;
    case INT:
      readInt();    break;
    case LONG:
      readLong();   break;
    case FIXED32:
    case FLOAT:
      skip(4);      break;
    case FIXED64:
    case DOUBLE:
      skip(8);      break;
    case STRING:
    case BYTES:
      skipBytes();  break;
    default:
      throw new TrevniRuntimeException("Unknown value type: "+type);
    }
  }

  public boolean readBoolean() throws IOException {
    if (bitCount == 0)
      read();
    int bits = buf[pos-1] & 0xff;
    int bit = (bits >> bitCount) & 1;
    bitCount++;
    if (bitCount == 8)
      bitCount = 0;
    return bit == 0 ? false : true;
  }

  public int readLength() throws IOException {
    bitCount = 0;
    if (runLength > 0) {
      runLength--;                                // in run
      return runValue;
    }

    int length = readInt();
    if (length >= 0)                              // not a run
      return length;

    runLength = (1-length)>>>1;                   // start of run
    runValue = (length+1) & 1;
    return runValue;
  }

  public int readInt() throws IOException {
    if ((limit - pos) < 5) {                      // maybe not in buffer
      int b = read();
      int n = b & 0x7f;
      for (int shift = 7; b > 0x7f; shift += 7) {
        b = read();
        n ^= (b & 0x7f) << shift;
      }
      return (n >>> 1) ^ -(n & 1);                  // back to two's-complement
    }
    int len = 1;
    int b = buf[pos] & 0xff;
    int n = b & 0x7f;
    if (b > 0x7f) {
      b = buf[pos + len++] & 0xff;
      n ^= (b & 0x7f) << 7;
      if (b > 0x7f) {
        b = buf[pos + len++] & 0xff;
        n ^= (b & 0x7f) << 14;
        if (b > 0x7f) {
          b = buf[pos + len++] & 0xff;
          n ^= (b & 0x7f) << 21;
          if (b > 0x7f) {
            b = buf[pos + len++] & 0xff;
            n ^= (b & 0x7f) << 28;
            if (b > 0x7f) {
              throw new IOException("Invalid int encoding");
            }
          }
        }
      }
    }
    pos += len;
    if (pos > limit)
      throw new EOFException();
    return (n >>> 1) ^ -(n & 1);                  // back to two's-complement
  }

  public long readLong() throws IOException {
    if ((limit - pos) < 10) {                     // maybe not in buffer
      int b = read();
      long n = b & 0x7f;
      for (int shift = 7; b > 0x7f; shift += 7) {
        b = read();
        n ^= (b & 0x7fL) << shift;
      }
      return (n >>> 1) ^ -(n & 1);                // back to two's-complement
    }

    int b = buf[pos++] & 0xff;
    int n = b & 0x7f;
    long l;
    if (b > 0x7f) {
      b = buf[pos++] & 0xff;
      n ^= (b & 0x7f) << 7;
      if (b > 0x7f) {
        b = buf[pos++] & 0xff;
        n ^= (b & 0x7f) << 14;
        if (b > 0x7f) {
          b = buf[pos++] & 0xff;
          n ^= (b & 0x7f) << 21;
          if (b > 0x7f) {
            // only the low 28 bits can be set, so this won't carry
            // the sign bit to the long
            l = innerLongDecode((long)n);
          } else {
            l = n;
          }
        } else {
          l = n;
        }
      } else {
        l = n;
      }
    } else {
      l = n;
    }
    if (pos > limit) {
      throw new EOFException();
    }
    return (l >>> 1) ^ -(l & 1); // back to two's-complement
  }

  // splitting readLong up makes it faster because of the JVM does more
  // optimizations on small methods
  private long innerLongDecode(long l) throws IOException {
    int len = 1;
    int b = buf[pos] & 0xff;
    l ^= (b & 0x7fL) << 28;
    if (b > 0x7f) {
      b = buf[pos + len++] & 0xff;
      l ^= (b & 0x7fL) << 35;
      if (b > 0x7f) {
        b = buf[pos + len++] & 0xff;
        l ^= (b & 0x7fL) << 42;
        if (b > 0x7f) {
          b = buf[pos + len++] & 0xff;
          l ^= (b & 0x7fL) << 49;
          if (b > 0x7f) {
            b = buf[pos + len++] & 0xff;
            l ^= (b & 0x7fL) << 56;
            if (b > 0x7f) {
              b = buf[pos + len++] & 0xff;
              l ^= (b & 0x7fL) << 63;
              if (b > 0x7f) {
                throw new IOException("Invalid long encoding");
              }
            }
          }
        }
      }
    }
    pos += len;
    return l;
  }

  public float readFloat() throws IOException {
    return Float.intBitsToFloat(readFixed32());
  }

  public int readFixed32() throws IOException {
    if ((limit - pos) < 4)                        // maybe not in buffer
      return read() | (read() << 8) | (read() << 16) | (read() << 24);

    int len = 1;
    int n = (buf[pos] & 0xff) | ((buf[pos + len++] & 0xff) << 8)
        | ((buf[pos + len++] & 0xff) << 16) | ((buf[pos + len++] & 0xff) << 24);
    if ((pos + 4) > limit)
      throw new EOFException();
    pos += 4;
    return n;
  }

  public double readDouble() throws IOException {
    return Double.longBitsToDouble(readFixed64());
  }

  public long readFixed64() throws IOException {
    return (readFixed32() & 0xFFFFFFFFL) | (((long)readFixed32()) << 32);
  }

  public String readString() throws IOException {
    int length = readInt();
    if (length <= (limit - pos)) {                        // in buffer
      String result = utf8.decode(ByteBuffer.wrap(buf, pos, length)).toString();
      pos += length;
      return result;
    }
    byte[] bytes = new byte[length];
    readFully(bytes, 0, length);
    return utf8.decode(ByteBuffer.wrap(bytes, 0, length)).toString();
  }

  public byte[] readBytes() throws IOException {
    byte[] result = new byte[readInt()];
    readFully(result);
    return result;
  }

  public ByteBuffer readBytes(ByteBuffer old) throws IOException {
    int length = readInt();
    ByteBuffer result;
    if (old != null && length <= old.capacity()) {
      result = old;
      result.clear();
    } else {
      result = ByteBuffer.allocate(length);
    }
    readFully(result.array(), result.position(), length);
    result.limit(length);
    return result;
  }

  public void skipBytes() throws IOException {
    skip(readInt());
  }

  private void skip(long length) throws IOException {
    seek(tell()+length);
  }

  public int read() throws IOException {
    if (pos >= limit) {
      limit = readInput(buf, 0, buf.length);
      pos = 0;
    }
    return buf[pos++] & 0xFF;
  }

  public void readFully(byte[] bytes) throws IOException {
    readFully(bytes, 0, bytes.length);
  }

  public void readFully(byte[] bytes, int start, int len) throws IOException {
    int buffered = limit - pos;
    if (len > buffered) {                        // buffer is insufficient

      System.arraycopy(buf, pos, bytes, start, buffered); // consume buffer
      start += buffered;
      len -= buffered;
      pos += buffered;
      if (len > buf.length) {                     // bigger than buffer
        do {
          int read = readInput(bytes, start, len); // read directly into result
          len -= read;
          start += read;
        } while (len > 0);
        return;
      }

      limit = readInput(buf, 0, buf.length);        // refill buffer
      pos = 0;
    }

    System.arraycopy(buf, pos, bytes, start, len); // copy from buffer
    pos += len;
  }

  private int readInput(byte[] b, int start, int len) throws IOException {
    int read = in.read(offset, b, start, len);
    if (read < 0) throw new EOFException();
    offset += read;
    return read;
 }

}
