/*
 * File    : DiskManagerImpl.java
 * Created : 18-Oct-2003
 * By      : stuff
 * 
 * Azureus - a Java Bittorrent client
 *
 * This program 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 2 of the License.
 *
 * 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 ( see the LICENSE file ).
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
 
package org.gudy.azureus2.core3.disk;
 
 
import java.io.File;

import org.gudy.azureus2.core3.disk.impl.piecemapper.DMPieceList;
import org.gudy.azureus2.core3.disk.impl.piecemapper.DMPieceMap;
import org.gudy.azureus2.core3.torrent.TOTorrent;
import org.gudy.azureus2.core3.util.DirectByteBuffer;
import org.gudy.azureus2.core3.util.IndentWriter;

/**
* @author MjrTom
*			2005/Oct/08: Priority, getPieces done, etc changes for new piece-picking
*/

public interface
DiskManager
{
	public static final int INITIALIZING = 1;
	public static final int ALLOCATING = 2;
	public static final int CHECKING = 3;
	public static final int READY = 4;
	public static final int FAULTY = 10;
	
	
		// CHANGE THIS AND YOU MUST CHANGE NORMAL_REQUEST_SIZE in PeerReadRequest (plugin interface)
	
	public static final int BLOCK_SIZE_KB 	= 16;
	public static final int BLOCK_SIZE 		= BLOCK_SIZE_KB*1024;

	/**
	 * Start checking/allocating
	 */
	public void
	start();
	
		/**
		 * Stop can go async if the download is in a 'starting' state - if so this method returns true
		 * @param closing
		 * @return 
		 */
	
	public boolean
	stop(
		boolean	closing );
	
	public boolean
	isStopped();
	
	/**
	  * @return whether all files exist and sizes match
	  */
	
	public boolean
	filesExist();

	public DirectByteBuffer 
	readBlock(
		int pieceNumber, 
		int offset, 
		int length );
	
	public DiskManagerWriteRequest
	createWriteRequest(
		int 				pieceNumber,
		int 				offset,
		DirectByteBuffer 	data,
		Object 				user_data );

	
		/**
		 * enqueue an async write request
		 * @param pieceNumber
		 * @param offset
		 * @param data
		 * @param user_data	this will be provided to the listener when called back
		 * @param listener
		 */
	
	public void 
	enqueueWriteRequest(
		DiskManagerWriteRequest			request,
		DiskManagerWriteRequestListener	listener );

	public boolean
	hasOutstandingWriteRequestForPiece(
		int		piece_number );
	
	public DiskManagerReadRequest
	createReadRequest(
		int pieceNumber,
		int offset,
		int length );
	
		  /**
		   * Enqueue an async disk read request.
		   * @param request
		   * @param listener
		   */
	
	public void 
	enqueueReadRequest( 
		DiskManagerReadRequest 			request, 
		DiskManagerReadRequestListener 	listener );

	public boolean
	hasOutstandingReadRequestForPiece(
		int		piece_number );
	
		/**
		 * Create a request to check a particular piece
		 * @param pieceNumber	-1 for a complete recheck request
		 * @param user_data
		 * @return
		 */
	
	public DiskManagerCheckRequest
	createCheckRequest(
		int 		pieceNumber,
		Object		user_data );
	
		/**
		 * enqueue an asynchronous single piece check
		 * @param pieceNumber
		 * @param listener
		 * @param user_data
		 */
	
	public void
	enqueueCheckRequest(
		DiskManagerCheckRequest			request,
		DiskManagerCheckRequestListener	listener );
	
	public boolean
	hasOutstandingCheckRequestForPiece(
		int		piece_number );
	
		/**
		 * recheck the entire torrent asynchronously, reporting each piece to the listener
		 * @param listener
		 * @param user_data
		 */
	
	public void
	enqueueCompleteRecheckRequest(
		DiskManagerCheckRequest			request,
		DiskManagerCheckRequestListener	listener );
	
	public void
	setPieceCheckingEnabled(
		boolean		enabled );
			
	public void
    saveResumeData(
    	boolean interim_save )
		
		throws Exception;

	
	public DiskManagerPiece[] 
	getPieces();
	
	public int 
	getNbPieces();

	public DiskManagerFileInfo[] getFiles();
	public DiskManagerFileInfoSet getFileSet();
	public DiskManagerPiece getPiece(int PieceNumber);

		/**
		 * DON'T CACHE the DMPieceMap - as it is designed to be discarded when not in use
		 * @return
		 */
	
	public DMPieceMap  getPieceMap();
	
	public DMPieceList getPieceList(int pieceNumber);
	
	public int
	getState();
	
	public long
	getTotalLength();
	
	public int
	getPieceLength();
	
	public int
	getPieceLength(
		int	piece_number );
	
	public long
	getRemaining();
	
	public long
	getRemainingExcludingDND();
	
	/**
	 * Get the percentage done during checking, allocation or initializing
	 *  
	 * @return percent done * 1000 (1000 = 100%)
	 */
	public int
	getPercentDone();
	
	public String
	getErrorMessage();
  
	public void
	downloadEnded(
		OperationStatus		op_status );

    public void
    downloadRemoved();
	
	public void 
	moveDataFiles(
		File 				new_parent_dir, 
		String 				dl_name, 
		OperationStatus 	op_status );
	
		/**
		 * returns -1 if no recheck in progress, percentage complete in 1000 notation otherwise
		 * @return
		 */
	
	public int 
	getCompleteRecheckStatus();
  
		/**
		 * When a download's data is moving (for completion or removal events) this gives the progress in 1000 notation. -1 if nothing's going on
		 * @return
		 */
	
	public int
	getMoveProgress();
	
		/**
		 * method for checking that the block details are sensible
		 * @param pieceNumber
		 * @param offset
		 * @param data
		 * @return
		 */
	
	public boolean 
	checkBlockConsistencyForWrite(
		String				originator,
		int 				pieceNumber, 
		int 				offset, 
		DirectByteBuffer 	data );

		/**
		 * method for checking that the block details are sensible
		 * @param pieceNumber
		 * @param offset
		 * @param length
		 * @return
		 */
	
	public boolean 
	checkBlockConsistencyForRead(
		String	originator,
		boolean	peer_request,
		int 	pieceNumber, 
		int	 	offset, 
		int 	length );
		
	public boolean 
	checkBlockConsistencyForHint(
		String	originator,
		int 	pieceNumber, 
		int	 	offset, 
		int 	length );
	
	public TOTorrent
	getTorrent();
	
	public File
	getSaveLocation();
	
	public void
	addListener(
		DiskManagerListener	l );
	
	public void
	removeListener(
		DiskManagerListener	l );
  
	public boolean
	hasListener(
	    DiskManagerListener	l );
  
  /**
   * Save the individual file priorities map to
   * DownloadManager.getData( "file_priorities" ).
   */

	public void 
	saveState();

	/**
	 * @param pieceNumber
	 * @return true if the pieceNumber is Needed and not Done
	 */
	public boolean isInteresting(int pieceNumber);
	
	public boolean isDone(int pieceNumber);

	public int getCacheMode();
	
	public long[]
	getReadStats();
	
	public void
	generateEvidence(
		IndentWriter		writer );
	
	public interface
	OperationStatus
	{
		public void
		gonnaTakeAWhile(
			GettingThere	gt );
	}
	
	public interface
	GettingThere
	{
		public boolean
		hasGotThere();
	}
}