package de.duehl.basics.io;

/*
 * Copyright 2019 Christian Dühl. All rights reserved.
 *
 * This program is free software. You can redistribute it and/or
 * modify it under the same terms as perl:
 *
 * general:  http://dev.perl.org/licenses/
 * GPL:      http://dev.perl.org/licenses/gpl1.html
 * artistic: http://dev.perl.org/licenses/artistic.html
 */

import static org.junit.Assert.*;

import java.io.File;
import java.util.Arrays;
import java.util.List;

import org.junit.Test;

import de.duehl.basics.io.exceptions.IORuntimeException;
import de.duehl.basics.test.TestHelper;

public class FineFileWriterTest {

    private final String path;

    public FineFileWriterTest() {
        TestHelper testHelper = TestHelper.createForBasics(getClass(), 6);
        path =  testHelper.getTestDataPath() + File.separator;
    }


    /* -------------------------- TESTS -------------------------- */


    @Test(expected = IORuntimeException.class)
    public void createWrongObject1() {
        new FineFileWriter("c:/UsersB/NICHT_DA");
    }

    @Test
    public void createWrongObject2() {
        Writer writer = null;
        try {
            writer = new FineFileWriter("c:/UsersB/NICHT_DA");
        }
        catch (IORuntimeException e) {
        }
        assertTrue(null == writer);
    }

    @Test
    public void checkOutputExists() {
        String name = path + "file_writer_demo.txt";
        File file = new File(name);
        file.delete();

        Writer writer = new FineFileWriter(name);
        writer.write("line one");
        writer.write("line two");
        writer.write("line three");
        writer.close();

        assertTrue(file.exists() && file.isFile());
    }

    @Test
    public void checkOutputIsCorrect() {
        String name = path + "file_writer_demo.txt";
        String one   = "line one";
        String two   = "line two";
        String three = "line three";

        /* Datei löschen, falls vorhanden: */
        {
            File file = new File(name);
            file.delete();
        }

        /* Datei schreiben: */
        {
            Writer writer = new FineFileWriter(name);
            writer.writeln(one);
            writer.writeln(two);
            writer.writeln(three);
            writer.close();
        }

        /* Datei lesen: */
        Reader reader           = new FineFileReader(name);
        String lineOne          = reader.readNextLine();
        String lineTwo          = reader.readNextLine();
        String lineThree        = reader.readNextLine();
        String reachedEndOfFile = reader.readNextLine();

        /* Tests: */
        assertNotNull(lineOne);
        assertNotNull(lineTwo);
        assertNotNull(lineThree);
        assertNull(reachedEndOfFile);
        assertEquals(one, lineOne);
        assertEquals(two, lineTwo);
        assertEquals(three, lineThree);
    }

    @Test
    public void umlauts() {
        String name  = path + "file_writer_demo2.txt";
        String one   = "line one äääää";
        String two   = "line two ööööö";
        String three = "line three üüüüü";

        /* Datei löschen, falls vorhanden: */
        {
            File file = new File(name);
            file.delete();
        }

        /* Datei schreiben: */
        {
            Writer writer = new FineFileWriter(name);
            writer.writeln(one);
            writer.writeln(two);
            writer.writeln(three);
            writer.close();
        }

        /* Datei lesen: */
        Reader file = new FineFileReader(name);
        String lineOne = file.readNextLine();
        String lineTwo = file.readNextLine();
        String lineThree = file.readNextLine();
        String reachedEndOfFile = file.readNextLine();

        /* Tests: */
        assertNotNull(lineOne);
        assertNotNull(lineTwo);
        assertNotNull(lineThree);
        assertNull(reachedEndOfFile);
        assertEquals(one, lineOne);
        assertEquals(two, lineTwo);
        assertEquals(three, lineThree);
    }

    @Test(expected = IORuntimeException.class)
    public void writeAfterClose1() {
        String name  = path + "file_writer_demo3.txt";
        String one   = "line one";
        String two   = "line two";
        String three = "line three";
        String four  = "line four";

        /* Datei löschen, falls vorhanden: */
        {
            File file = new File(name);
            file.delete();
        }

        /* Datei schreiben: */
        {
            Writer writer = new FineFileWriter(name);
            writer.writeln(one);
            writer.writeln(two);
            writer.writeln(three);
            writer.close();
            writer.writeln(four);
        }
    }

    @Test
    public void writeAfterClose2() {
        String name  = path + "file_writer_demo3.txt";
        String one   = "line one";
        String two   = "line two";
        String three = "line three";
        String four  = "line four";

        /* Datei löschen, falls vorhanden: */
        {
            File file = new File(name);
            file.delete();
        }

        /* Datei schreiben: */
        {
            Writer writer = new FineFileWriter(name);
            writer.writeln(one);
            writer.writeln(two);
            writer.writeln(three);
            writer.close();
            try {
                writer.writeln(four);
                fail();
            }
            catch (Exception e) {
            }
        }
    }

