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

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.StringReader;
import java.io.Writer;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.List;
import net.ranides.assira.io.FileHelper;
import net.ranides.assira.io.RIOException;
import org.junit.Test;
import static org.junit.Assert.*;

/**
 *
 * @author Ranides Atterwim <ranides@gmail.com>
 */
public class StringLoaderTest {
    
    public static final String TEXT = "Hello world\n2.line\n3.źrebię pasie się na łące gdy świeci słońce\nEOF";
    
    public StringLoaderTest() {
    }
    
    @Test
    public void testFromFile() throws IOException {
        File file = FileHelper.createTempFile("file", StringLoaderTest.class);
        writeToFile(file, TEXT, TextEncoding.NIO_UTF8);
        
        assertEquals(TEXT, StringLoader.fromFile(file));
        assertEquals(TEXT, StringLoader.fromFile(file.toString()));
        
        assertEquals(TEXT, StringLoader.fromFile(file, TextEncoding.NIO_UTF8));
        assertEquals(TEXT, StringLoader.fromFile(file.toString(), TextEncoding.NIO_UTF8));
        
        assertFalse( TEXT.equals(StringLoader.fromFile(file, TextEncoding.NIO_PL_WINDOWS)) );
        assertFalse( TEXT.equals(StringLoader.fromFile(file.toString(), TextEncoding.NIO_PL_WINDOWS)) );
        
        try {
            StringLoader.fromFile("404 :: not found");
            fail("RIOException expected");
        } catch(RIOException cause) {
            assertTrue(true);
        }
    }
    
    private void writeToFile(File file, String text, Charset charset) throws IOException {
        // @todo (prev # 4) StringIO # write ?
        // w zasadzie StringLoader powinien polecieć do StringIO
        // a tam powinny też siedzieć utility methods do zapisu :)
        // na przykład ta tutaj ;)
        try (Writer writer = new OutputStreamWriter(new FileOutputStream(file), charset)) {
            writer.append(text);
        }
    }
    
    @Test
    public void testFromReader() throws IOException {
        Reader reader = new StringReader(TEXT);
        assertEquals(TEXT, StringLoader.fromReader(reader));
        
        try {
            StringLoader.fromReader(null);
            fail("Exception expected");
        } catch(Exception cause) {
            assertTrue(true);
        }
    }
    
    @Test
    public void testFromStream() throws IOException {
        InputStream stream1 = new TextInputStream(TEXT);
        assertEquals(TEXT, StringLoader.fromStream(stream1));
        
        InputStream stream2 = new TextInputStream(TEXT, TextEncoding.NIO_PL_WINDOWS);
        stream2.mark(0);
        assertFalse( TEXT.equals(StringLoader.fromStream(stream2)) );
        
        stream2.reset();
        assertEquals(TEXT, StringLoader.fromStream(stream2, TextEncoding.NIO_PL_WINDOWS));
        
        try {
            StringLoader.fromStream(null);
            fail("Exception expected");
        } catch(Exception cause) {
            assertTrue(true);
        }
    }
    
    @Test
    public void testLoadProperties() throws IOException {
        Reader reader1 = new StringReader(Strings.raw(/*
            key=hello
            other.key=world
            last=X    
        */));
        assertEquals(
            "{key=hello, other.key=world, last=X}", 
            StringLoader.loadProperties(reader1).toString()
        );
        
        Reader reader2 = new StringReader(Strings.raw(/*
            key=hello
            other.key=world
            other.key=duplicate
            with.space= after 
            last=X    
        */));
        assertEquals(
            "{key=hello, other.key=duplicate, with.space=after, last=X}",
            StringLoader.loadProperties(reader2).toString()
        );
        
        Reader reader3 = new StringReader(Strings.raw(/*
            key=hello
            other.key=world
            other.key=duplicate
            with.space = everywhere 
            last=X    
        */));
        assertEquals(
            "{key=hello, other.key=duplicate, with.space=everywhere, last=X}",
            StringLoader.loadProperties(reader3).toString()
        );
        
        try {
            StringLoader.loadProperties(reader3);
            fail("IOException expected");
        } catch(RIOException cause) {
            assertTrue(true);
        }
    }
    
    @Test
    public void testLinesFromFile() throws IOException {
        File file1 = FileHelper.createTempFile("lines-utf", StringLoaderTest.class);
        File file2 = FileHelper.createTempFile("lines-win", StringLoaderTest.class);
        writeToFile(file1, TEXT, TextEncoding.NIO_UTF8);
        writeToFile(file2, TEXT, TextEncoding.NIO_PL_WINDOWS);
        
        List<String> expected = Arrays.asList(
            "Hello world",
            "2.line",
            "3.źrebię pasie się na łące gdy świeci słońce",
            "EOF"
        );
        
        assertEquals(expected, StringLoader.linesFromFile(file1));
        
        assertFalse( expected.equals(StringLoader.linesFromFile(file2)));
        assertEquals(expected, StringLoader.linesFromFile(file2, TextEncoding.NIO_PL_WINDOWS));
        
        assertEquals(expected, StringLoader.linesFromFile(file1.toString()));
        assertEquals(expected, StringLoader.linesFromFile(file2.toString(), TextEncoding.NIO_PL_WINDOWS));
        
        try {
            assertEquals(expected, StringLoader.linesFromFile("404 :: not found"));
            fail("RIOException expected");
        } catch(RIOException cause) {
            assertTrue(true);
        }
        
    }
    
    
}
