package org.maachang.comet.net.nio ;

import java.io.IOException;
import java.io.InputStream;
import java.net.SocketTimeoutException;

import org.maachang.util.ArrayBinary;

/**
 * Nio用InputStream.
 * 
 * @version 2008/05/28
 * @author  masahito suzuki
 * @since   MaachangComet 1.1B
 */
class NioInputStream extends InputStream {
    
    private static final long TIMEOUT = 5000L ;
    private static final long MIN_TIMEOUT = 500L ;
    
    private NioElement element = null ;
    private int count = 0 ;
    private long timeout = -1L ;
    
    private NioInputStream() {
        
    }
    
    public NioInputStream( NioElement element ) {
        this( element,TIMEOUT ) ;
    }
    
    public NioInputStream( NioElement element,long timeout ) {
        this.element = element ;
        this.count = 0 ;
        this.timeout = ( timeout <= MIN_TIMEOUT ) ? MIN_TIMEOUT : timeout ;
    }
    
    public void close() {
        element = null ;
        count = 0 ;
    }
    
    public int available() throws IOException {
        if( element == null || element.isUse() == false ) {
            throw new IOException( "オブジェクトは既にクローズしています" ) ;
        }
        ArrayBinary bm = element.getBuffer() ;
        return bm.length() - count ;
    }
    
    public int read() throws IOException {
        if( element == null || element.isUse() == false ) {
            throw new IOException( "オブジェクトは既にクローズしています" ) ;
        }
        ArrayBinary bm = element.getBuffer() ;
        if( bm.length() <= count ) {
            long time = System.currentTimeMillis() ;
            for( ;; ) {
                if( bm.length() > count ) {
                    break ;
                }
                if( time + timeout <= System.currentTimeMillis() ) {
                    throw new SocketTimeoutException( "SocketTimeout" ) ;
                }
                try { Thread.sleep( 5L ) ; } catch( Exception e ) {}
            }
        }
        int ret = bm.getByte( count ) ;
        count ++ ;
        return ( byte )( ret & 0x000000ff ) ;
    }
    
    public boolean markSupported() {
        return false ;
    }
}
