package de.duehl.basics.text;

/*
 * Copyright 2021 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.ArrayList;
import java.util.List;

import org.junit.Test;

import de.duehl.basics.collections.CollectionsHelper;
import de.duehl.basics.test.TestHelper;

public class LinesTest {

    private final String path;

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


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


    @Test
    public void createEmptyLinesIsEmpty() {
        Lines lines = new Lines();
        assertTrue(lines.isEmpty());
        assertTrue(lines.getLines().isEmpty());
    }

    @Test
    public void createLinesFromListIsNotEmpty() {
        List<String> list = CollectionsHelper.buildListFrom("foo", "bar", "baz");
        Lines lines = new Lines(list);
        assertFalse(lines.isEmpty());
        assertFalse(lines.getLines().isEmpty());
    }

    @Test
    public void createLinesFromThreeElementListHasThreeELements() {
        List<String> list = CollectionsHelper.buildListFrom("foo", "bar", "baz");
        Lines lines = new Lines(list);
        assertEquals(list.size(), lines.size());
        assertEquals(3, lines.size());
    }

    @Test
    public void createLinesFromOtherLinesObjekt() {
        List<String> list = CollectionsHelper.buildListFrom("foo", "bar", "baz");
        Lines lines1 = new Lines(list);
        Lines lines2 = new Lines(lines1);
        assertEquals(list.size(), lines1.size());
        assertEquals(list.size(), lines2.size());
        assertEquals(3, lines1.size());
        assertEquals(3, lines2.size());
        assertEquals(list, lines1.getLines());
        assertEquals(list, lines2.getLines());
        assertEquals(lines1, lines2);
    }

    @Test
    public void createLinesFromElementListAndItsListIsSameAsInitialList() {
        List<String> list = CollectionsHelper.buildListFrom("foo", "bar", "baz");
        Lines lines = new Lines(list);
        assertEquals(list, lines.getLines());
    }

    @Test
    public void createLinesFromElementListHasSameELements() {
        List<String> list = CollectionsHelper.buildListFrom("foo", "bar", "baz");
        Lines lines = new Lines(list);
        assertEquals(list.size(), lines.size());
        for (int index = 0; index < lines.size(); ++index) {
            String listElement = list.get(index);
            String linesElement = lines.get(index);
            assertEquals(listElement, linesElement);
        }
    }

    @Test
    public void createLinesFromElementListAndLinesWithSingleAddAreSame() {
        List<String> list = CollectionsHelper.buildListFrom("foo", "bar", "baz");
        Lines lines1 = new Lines(list);
        Lines lines2 = new Lines();
        for (String line : list) {
            lines2.add(line);
        }
        assertEquals(lines1, lines2);
    }

    @Test
    public void createListOfLinesFromListOfListOfStrings() {
        List<String> list1 = CollectionsHelper.buildListFrom("foo1", "bar1", "baz1");
        List<String> list2 = CollectionsHelper.buildListFrom("foo2", "bar2", "baz2");
        List<String> list3 = CollectionsHelper.buildListFrom("foo3", "bar3", "baz3");

        List<List<String>> listOfLists = new ArrayList<>();
        listOfLists.add(list1);
        listOfLists.add(list2);
        listOfLists.add(list3);

        List<Lines> listOfLines = Lines.createListOfLinesFromListOfListOfStrings(listOfLists);
        assertEquals(3, listOfLines.size());
        Lines lines1 = listOfLines.get(0);
        Lines lines2 = listOfLines.get(1);
        Lines lines3 = listOfLines.get(2);

        assertEquals(3, lines1.size());
        assertEquals(3, lines2.size());
        assertEquals(3, lines3.size());

        assertEquals(list1, lines1.getLines());
        assertEquals(list2, lines2.getLines());
        assertEquals(list3, lines3.getLines());
    }

    @Test
    public void splitTextByLineBreaks() {
        String text = "foo" + Text.LINE_BREAK + "bar" + Text.LINE_BREAK + "baz";
        Lines lines = Lines.splitTextByLineBreaks(text);
        assertEquals(3, lines.size());

        assertEquals("foo", lines.get(0));
        assertEquals("bar", lines.get(1));
        assertEquals("baz", lines.get(2));
    }

    @Test
    public void splitTextByLineBreaksWithFinalLineBreak() {
        String text = "foo" + Text.LINE_BREAK + "bar" + Text.LINE_BREAK + "baz" + Text.LINE_BREAK;
        Lines lines = Lines.splitTextByLineBreaks(text);
        assertEquals(4, lines.size());

        assertEquals("foo", lines.get(0));
        assertEquals("bar", lines.get(1));
        assertEquals("baz", lines.get(2));
        assertEquals("", lines.get(3));
    }

    @Test
    public void iterate() {
        List<String> list = CollectionsHelper.buildListFrom("foo", "bar", "baz");
        Lines lines = new Lines(list);
        for (String line : lines) {
            list.contains(line);
        }
    }

    @Test
    public void joinWithLineBreak() {
        List<String> list = CollectionsHelper.buildListFrom("foo", "bar", "baz");
        Lines lines = new Lines(list);
        String actual = lines.joinWithLineBreak();
        String expected = "foo" + Text.LINE_BREAK + "bar" + Text.LINE_BREAK + "baz";
        assertEquals(expected, actual);
    }

    @Test
    public void buildListFrom() {
        List<String> list = CollectionsHelper.buildListFrom("foo", "bar", "baz");
        Lines lines1 = new Lines(list);
        Lines lines2 = Lines.buildListFrom("foo", "bar", "baz");
        assertEquals(lines1, lines2);
    }

    @Test (expected = RuntimeException.class)
    public void skipFirstAndLastNoLines() {
        Lines lines = Lines.buildListFrom();
        lines.skipFirstAndLast();
    }

    @Test (expected = RuntimeException.class)
    public void skipFirstAndLastOneLine() {
        Lines lines = Lines.buildListFrom("foo");
        lines.skipFirstAndLast();
    }

    @Test
    public void skipFirstAndLastTwoLines() {
        Lines lines = Lines.buildListFrom("foo", "bar");
        lines.skipFirstAndLast();
        assertEquals(0, lines.size());
    }

    @Test
    public void skipFirstAndLastThreeLines() {
        Lines lines = Lines.buildListFrom("foo", "bar", "baz");
        lines.skipFirstAndLast();
        assertEquals(1, lines.size());
        assertEquals("bar", lines.get(0));
    }

    @Test
    public void skipFirstAndLastFourLines() {
        Lines lines = Lines.buildListFrom("foo", "bar", "baz", "blubb");
        lines.skipFirstAndLast();
        assertEquals(2, lines.size());
        assertEquals("bar", lines.get(0));
        assertEquals("baz", lines.get(1));
    }

    @Test
    public void toStringTest() {
        /*
        Lines lines = Lines.buildListFrom("foo", "bar", "baz");
        String actual = lines.toString();
        String expected = "Lines [lines=[foo, bar, baz]]";
        assertEquals(expected, actual);
        */
        Lines lines = Lines.buildListFrom("foo", "bar", "baz");
        String actual = lines.toNiceString();
        String expected = ""
                + "     1. [foo]" + Text.LINE_BREAK
                + "     2. [bar]" + Text.LINE_BREAK
                + "     3. [baz]" + Text.LINE_BREAK;
        assertEquals(expected, actual);
    }

    @Test
    public void toNiceString() {
        Lines lines = Lines.buildListFrom("foo", "bar", "baz");
        String actual = lines.toNiceString();
        String expected = ""
                + "     1. [foo]" + Text.LINE_BREAK
                + "     2. [bar]" + Text.LINE_BREAK
                + "     3. [baz]" + Text.LINE_BREAK;
        assertEquals(expected, actual);
    }

    @Test
    public void readFileToLines() {
        String filename = path + "lines_test.txt";
        Lines lines = Lines.readFileToLines(filename);
        assertEquals(3, lines.size());

        assertEquals("foo", lines.get(0));
        assertEquals("bar", lines.get(1));
        assertEquals("baz", lines.get(2));
    }

    @Test
    public void addAllFromLines() {
        Lines lines1 = Lines.buildListFrom("foo", "bar", "baz");
        Lines lines2 = new Lines();
        lines2.addAll(lines1);
        assertEquals(lines1, lines2);
    }

    @Test
    public void addAllFromListOfStrings() {
        List<String> list = CollectionsHelper.buildListFrom("foo", "bar", "baz");
        Lines lines = new Lines();
        lines.addAll(list);
        assertEquals(list, lines.getLines());
    }

    @Test
    public void removeFirstIndex() {
        List<String> list = CollectionsHelper.buildListFrom("foo", "bar", "baz");
        Lines lines = new Lines(list);
        assertEquals(3, lines.size());
        assertEquals("foo", lines.get(0));
        assertEquals("bar", lines.get(1));
        assertEquals("baz", lines.get(2));
        lines.remove(0);
        assertEquals(2, lines.size());
        assertEquals("bar", lines.get(0));
        assertEquals("baz", lines.get(1));
    }

    @Test
    public void removeMiddleIndex() {
        List<String> list = CollectionsHelper.buildListFrom("foo", "bar", "baz");
        Lines lines = new Lines(list);
        assertEquals(3, lines.size());
        assertEquals("foo", lines.get(0));
        assertEquals("bar", lines.get(1));
        assertEquals("baz", lines.get(2));
        lines.remove(1);
        assertEquals(2, lines.size());
        assertEquals("foo", lines.get(0));
        assertEquals("baz", lines.get(1));
    }

    @Test
    public void removeLastIndex() {
        List<String> list = CollectionsHelper.buildListFrom("foo", "bar", "baz");
        Lines lines = new Lines(list);
        assertEquals(3, lines.size());
        assertEquals("foo", lines.get(0));
        assertEquals("bar", lines.get(1));
        assertEquals("baz", lines.get(2));
        lines.remove(2);
        assertEquals(2, lines.size());
        assertEquals("foo", lines.get(0));
        assertEquals("bar", lines.get(1));
    }

    @Test
    public void createFromMultipleLineInOneString() {
        String n = Text.LINE_BREAK;
        String line = ""
                + "<task>" + n
                + "    <task-name>NoGoodTags1</task-name>" + n
                + "    <task-sector>" + n
                + "        <task-sector-name>HR</task-sector-name>" + n
                + "    </task-sector>" + n
                + "</task>";
        Lines actual = Lines.createFromMultipleLineInOneString(line);
        Lines expected = new Lines(CollectionsHelper.buildListFrom(
                "<task>",
                "    <task-name>NoGoodTags1</task-name>",
                "    <task-sector>",
                "        <task-sector-name>HR</task-sector-name>",
                "    </task-sector>",
                "</task>"
                ));
        assertEquals(expected, actual);
    }

}
