package de.duehl.basics.io;

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

import org.junit.Test;

public class FileSetTest {

    @Test
    public void createObjectWithEmptyList() {
        FileSet set = new FileSet(new ArrayList<String>());
        assertNotNull(set);
    }

    @Test
    public void createObjectWithEmptyEllipse() {
        FileSet set = new FileSet();
        assertNotNull(set);
    }

    @Test
    public void createObjectWithFilledList() {
        String fileName1 = "c:/test/foo.txt";
        String fileName2 = "c:/test/bar.txt";
        String fileName3 = "c:/test/baz.txt";
        List<String> fileNames = new ArrayList<>();
        fileNames.add(fileName1);
        fileNames.add(fileName2);
        fileNames.add(fileName3);
        FileSet set = new FileSet(fileNames);
        assertNotNull(set);
    }

    @Test
    public void createObjectWithFilledEllipse() {
        String fileName1 = "c:/test/foo.txt";
        String fileName2 = "c:/test/bar.txt";
        String fileName3 = "c:/test/baz.txt";
        FileSet set = new FileSet(fileName1, fileName2, fileName3);
        assertNotNull(set);
    }

    @Test (expected = IllegalArgumentException.class)
    public void failOnCreateObjectWithFilledListWithTwoEqualNames() {
        String fileName1 = "c:/test/foo.txt";
        String fileName2 = "c:/test/foo.txt";
        List<String> fileNames = new ArrayList<>();
        fileNames.add(fileName1);
        fileNames.add(fileName2);
        new FileSet(fileNames);
    }

    @Test (expected = IllegalArgumentException.class)
    public void failOnCreateObjectWithEllipseWithTwoEqualNames() {
        String fileName1 = "c:/test/foo.txt";
        String fileName2 = "c:/test/foo.txt";
        new FileSet(fileName1, fileName2);
    }

    @Test (expected = IllegalArgumentException.class)
    public void failOnCreateObjectWithFilledListWithTwoNormalizedEqualNames() {
        String fileName1 = "c:/test/foo.txt";
        String fileName2 = "c:\\test\\foo.txt";
        List<String> fileNames = new ArrayList<>();
        fileNames.add(fileName1);
        fileNames.add(fileName2);
        new FileSet(fileNames);
    }

    @Test (expected = IllegalArgumentException.class)
    public void failOnCreateObjectWithEllipseWithTwoNormalizedEqualNames() {
        String fileName1 = "c:/test/foo.txt";
        String fileName2 = "c:\\test\\foo.txt";
        new FileSet(fileName1, fileName2);
    }

    @Test (expected = IllegalArgumentException.class)
    public void failOnAddAnEqualNameAfterCreationWithList() {
        String fileName1 = "c:/test/foo.txt";
        List<String> fileNames = new ArrayList<>();
        fileNames.add(fileName1);
        FileSet set = new FileSet(fileNames);
        String fileName2 = "c:/test/foo.txt";
        set.add(fileName2);
    }

    @Test (expected = IllegalArgumentException.class)
    public void failOnAddAnEqualNameAfterCreationWithEllipse() {
        String fileName1 = "c:/test/foo.txt";
        FileSet set = new FileSet(fileName1);
        String fileName2 = "c:/test/foo.txt";
        set.add(fileName2);
    }

    @Test (expected = IllegalArgumentException.class)
    public void failOnAddANormalizedEqualNameAfterCreationWithList() {
        String fileName1 = "c:/test/foo.txt";
        List<String> fileNames = new ArrayList<>();
        fileNames.add(fileName1);
        new FileSet(fileNames);
        FileSet set = new FileSet(fileNames);
        String fileName2 = "c:\\test\\foo.txt";
        set.add(fileName2);
    }

    @Test (expected = IllegalArgumentException.class)
    public void failOnAddANormalizedEqualNameAfterCreationWithEllipse() {
        String fileName1 = "c:/test/foo.txt";
        FileSet set = new FileSet(fileName1);
        String fileName2 = "c:\\test\\foo.txt";
        set.add(fileName2);
    }

    @Test
    public void addAll() {
        String fileName1 = "c:/test/foo.txt";
        String fileName2 = "c:/test/bar.txt";
        String fileName3 = "c:/test/baz.txt";
        FileSet set1 = new FileSet(fileName1, fileName2, fileName3);

        String fileName4 = "c:/test/foo2.txt";
        String fileName5 = "c:/test/bar2.txt";
        String fileName6 = "c:/test/baz2.txt";
        FileSet set2 = new FileSet(fileName4, fileName5, fileName6);


        int oldSize = set1.size();
        int addSize = set2.size();

        set1.addAll(set2);
        int newSize = set1.size();
        assertTrue(newSize == oldSize + addSize);
    }

