/* ====================================================================
   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.poi.util;

import java.io.OutputStream;

/**
 * Adapts a plain byte array to {@link LittleEndianOutput}
 */
public final class LittleEndianByteArrayOutputStream extends OutputStream implements LittleEndianOutput, DelayableLittleEndianOutput {
	private final byte[] _buf;
	private final int _endIndex;
	private int _writeIndex;

	public LittleEndianByteArrayOutputStream(byte[] buf, int startOffset, int maxWriteLen) { // NOSONAR
		if (startOffset < 0 || startOffset > buf.length) {
			throw new IllegalArgumentException("Specified startOffset (" + startOffset
					+ ") is out of allowable range (0.." + buf.length + ")");
		}
		_buf = buf;
		_writeIndex = startOffset;
		_endIndex = startOffset + maxWriteLen;
		if (_endIndex < startOffset ||  _endIndex > buf.length) {
			throw new IllegalArgumentException("calculated end index (" + _endIndex
					+ ") is out of allowable range (" + _writeIndex + ".." + buf.length + ")");
		}
	}
	public LittleEndianByteArrayOutputStream(byte[] buf, int startOffset) {
		this(buf, startOffset, buf.length - startOffset);
	}

	private void checkPosition(int i) {
		if (i > _endIndex - _writeIndex) {
			throw new RuntimeException("Buffer overrun");
		}
	}

	@Override
    public void writeByte(int v) {
		checkPosition(1);
		_buf[_writeIndex++] = (byte)v;
	}

	@Override
    public void writeDouble(double v) {
		writeLong(Double.doubleToLongBits(v));
	}

	@Override
    public void writeInt(int v) {
		checkPosition(4);
		int i = _writeIndex;
		_buf[i++] = (byte)((v >>>  0) & 0xFF);
		_buf[i++] = (byte)((v >>>  8) & 0xFF);
		_buf[i++] = (byte)((v >>> 16) & 0xFF);
		_buf[i++] = (byte)((v >>> 24) & 0xFF);
		_writeIndex = i;
	}

	@Override
    public void writeLong(long v) {
		writeInt((int)(v >>  0));
		writeInt((int)(v >> 32));
	}

	@Override
    public void writeShort(int v) {
		checkPosition(2);
		int i = _writeIndex;
		_buf[i++] = (byte)((v >>>  0) & 0xFF);
		_buf[i++] = (byte)((v >>>  8) & 0xFF);
		_writeIndex = i;
	}

	@Override
    public void write(int b) {
	    writeByte(b);
    }

	@Override
    public void write(byte[] b) {
		int len = b.length;
		checkPosition(len);
		System.arraycopy(b, 0, _buf, _writeIndex, len);
		_writeIndex += len;
	}

	@Override
    public void write(byte[] b, int offset, int len) {
		checkPosition(len);
		System.arraycopy(b, offset, _buf, _writeIndex, len);
		_writeIndex += len;
	}

	public int getWriteIndex() {
		return _writeIndex;
	}

	@Override
    public LittleEndianOutput createDelayedOutput(int size) {
		checkPosition(size);
		LittleEndianOutput result = new LittleEndianByteArrayOutputStream(_buf, _writeIndex, size);
		_writeIndex += size;
		return result;
	}
}
