/*
 * 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.lucene.analysis.util;

import java.io.IOException;
import java.io.Reader;
import org.apache.lucene.util.ArrayUtil;

/**
 * Acts like a forever growing char[] as you read characters into it from the provided reader, but
 * internally it uses a circular buffer to only hold the characters that haven't been freed yet.
 * This is like a PushbackReader, except you don't have to specify up-front the max size of the
 * buffer, but you do have to periodically call {@link #freeBefore}.
 */
public final class RollingCharBuffer {

  private Reader reader;

  private char[] buffer = new char[512];

  // Next array index to write to in buffer:
  private int nextWrite;

  // Next absolute position to read from reader:
  private int nextPos;

  // How many valid chars (wrapped) are in the buffer:
  private int count;

  // True if we hit EOF
  private boolean end;

  /** Clear array and switch to new reader. */
  public void reset(Reader reader) {
    this.reader = reader;
    nextPos = 0;
    nextWrite = 0;
    count = 0;
    end = false;
  }

  /* Absolute position read.  NOTE: pos must not jump
   * ahead by more than 1!  Ie, it's OK to read arbitarily
   * far back (just not prior to the last {@link
   * #freeBefore}), but NOT ok to read arbitrarily far
   * ahead.  Returns -1 if you hit EOF. */
  public int get(int pos) throws IOException {
    // System.out.println("    get pos=" + pos + " nextPos=" + nextPos + " count=" + count);
    if (pos == nextPos) {
      if (end) {
        return -1;
      }
      if (count == buffer.length) {
        // Grow
        final char[] newBuffer = new char[ArrayUtil.oversize(1 + count, Character.BYTES)];
        // System.out.println(Thread.currentThread().getName() + ": cb grow " + newBuffer.length);
        System.arraycopy(buffer, nextWrite, newBuffer, 0, buffer.length - nextWrite);
        System.arraycopy(buffer, 0, newBuffer, buffer.length - nextWrite, nextWrite);
        nextWrite = buffer.length;
        buffer = newBuffer;
      }
      if (nextWrite == buffer.length) {
        nextWrite = 0;
      }

      final int toRead = buffer.length - Math.max(count, nextWrite);
      final int readCount = reader.read(buffer, nextWrite, toRead);
      if (readCount == -1) {
        end = true;
        return -1;
      }
      final int ch = buffer[nextWrite];
      nextWrite += readCount;
      count += readCount;
      nextPos += readCount;
      return ch;
    } else {
      // Cannot read from future (except by 1):
      assert pos < nextPos;

      // Cannot read from already freed past:
      assert nextPos - pos <= count : "nextPos=" + nextPos + " pos=" + pos + " count=" + count;

      return buffer[getIndex(pos)];
    }
  }

  // For assert:
  private boolean inBounds(int pos) {
    return pos >= 0 && pos < nextPos && pos >= nextPos - count;
  }

  private int getIndex(int pos) {
    int index = nextWrite - (nextPos - pos);
    if (index < 0) {
      // Wrap:
      index += buffer.length;
      assert index >= 0;
    }
    return index;
  }

  public char[] get(int posStart, int length) {
    assert length > 0;
    assert inBounds(posStart) : "posStart=" + posStart + " length=" + length;
    // System.out.println("    buffer.get posStart=" + posStart + " len=" + length);

    final int startIndex = getIndex(posStart);
    final int endIndex = getIndex(posStart + length);
    // System.out.println("      startIndex=" + startIndex + " endIndex=" + endIndex);

    final char[] result = new char[length];
    if (endIndex >= startIndex && length < buffer.length) {
      System.arraycopy(buffer, startIndex, result, 0, endIndex - startIndex);
    } else {
      // Wrapped:
      final int part1 = buffer.length - startIndex;
      System.arraycopy(buffer, startIndex, result, 0, part1);
      System.arraycopy(buffer, 0, result, buffer.length - startIndex, length - part1);
    }
    return result;
  }

  /** Call this to notify us that no chars before this absolute position are needed anymore. */
  public void freeBefore(int pos) {
    assert pos >= 0;
    assert pos <= nextPos;
    final int newCount = nextPos - pos;
    assert newCount <= count : "newCount=" + newCount + " count=" + count;
    assert newCount <= buffer.length : "newCount=" + newCount + " buf.length=" + buffer.length;
    count = newCount;
  }
}
