/*
 * @author Ranides Atterwim <ranides@gmail.com>
 * @copyright Ranides Atterwim
 * @license WTFPL
 * @url http://ranides.net/projects/assira
 */
package net.ranides.assira.nio;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import java.nio.CharBuffer;
import net.ranides.assira.text.StringEncoder;
import org.junit.Test;
import static org.junit.Assert.*;

/**
 *
 * @author Ranides Atterwim <ranides@gmail.com>
 */
public class DataAdapterTest {
    
    public DataAdapterTest() {
    }

    @Test
    public void testOutput() throws IOException {
        AOStream astream = new AOStream();
        OutputStream ostream = DataAdapter.asOutput(astream);
        
        ostream.write(new byte[]{1,2,3});
        ostream.write(27);
        ostream.write(new byte[]{5,6,7,8,9}, 1, 3);
        ostream.close();
        
        assertEquals("01 02 03 1B 06 07 08", astream.toByteString());
        assertTrue(true);
    }
    
    @Test 
    public void testWriter() throws IOException {
        AOStream astream = new AOStream();
        Writer writer = DataAdapter.asWriter(astream);
        
        writer.append("ABC");
        writer.append('D');
        writer.append("EFGHI", 1, 4);
        
        writer.write("abc");
        writer.write(new char[]{'d','e','f'});
        writer.write('g');
        writer.write("hijklm", 1, 3);
        writer.write(new char[]{'n','o','p','q','r'}, 0, 3);
        writer.close();
        
        assertEquals(
            "00 41 00 42 00 43 00 44 00 46 00 47 00 48 00 61 00 62 00 63 00 64 00 65 00 66 00 67 00 69 00 6A 00 6B 00 6E 00 6F 00 70", 
            astream.toByteString()
        );
    }
    
    @Test 
    public void testInput() throws IOException {
        AOStream estream = new AOStream();
        OutputStream ostream = DataAdapter.asOutput(estream);
        
        ostream.write(new byte[]{1,2,3});
        ostream.write(27);
        ostream.write(new byte[]{0x77, 0x77, 0x77});
        ostream.write(new byte[]{5,6,7,8,9}, 1, 3);
        ostream.close();
        
        byte[] input = estream.toByteArray();
        DataInputStream astream = new AIStream(input);
        InputStream istream = DataAdapter.asInput(astream);
        
        byte[] input1 = new byte[3];
        istream.read(input1);
        int input2 = istream.read();
        istream.skip(3);
        byte[] input3 = new byte[]{0x55,0x55,0x55,0x55,0x55};
        istream.read(input3, 1, 3);
        
        assertEquals(-1, istream.read(new byte[32]));
        
        istream.close();
        
        assertEquals("01 02 03", hex(input1));
        assertEquals(27, input2);
        assertEquals("55 06 07 08 55", hex(input3));
    }
    
    @Test 
    public void testReader() throws IOException {
        AOStream estream = new AOStream();
        Writer writer = DataAdapter.asWriter(estream);
        
        writer.append('A');
        writer.append("BCDE");
        writer.append("FGHI");
        writer.append("-----");
        writer.append("abc");
        
        writer.close();
        
        byte[] input = estream.toByteArray();
        DataInputStream astream = new AIStream(input);
        Reader reader = DataAdapter.asReader(astream);
        
        int input1 = reader.read();
        CharBuffer input2 = CharBuffer.allocate(4);
        reader.read(input2);
        char[] input3 = new char[4];
        reader.read(input3);
        reader.skip(5);
        char[] input4 = new char[]{'q','q','q','q','q'};
        reader.read(input4, 1, 3);
        
        assertEquals(-1, reader.read(new char[32]));
        reader.close();
        
        assertEquals('A', input1);
        assertArrayEquals("BCDE".toCharArray(), input2.array());
        assertArrayEquals("FGHI".toCharArray(), input3);
        assertArrayEquals("qabcq".toCharArray(), input4);
    }
    
    private static final class AIStream extends DataInputStream {

        public AIStream(byte[] array) {
            super(new ByteArrayInputStream(array));
        }
        
    }
    
    private static final class AOStream extends DataOutputStream {

        public AOStream() {
            super(new ByteArrayOutputStream());
        }
        
        public byte[] toByteArray() {
            return ((ByteArrayOutputStream)out).toByteArray();
        }
        
        public String toByteString() {
            return hex(toByteArray());
        }
        
    }
    
    private static String hex(byte[] array) {
        return StringEncoder.bytesToHex(array," ");
    }
    
}
