package com.one;

import java.io.*;

/**
 * Входной поток с произвольным доступом.
 */
public abstract class RandomAccessInputStream extends InputStream
{
	/**
	 * Переход на произвольную позицию
	 */
	public abstract void setPosition(int pos) throws IOException;
	
	/**
	 * Текущая позиция в потоке
	 */
	public abstract int getPosition() throws IOException;
	
	/**
	 * Общая емкость потока
	 */
	public abstract int getCapacity() throws IOException;
	
	/**
	 * Обновление потока
	 */
	public abstract void update() throws IOException;

	/**
	 * Временно "прикрыть" поток
	 */
	public abstract void pause() throws IOException;

	/**
	 * Восстановить "прикрытый" поток
	 */
	public abstract void resume() throws IOException;
	
	/**
	 * Mark / Reset поддерживается по определению
	 */
	public final boolean markSupported()
	{
		return true;
	}
	
	/**
	 * Поиск данных в потоке.
	 * Если startIndex >= 0, то поиск ведется со startIndex, иначе с текущей позиции.
	 * Если endIndex >= 0, то поиск идет максимум до endIndex, иначе до конца потока.
	 * После поиска поток возвращается на прежнюю позицию.
	 */
	public int indexOf(byte[] data, int off, int len, int startIndex, int endIndex) throws IOException
	{
		int prevpos = getPosition();
		
		if(startIndex >= 0)
		{
			setPosition(startIndex);
		}
		
		int end = off + len;
		int index = -1;
		int i = off;
		
		byte b;
		
		while(available() > 0)
		{
			b = (byte)read();
			
			if(b == data[i])
			{
				if(index < 0)
				{
					index = getPosition() - 1;
				}
				
				if(++i >= end)
				{
					break;
				}
			}
			else if(b == data[off])
			{
				index = getPosition() - 1;
				i = off;
			}
			else
			{
				index = -1;
				i = off;
			}
			
			if(endIndex >= 0 && getPosition() >= endIndex)
			{
				break;
			}
		}
		
		setPosition(prevpos);
		
		return index;
	}
	
	/**
	 * Получить часть некоторого потока
	 * как отдельный поток.
	 */
//	public static InputStream getPartialInputStream(RandomAccessInputStream is, int off, int len) throws IOException
//	{
//		byte[] b;
//
//		try
//		{
//			b = new byte[len];
//
//			int pos = is.tell();
//
//			is.seek(off);
//			len = is.read(b, 0, len);
//			is.seek(pos);
//		}
//		catch(OutOfMemoryError oome)
//		{
//			b = new byte[0];
//			len = 0;
//		}
//
//		return new ByteArrayInputStream(b, 0, len);
//	}
}
