package de.duehl.basics.history;

import static org.junit.Assert.*;

import org.junit.Test;

public class HistoryTest {

    @Test
    public void create() {
        HistoryObjectCopier<HistoryTestObject> copier = new HistoryTestObjectCopier();
        History<HistoryTestObject> history = new History<>(copier);
        assertNotNull(history);
        assertEquals(0, history.size());
    }

    @Test
    public void createEmtpyHasNoNext() {
        HistoryObjectCopier<HistoryTestObject> copier = new HistoryTestObjectCopier();
        History<HistoryTestObject> history = new History<>(copier);
        assertFalse(history.hasNext());
    }

    @Test
    public void createEmtpyHasNoPrevious() {
        HistoryObjectCopier<HistoryTestObject> copier = new HistoryTestObjectCopier();
        History<HistoryTestObject> history = new History<>(copier);
        assertFalse(history.hasPrevious());
    }

    @Test
    public void addObjectHistoryHasNoPreviousAndNoNext() {
        HistoryObjectCopier<HistoryTestObject> copier = new HistoryTestObjectCopier();
        History<HistoryTestObject> history = new History<>(copier);
        HistoryTestObject t = new HistoryTestObject("a", "b", "c");
        history.add(t);
        assertEquals(1, history.size());
        assertFalse(history.hasPrevious());
        assertFalse(history.hasNext());
    }

    @Test
    public void addTwoObjectsHistoryHasPreviousButNoNext() {
        HistoryObjectCopier<HistoryTestObject> copier = new HistoryTestObjectCopier();
        History<HistoryTestObject> history = new History<>(copier);
        HistoryTestObject t = new HistoryTestObject("a", "b", "c");
        history.add(t);
        t.setA("A");
        history.add(t);
        assertEquals(2, history.size());
        assertTrue(history.hasPrevious());
        assertFalse(history.hasNext());
    }

    @Test
    public void addTwoObjectsUndoHistoryHasNoPreviousButNext() {
        HistoryObjectCopier<HistoryTestObject> copier = new HistoryTestObjectCopier();
        History<HistoryTestObject> history = new History<>(copier);
        HistoryTestObject t = new HistoryTestObject("a", "b", "c");
        history.add(t);
        t.setA("A");
        history.add(t);
        assertEquals(2, history.size());
        t = history.getPrevious();
        assertEquals(2, history.size());
        assertFalse(history.hasPrevious());
        assertTrue(history.hasNext());
    }

    @Test
    public void addTwoObjectsUndoRedoHistoryHasPreviousButNoNext() {
        HistoryObjectCopier<HistoryTestObject> copier = new HistoryTestObjectCopier();
        History<HistoryTestObject> history = new History<>(copier);
        HistoryTestObject t = new HistoryTestObject("a", "b", "c");
        history.add(t);
        t.setA("A");
        history.add(t);
        assertEquals(2, history.size());
        t = history.getPrevious();
        assertEquals(2, history.size());
        t = history.getNext();
        assertEquals(2, history.size());
        assertTrue(history.hasPrevious());
        assertFalse(history.hasNext());
    }

    @Test
    public void createEmtpyAndClearHasNoPreviousAndNoNext() {
        HistoryObjectCopier<HistoryTestObject> copier = new HistoryTestObjectCopier();
        History<HistoryTestObject> history = new History<>(copier);
        history.clear();
        assertFalse(history.hasNext());
        assertFalse(history.hasPrevious());
    }

    @Test
    public void addTwoObjectsAndClearHasNoPreviousAndNoNext() {
        HistoryObjectCopier<HistoryTestObject> copier = new HistoryTestObjectCopier();
        History<HistoryTestObject> history = new History<>(copier);

        HistoryTestObject t = new HistoryTestObject("a", "b", "c");
        history.add(t);
        t.setA("A");
        history.add(t);

        history.clear();

        assertFalse(history.hasNext());
        assertFalse(history.hasPrevious());
    }

    @Test
    public void play01() {
        HistoryObjectCopier<HistoryTestObject> copier = new HistoryTestObjectCopier();
        History<HistoryTestObject> history = new History<>(copier);
        assertEquals(0, history.size());

        HistoryTestObject t = new HistoryTestObject("a", "b", "c");
        history.add(t);
        assertEquals(1, history.size());

        t.setA("A");
        history.add(t);
        assertEquals(2, history.size());

        t.setB("B");
        assertEquals(2, history.size());
        history.add(t);
        assertEquals(3, history.size());

        t.setC("C");
        history.add(t);
        assertEquals(4, history.size());

        assertEquals("A", t.getA());
        assertEquals("B", t.getB());
        assertEquals("C", t.getC());

        t = history.getPrevious();
        t = history.getPrevious();
        t = history.getPrevious();
        assertEquals(4, history.size());
        assertEquals("a", t.getA());
        assertEquals("b", t.getB());
        assertEquals("c", t.getC());

        assertFalse(history.hasPrevious());
        assertTrue(history.hasNext());

        t.setA("aaa");
        history.add(t);
        assertEquals(2, history.size());
        assertEquals("aaa", t.getA());
        assertEquals("b", t.getB());
        assertEquals("c", t.getC());
    }

    @Test
    public void play02() {
        HistoryObjectCopier<HistoryTestObject> copier = new HistoryTestObjectCopier();
        History<HistoryTestObject> history = new History<>(copier);
        assertEquals(0, history.size());

        HistoryTestObject t = new HistoryTestObject("a", "b", "c");
        history.add(t);
        assertEquals(1, history.size());

        t.setA("A");
        // vergessen das der Historie mitzuteilen
        assertEquals(1, history.size());

        t.setB("B");
        history.add(t);
        assertEquals(2, history.size());

        assertEquals("A", t.getA());
        assertEquals("B", t.getB());
        assertEquals("c", t.getC());

        t = history.getPrevious();

        assertEquals("a", t.getA());
        assertEquals("b", t.getB());
        assertEquals("c", t.getC());
    }

    // TODO mehr herumspielen!

}
