/*
 * Copyright (C) 2007-2009 KenD00
 * 
 * This file is part of DumpHD.
 * 
 * DumpHD is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package dumphd.util;

import java.io.File;
import java.io.IOException;

/**
 * A ByteSource is an abstraction layer to allow easy access to data from various sources and hide the required I/O operations.
 * All operations should be buffered to allow performant reads and writes of small amounts of data.
 * 
 * This interface is intended for streaming access to the data (although it is highly recommended that an implementation uses faster
 * methods to physically access the data), thats why only relative read and write operations are supported.
 * 
 * Seek operations are also supported but should be used with care, it may be possible that these operations are very costly.
 * 
 * Windowing allows to reduce the view on the data to only a portion of it.
 * 
 * 
 * It is up to the implementation to support read only or read and write access.
 * 
 * Implementations need not to be thread safe.
 * 
 * General usage guidelines are:
 * - Never remove a window that you have not set yourself
 * - Never close a ByteSource that you have not created yourself
 * 
 * @author KenD00 
 */
public interface ByteSource {

   /**
    * R_MODE, only read access allowed
    */
   public final static int R_MODE = 0;
   /**
    * W_MODE, only write access allowed
    */
   public final static int W_MODE = 1;
   /**
    * RW_MODE, read and write access allowed
    */
   public final static int RW_MODE = 2;

   /**
    * Relative read operation.
    * Reads length bytes from the current position and stores them in dst starting at offset.
    * It is guaranteed that length bytes are read except EOF is reached.
    * If an I/O Error occurs, an exception is thrown.
    * 
    * @param dst Destination to store the read bytes
    * @param offset Offset in dst to store the bytes
    * @param length Number of bytes to read
    * @return The number of read bytes, -1 if EOF is reached
    * @throws IOException If an I/O error occurred 
    */
   public int read(byte[] dst, int offset, int length) throws IOException;

   /**
    * Relative write operation.
    * Writes length bytes to the current position from src starting at offset.
    * It is guaranteed that length bytes get written, except EOF is reached and it is not allowed to grow this ByteSource.
    * If an I/O Error occurs, an exception is thrown.
    *  
    * @param src Source to read from
    * @param offset Offset in src to start reading
    * @param length Number of bytes to write
    * @return The number of written bytes, -1 if EOF is reached and ByteSource cannot be grown
    * @throws IOException If an I/O error occurred 
    */
   public int write(byte[] src, int offset, int length) throws IOException;

   /**
    * Returns the current position.
    * 
    * @return The current Position
    * @throws IOException If an I/O error occurred
    */
   public long getPosition() throws IOException;

   /**
    * Sets the position to position.
    * 
    * @param position The new position to set
    * @throws IOException If an I/O error occurred
    */
   public void setPosition(long position) throws IOException;

   /**
    * Adds a Window starting at the current position with the given size.
    * After the window has been set, the current position will be position 0 and the ByteSource will be size big (at most, may be smaller if it is physically smaller
    * than the window). Multiple windows can be set, but a new window can only be smaller than the current window.
    * 
    * @param size The size in bytes of the window
    * @throws IOException An I/O error occurred or the new window exceeds the current window bounds 
    */
   public void addWindow(long size) throws IOException;

   /**
    * Removes the last set window.
    * 
    * @throws IOException An I/O error occurred or there are no more windows set
    */
   public void removeWindow() throws IOException;

   /**
    * Returns the current number of set windows.
    * 
    * @return The current number of set windows
    */
   public int windowCount();

   /**
    * Returns the size of this ByteSource.
    * If a window is set, returns the size of the last added window.
    * 
    * @return The size in bytes of this ByteSource
    * @throws IOException If an I/O error occurred
    */
   public long size() throws IOException ;

   /**
    * The mode of this ByteSource.
    * It may support read only, write only or read and write.
    * 
    * @return The mode of this ByteSource
    */
   public int getMode();

   /**
    * Returns the file object of the underlying physical data source.
    * 
    * @return The file object of the underlying physical data source.
    */
   public File getFile();

   /**
    * Closes the ByteSource, no further reads and writes are possible.
    * 
    * @throws IOException If an I/O error occurred
    */
   public void close() throws IOException;

}