    @Test
    public void addAllWithDoubleNames() {
        String fileName1 = "c:/test/foo.txt";
        String fileName2 = "c:/test/bar.txt";
        String fileName3 = "c:/test/baz.txt";
        FileSet set1 = new FileSet(fileName1, fileName2, fileName3);

        String fileName4 = "c:/test/foo.txt";
        String fileName5 = "c:/test/bar.txt";
        String fileName6 = "c:/test/baz.txt";
        FileSet set2 = new FileSet(fileName4, fileName5, fileName6);

        int oldSize = set1.size();

        set1.addAll(set2);
        int newSize = set1.size();
        assertTrue(newSize == oldSize);
    }

    @Test
    public void addAllWithDoubleNamesNormalized() {
        String fileName1 = "c:/test/foo.txt";
        String fileName2 = "c:/test/bar.txt";
        String fileName3 = "c:/test/baz.txt";
        FileSet set1 = new FileSet(fileName1, fileName2, fileName3);

        String fileName4 = "c:\\test\\foo.txt";
        String fileName5 = "c:\\test\\bar.txt";
        String fileName6 = "c:\\test\\baz.txt";
        FileSet set2 = new FileSet(fileName4, fileName5, fileName6);

        int oldSize = set1.size();

        set1.addAll(set2);
        int newSize = set1.size();
        assertTrue(newSize == oldSize);
    }

    @Test
    public void containsFailing() {
        String fileName1 = "c:/test/foo.txt";
        String fileName2 = "c:/test/bar.txt";
        String fileName3 = "c:/test/baz.txt";
        FileSet set = new FileSet(fileName1, fileName2, fileName3);

        String fileName4 = "c:/test/blabla.txt";
        assertFalse(set.contains(fileName4));
    }

    @Test
    public void containsSuccessfulWithEqualName() {
        String fileName1 = "c:/test/foo.txt";
        String fileName2 = "c:/test/bar.txt";
        String fileName3 = "c:/test/baz.txt";
        FileSet set = new FileSet(fileName1, fileName2, fileName3);

        String fileName4 = "c:/test/foo.txt";
        assertTrue(set.contains(fileName4));
    }

    @Test
    public void containsSuccessfulWithEqualNormalizedName() {
        String fileName1 = "c:/test/foo.txt";
        String fileName2 = "c:/test/bar.txt";
        String fileName3 = "c:/test/baz.txt";
        FileSet set = new FileSet(fileName1, fileName2, fileName3);

        String fileName4 = "c:\\test\\foo.txt";
        assertTrue(set.contains(fileName4));
    }

    @Test
    public void iteratorTest() {
        String fileName1 = "c:/test/foo.txt";
        String fileName2 = "c:/test/bar.txt";
        String fileName3 = "c:/test/baz.txt";
        FileSet set = new FileSet(fileName1, fileName2, fileName3);

        int count = 0;
        for (@SuppressWarnings("unused") String filename : set) {
            ++count;
        }
        assertEquals(3, count);
    }

    @Test
    public void size() {
        String fileName1 = "c:/test/foo.txt";
        String fileName2 = "c:/test/bar.txt";
        String fileName3 = "c:/test/baz.txt";
        FileSet set = new FileSet(fileName1, fileName2, fileName3);

        assertEquals(3, set.size());
    }

    @Test
    public void addFileAndIncreaseSize() {
        String fileName1 = "c:/test/foo.txt";
        String fileName2 = "c:/test/bar.txt";
        String fileName3 = "c:/test/baz.txt";
        FileSet set = new FileSet(fileName1, fileName2, fileName3);

        String fileName4 = "c:/test/blabla.txt";
        int oldSize = set.size();
        set.add(fileName4);
        int newSize = set.size();
        assertTrue(newSize == oldSize + 1);
    }

    @Test
    public void get() {
        String fileName1 = "c:\\test\\foo.txt";
        FileSet set = new FileSet(fileName1);

        String expected = "c:/test/foo.txt";
        String actual = set.get(0);

        assertEquals(expected, actual);
    }

    @Test
    public void toStringTest() {
        String fileName1 = "c:/test/foo.txt";
        String fileName2 = "c:/test/bar.txt";
        String fileName3 = "c:/test/baz.txt";
        FileSet set = new FileSet(fileName1, fileName2, fileName3);

        String expected = "FileSet [fileNames=[c:/test/foo.txt, c:/test/bar.txt, c:/test/baz.txt]]";
        String actual = set.toString();

        assertEquals(expected, actual);
    }

    @Test
    public void removeEqualName() {
        String fileName1 = "c:/test/foo.txt";
        String fileName2 = "c:/test/bar.txt";
        String fileName3 = "c:/test/baz.txt";
        FileSet set = new FileSet(fileName1, fileName2, fileName3);

        String fileName4 = "c:/test/foo.txt";
        int oldSize = set.size();
        set.remove(fileName4);
        int newSize = set.size();
        assertTrue(newSize == oldSize - 1);
    }

