package org.maachang.comet.net.nio ;

import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;

/**
 * 処理用プーリングスレッド.
 * 
 * @version 2008/05/28
 * @author  masahito suzuki
 * @since   MaachangComet 1.1B
 */
class NioOutputStream extends OutputStream {
    
    private static final int BUFFER_LENGTH = 1024 ;
    private static final ByteBuffer EMPTY_BUFFER = ByteBuffer.allocate( 0 ) ;
    
    private NioElement element = null ;
    private ByteBuffer buffer = null ;
    private int count = 0 ;
    
    private NioOutputStream() {
        
    }
    
    public NioOutputStream( NioElement element ) {
        this.element = element ;
        this.buffer = ByteBuffer.allocate( BUFFER_LENGTH ) ;
        this.buffer.clear() ;
        this.element.update() ;
        this.element.startWrite() ;
    }
    
    public synchronized void close() throws IOException {
        if( element != null && element.isUse() ) {
            try { flush() ; } catch( Exception e ) {}
            element.getWriteBuffer().append( EMPTY_BUFFER ) ;
        }
        element = null ;
        buffer = null ;
        count = 0 ;
    }
    
    public synchronized void flush() throws IOException {
        if( element == null || element.isUse() == false ) {
            throw new IOException( "オブジェクトは既にクローズしています" ) ;
        }
        if( count > 0 ) {
            buffer.flip() ;
            element.getWriteBuffer().append( buffer ) ;
            buffer = ByteBuffer.allocate( BUFFER_LENGTH ) ;
            buffer.clear() ;
            count = 0 ;
        }
        element.update() ;
    }
    
    public synchronized void write(int b) throws IOException {
        if( element == null || element.isUse() == false ) {
            throw new IOException( "オブジェクトは既にクローズしています" ) ;
        }
        if( count >= BUFFER_LENGTH ) {
            this.flush() ;
        }
        buffer.put( ( byte )( b & 0x000000ff ) ) ;
        count ++ ;
    }
}
