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

import java.io.IOException;
import java.io.Reader;
import java.util.function.BiConsumer;
import java.util.function.Function;
import javax.annotation.Resource;
import net.ranides.assira.junit.TestContract;
import static org.junit.Assert.*;

/**
 *
 * @author Ranides Atterwim <ranides@gmail.com>
 */
public class ReaderTester {
    
    @Resource(name = "reader.appender!")
    private BiConsumer<Reader, String> ar;
    
    @TestContract
    public void readBasic(Function<String, Reader> f) throws IOException {
        Reader reader = f.apply("Hello world");
        
        int a = reader.read();
        assertEquals('H', (char)a);
        
        char[] b = ".##...".toCharArray();
        assertEquals(2, reader.read(b, 1, 2));
        assertArrayEquals(".el...".toCharArray(), b);

        assertEquals(0, reader.skip(-5));        
        assertEquals(5, reader.skip(5));
        
        assertTrue(reader.ready());
        assertTrue(reader.ready());
        
        char[] c = ".###...".toCharArray();
        assertEquals(3, reader.read(c, 1, 4));
        assertArrayEquals(".rld...".toCharArray(), c);
        
        assertFalse(reader.ready());
        assertFalse(reader.ready());
        
        assertEquals(0, reader.skip(3));
        assertEquals(-1, reader.read());
       
        reader.close();
        reader.close();
    }
    
    @TestContract
    public void readEOF(Function<String, Reader> f) throws IOException {
        Reader reader1 = f.apply("Hello world");
        
        char a1[] = new char[6];
        assertEquals(6, reader1.read(a1));
        assertArrayEquals("Hello ".toCharArray(), a1);
        
        char b1[] = "#####....".toCharArray();
        assertEquals(5, reader1.read(b1));
        assertArrayEquals("world....".toCharArray(), b1);
        
        assertEquals(-1, reader1.read(b1));
        assertFalse(reader1.ready());
        reader1.close();
        
        
        Reader reader2 = f.apply("Hello world");
        
        char a2[] = new char[6];
        assertEquals(6, reader2.read(a2));
        assertArrayEquals("Hello ".toCharArray(), a2);
        
        assertTrue(reader2.ready());
        
        char b2[] = "#####....".toCharArray();
        assertEquals(5, reader2.read(b2));
        assertArrayEquals("world....".toCharArray(), b2);
        
        assertFalse(reader2.ready());
        assertEquals(-1, reader2.read(b2));
        reader2.close();
    }
    
    @TestContract
    public void readBasic_Append(Reader reader) throws IOException {
        ar.accept(reader, "Hello world");
        
        int a = reader.read();
        assertEquals('H', (char)a);
        
        char[] b = ".##...".toCharArray();
        assertEquals(2, reader.read(b, 1, 2));
        assertArrayEquals(".el...".toCharArray(), b);

        assertEquals(0, reader.skip(-5));        
        assertEquals(5, reader.skip(5));
        
        char[] c = ".###...".toCharArray();
        assertEquals(3, reader.read(c, 1, 4));
        assertArrayEquals(".rld...".toCharArray(), c);
        
        assertFalse(reader.ready());
        assertEquals(0, reader.skip(3));
        assertEquals(-1, reader.read());
        
        ar.accept(reader, "!? ");
        assertTrue(reader.ready());
        assertEquals('!', (char)reader.read());
        assertEquals(2, reader.skip(7));
        assertFalse(reader.ready());
        assertFalse(reader.ready());
        
        ar.accept(reader, "text.");
        assertTrue(reader.ready());
        assertTrue(reader.ready());
        
        reader.close();
    }
    
    @TestContract
    public void mark(Function<String, Reader> f) throws IOException {
        Reader reader = f.apply("text.");

        assertTrue(reader.ready());
        assertTrue(reader.ready());
        assertTrue(reader.markSupported());
        
        reader.mark(100);
        char d[] = "-----".toCharArray();
        assertEquals(5, reader.read(d, 0, 5));
        assertArrayEquals("text.".toCharArray(), d);
        
        char e[] = "-----".toCharArray();
        assertEquals(-1, reader.read(e, 0, 30));
        assertEquals(-1, reader.read(e, 0, 30));
        reader.reset();
        assertEquals(5, reader.read(e, 0, 30));
        assertArrayEquals("text.".toCharArray(), e);
        
        reader.close();
    }
    
    @TestContract
    public void skip(Function<String, Reader> f) throws IOException {
        Reader reader = f.apply("Quick fox jumps over lazy dog.");
        
        assertEquals(0,reader.skip(0));
        assertRead("Qui", reader);
        
        assertTrue(reader.ready());
        assertEquals(0,reader.skip(0));
        assertRead("ck ", reader);
        
        assertEquals(2,reader.skip(2));
        assertRead("x j", reader);
        
        assertTrue(reader.ready());
        assertEquals(2,reader.skip(2));
        assertRead("ps ", reader);
        
        assertEquals(6,reader.skip(6));
        assertEquals((int)'a', reader.read());
        
        assertEquals(7,reader.skip(10));
        assertEquals(-1, reader.read());
        assertFalse(reader.ready());
        
        reader.close();
    }
    
    private static void assertRead(String expected, Reader reader) throws IOException {
        char[] buffer = new char[expected.length()];
        assertEquals(expected.length(), reader.read(buffer));
        assertArrayEquals(expected.toCharArray(), buffer);
    }
    
}