    @Test
    public void writeFiledsLine() {
        String[] fields = { "A", "B", "C" };

        String name = path + "file_writer_demo_write_fields.txt";

        /* Datei löschen, falls vorhanden: */
        {
            File file = new File(name);
            file.delete();
        }

        /* Datei schreiben: */
        {
            Writer writer = new FineFileWriter(name);
            writer.writeFieldsLine(fields);
            writer.close();
        }

        /* Datei lesen: */
        Reader reader           = new FineFileReader(name);
        String line             = reader.readNextLine();
        String reachedEndOfFile = reader.readNextLine();

        /* Tests: */
        assertNotNull(line);
        assertNull(reachedEndOfFile);
        String[] parts = line.split("\t", -1);
        assertEquals(fields.length, parts.length);
        for (int i=0; i<fields.length; ++i) {
            assertEquals(fields[i], parts[i]);
        }
    }

    @Test
    public void writeFiledsLineList() {
        List<String> fieldsList;
        {
            String[] fields = { "A", "B", "C" };
            fieldsList = Arrays.asList(fields);
        }

        String name = path + "file_writer_demo_write_fields_list.txt";

        /* Datei löschen, falls vorhanden: */
        {
            File file = new File(name);
            file.delete();
        }

        /* Datei schreiben: */
        {
            Writer writer = new FineFileWriter(name);
            writer.writeFieldsLine(fieldsList);
            writer.close();
        }

        /* Datei lesen: */
        Reader reader           = new FineFileReader(name);
        String line             = reader.readNextLine();
        String reachedEndOfFile = reader.readNextLine();

        /* Tests: */
        assertNotNull(line);
        assertNull(reachedEndOfFile);
        List<String> parts = Arrays.asList(line.split("\t", -1));
        assertEquals(fieldsList.size(), parts.size());
        for (int i=0; i<fieldsList.size(); ++i) {
            assertEquals(fieldsList.get(i), parts.get(i));
        }
    }

    @Test
    public void writeFiledsLineVararg() {
        String name = path + "file_writer_demo_write_fields_vararg.txt";

        /* Datei löschen, falls vorhanden: */
        {
            File file = new File(name);
            file.delete();
        }

        /* Datei schreiben: */
        {
            Writer writer = new FineFileWriter(name);
            writer.writeFieldsLine("A", "B", "C");
            writer.close();
        }

        /* Datei lesen: */
        Reader reader           = new FineFileReader(name);
        String line             = reader.readNextLine();
        String reachedEndOfFile = reader.readNextLine();

        /* Tests: */
        assertNotNull(line);
        assertNull(reachedEndOfFile);
        String[] parts = line.split("\t", -1);
        String[] fields = { "A", "B", "C" };
        assertEquals(fields.length, parts.length);
        for (int i=0; i<fields.length; ++i) {
            assertEquals(fields[i], parts[i]);
        }
    }

    @Test
    public void writeFiledsLineListAndVararg() {
        List<String> fieldsList;
        {
            String[] fields = { "A", "B", "C" };
            fieldsList = Arrays.asList(fields);
        }

        String name = path + "file_writer_demo_write_fields_list_and_vararg.txt";

        /* Datei löschen, falls vorhanden: */
        {
            File file = new File(name);
            file.delete();
        }

        /* Datei schreiben: */
        {
            Writer writer = new FineFileWriter(name);
            writer.writeFieldsLine(fieldsList, "D", "E", "F");
            writer.close();
        }

        /* Datei lesen: */
        Reader reader           = new FineFileReader(name);
        String line             = reader.readNextLine();
        String reachedEndOfFile = reader.readNextLine();

        /* Tests: */
        assertNotNull(line);
        assertNull(reachedEndOfFile);
        List<String> parts = Arrays.asList(line.split("\t", -1));
        assertEquals(fieldsList.size() + 3, parts.size());
        for (int i = 0; i < fieldsList.size(); ++i) {
            assertEquals(fieldsList.get(i), parts.get(i));
        }
        assertEquals("D", parts.get(fieldsList.size() + 0));
        assertEquals("E", parts.get(fieldsList.size() + 1));
        assertEquals("F", parts.get(fieldsList.size() + 2));
    }

    @Test
    public void getFileName() {
        String name = path + "file_writer_demo_write_fields_vararg.txt";
        Writer writer = new FineFileWriter(name);
        String actual = writer.getFileName();
        String expected = name;
        assertEquals(expected, actual);
    }

}
