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

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.util.function.BiConsumer;
import java.util.function.Function;
import net.ranides.assira.ContractTesters;
import net.ranides.assira.collection.arrays.ArrayUtils;
import net.ranides.assira.test.TAdapter;
import net.ranides.assira.text.Charsets;
import static org.junit.Assert.*;
import org.junit.Test;

/**
 *
 * @author Ranides Atterwim <ranides@gmail.com>
 */
public class DataAdapterTest {
   
    @Test
    public void testWriter() {
        TAdapter<Writer, ByteArrayOutputStream> map = new TAdapter<>();

        Function<Writer, String> mr = (ostream) -> {
            return new String(map.get(ostream).toByteArray(), Charsets.UTF16BE);
        };
        ContractTesters.runner()
            .param("writer.chars!", mr)
            .supplier(map.map(()->new ByteArrayOutputStream(), a -> DataAdapter.asWriter(new DataOutputStream(a))))
			.run();
        assertTrue(true);
    }
    
    @Test
    public void testOStream() {
        TAdapter<OutputStream, ByteArrayOutputStream> map = new TAdapter<>();
        
        Function<OutputStream, byte[]> mr = (ostream) -> {
            return map.get(ostream).toByteArray();
        };
        
        ContractTesters.runner()
            .param("ostream.bytes!", mr)
            .supplier(map.map(
                () -> new ByteArrayOutputStream(), 
                a -> DataAdapter.asOutput(new DataOutputStream(a))
            ))
			.run();
        assertTrue(true);

    }
    
    @Test
    public void testInput() throws IOException {
        Function<byte[], InputStream> mr = (array) -> {
            return DataAdapter.asInput(new DataInputStream(new ByteArrayInput().append(array)));
        };
        
        ContractTesters.runner()
			.ignore("InputStreamTester.mark")
            .function(new byte[0], mr)
			.run();
        assertTrue(true);
    }
    
    @Test
    public void testAsReader() throws IOException {
        TAdapter<Reader, ByteArrayInput> map = new TAdapter<>();
        
        BiConsumer<Reader, String> ar = (reader, value) -> {
            ByteArrayInput di = map.get(reader);
            di.append(value);
        };
        ContractTesters.runner()
            .ignore("ReaderTester.mark")
            .param("reader.appender!", ar)
            .function("", map.map(
				array -> new ByteArrayInput().append(array), 
                istream -> DataAdapter.asReader(new DataInputStream(istream))
            ))
			.run();
        assertTrue(true);
    }
    
    private static final class ByteArrayInput extends InputStream  {
        
        byte[] buffer = new byte[0];
        int position = 0;
 
        public ByteArrayInput append(String value) {
            return append(value.getBytes(Charsets.UTF16BE));
        }                
        
        public ByteArrayInput append(byte[] value) {
            buffer = ArrayUtils.concat(buffer, value);
            return this;
        }

        @Override
        public int read() throws IOException {
            return (position >= buffer.length) ? -1 : buffer[position++];
        }
        
    }
    
}