    @Test
    public void removeEqualNormalizedName() {
        String fileName1 = "c:/test/foo.txt";
        String fileName2 = "c:/test/bar.txt";
        String fileName3 = "c:/test/baz.txt";
        FileSet set = new FileSet(fileName1, fileName2, fileName3);

        String fileName4 = "c:\\test\\foo.txt";
        int oldSize = set.size();
        set.remove(fileName4);
        int newSize = set.size();
        assertTrue(newSize == oldSize - 1);
    }

    @Test
    public void removeMissingName() {
        String fileName1 = "c:/test/foo.txt";
        String fileName2 = "c:/test/bar.txt";
        String fileName3 = "c:/test/baz.txt";
        FileSet set = new FileSet(fileName1, fileName2, fileName3);

        String fileName4 = "missing file name";
        int oldSize = set.size();
        set.remove(fileName4);
        int newSize = set.size();
        assertTrue(newSize == oldSize);
    }

    @Test
    public void removeEqualNameCheckResult() {
        String fileName1 = "c:/test/foo.txt";
        String fileName2 = "c:/test/bar.txt";
        String fileName3 = "c:/test/baz.txt";
        FileSet set = new FileSet(fileName1, fileName2, fileName3);

        String fileName4 = "c:/test/foo.txt";
        boolean success = set.remove(fileName4);
        assertTrue(success);
    }

    @Test
    public void removeEqualNormalizedNameCheckResult() {
        String fileName1 = "c:/test/foo.txt";
        String fileName2 = "c:/test/bar.txt";
        String fileName3 = "c:/test/baz.txt";
        FileSet set = new FileSet(fileName1, fileName2, fileName3);

        String fileName4 = "c:\\test\\foo.txt";
        boolean success = set.remove(fileName4);
        assertTrue(success);
    }

    @Test
    public void removeMissingNameCheckResult() {
        String fileName1 = "c:/test/foo.txt";
        String fileName2 = "c:/test/bar.txt";
        String fileName3 = "c:/test/baz.txt";
        FileSet set = new FileSet(fileName1, fileName2, fileName3);

        String fileName4 = "missing file name";
        boolean success = set.remove(fileName4);
        assertFalse(success);
    }

    @Test
    public void clear() {
        String fileName1 = "c:/test/foo.txt";
        String fileName2 = "c:/test/bar.txt";
        String fileName3 = "c:/test/baz.txt";
        FileSet set = new FileSet(fileName1, fileName2, fileName3);


        String fileName4 = "missing file name";
        boolean success = set.remove(fileName4);
        assertFalse(success);
    }

    @Test
    public void addClearAndDoNotContain() {
        String fileName = "c:/test/foo.txt";
        FileSet set = new FileSet(fileName);
        set.clear();
        assertFalse(set.contains(fileName));
    }

    @Test
    public void addClearAndDoNotRemove() {
        String fileName = "c:/test/foo.txt";
        FileSet set = new FileSet(fileName);
        set.clear();
        boolean success = set.remove(fileName);
        assertFalse(success);
    }

    @Test
    public void doNotFailOnCreateObjectWithFilledListWithTwoEqualNamesAndIntermediateClear() {
        String fileName = "c:/test/foo.txt";
        FileSet set = new FileSet(fileName);
        set.clear();
        set.add(fileName);
    }

    @Test
    public void emptyFileSetIsEmpty() {
        FileSet set = new FileSet();
        assertTrue(set.isEmpty());
    }

    @Test
    public void addClearAndFileSetIsEmpty() {
        String fileName = "c:/test/foo.txt";
        FileSet set = new FileSet(fileName);
        set.clear();
        assertTrue(set.isEmpty());
    }

    @Test
    public void createNotEmptyAndFileSetIsNotEmpty() {
        String fileName = "c:/test/foo.txt";
        FileSet set = new FileSet(fileName);
        assertFalse(set.isEmpty());
    }

    @Test
    public void addAndDoNotHaveAnEmptyList() {
        String fileName = "c:/test/foo.txt";
        FileSet set = new FileSet();
        set.add(fileName);
        assertFalse(set.isEmpty());
    }

    @Test
    public void sort() {
        String fileName1 = "c.txt";
        String fileName2 = "a.txt";
        String fileName3 = "b.txt";
        FileSet set = new FileSet(fileName1, fileName2, fileName3);

        set.sort();
        String filename1AfterSort = set.get(0);
        String filename2AfterSort = set.get(1);
        String filename3AfterSort = set.get(2);

        assertEquals(fileName2, filename1AfterSort);
        assertEquals(fileName3, filename2AfterSort);
        assertEquals(fileName1, filename3AfterSort);
    }

}
