/**
 * 
 */


package gov.va.med.cds.client.proxy;


import gov.va.med.cds.exception.SocketClientException;
import gov.va.med.cds.junit.runners.Suite;
import gov.va.med.cds.junit.runners.SuiteAwareRunner;
import gov.va.med.cds.testharness.AbstractLoggingTest;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.io.IOException;
import java.io.InputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.SocketTimeoutException;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.SocketChannel;


/**
 * @author susarlan
 * 
 */
@RunWith( SuiteAwareRunner.class )
public class BlockingConnectionFactoryTest
    extends
        AbstractLoggingTest
{
    /***
     * Test exception path of getConnection on the blocking connection factory
     */
    @Test
    //( expected = IllegalArgumentException.class )
    @Suite( groups = "checkintest", order = 1 )
    public void testGetBlockingConnectionConnectionRefused( )
        throws IOException
    {
        try
        {

            BlockingConnectionFactory factory = new BlockingConnectionFactory();

            SocketChannel socketChannel = factory.getConnection( "localhost", 5343 );

            Assert.assertFalse( socketChannel.connect( new InetSocketAddress( Integer.parseInt( "5343" ) ) ) );
        }
        catch ( SocketClientException socketClientException )
        {
            socketClientException.printStackTrace();
        }
    }


    /***
     * Test getConnection on the blocking connection factory
     * @throws InterruptedException 
     */
    @Test
    @Suite( groups = { "checkintest" }, order = 2 )
    public void testGetBlockingConnection( )
        throws IOException,
            InterruptedException
    {

        ServerSocket serverSocket = startServer();

        BlockingConnectionFactory factory = new BlockingConnectionFactory();

        SocketChannel socketChannel = factory.getConnection( "localhost", 5343 );

        Assert.assertTrue( socketChannel.isConnected() );

        stopServer( serverSocket );

        socketChannel.close();

    }


    /***
     * Test to check whether the setting of readTimeoutMillis is working
     * @throws InterruptedException 
     */
    @Test( expected = SocketTimeoutException.class )
    @Suite( groups = { "checkintest" }, order = 3 )
    public void testBlockingConnectionResponseTimeOut( )
        throws IOException,
            InterruptedException
    {

        byte EOB = 0x1C;

        startServer();

        BlockingConnectionFactory factory = new BlockingConnectionFactory();

        factory.setReadTimeoutMillis( 1000 );

        SocketChannel socketChannel = factory.getConnection( "localhost", 5343 );

        InputStream inStream = socketChannel.socket().getInputStream();

        ReadableByteChannel wrappedReadableByteChannel = Channels.newChannel( inStream );

        ByteBuffer byteBuffer = ByteBuffer.allocate( 2048 );

        wrappedReadableByteChannel.read( byteBuffer );
    }


    private ServerSocket startServer( )
        throws IOException
    {
        ServerSocket serverSocket = new ServerSocket( Integer.parseInt( "5343" ) );

        return serverSocket;
    }


    private void stopServer( ServerSocket serverSocket )
    {
        try
        {
            serverSocket.close();
        }
        catch ( IOException e )
        {
            e.printStackTrace();
        }
    }

}
