/*******************************************************************************
 * Copyright (c) 2018, 2020 Dirk Fauth.
 *
 * This program and the accompanying materials are made
 * available under the terms of the Eclipse Public License 2.0
 * which is available at https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     Dirk Fauth <dirk.fauth@googlemail.com> - initial API and implementation
 ******************************************************************************/
package org.eclipse.nebula.widgets.nattable.extension.glazedlists.test.integration;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import java.io.Serializable;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import org.eclipse.nebula.widgets.nattable.command.DisposeResourcesCommand;
import org.eclipse.nebula.widgets.nattable.data.IColumnPropertyAccessor;
import org.eclipse.nebula.widgets.nattable.data.IRowDataProvider;
import org.eclipse.nebula.widgets.nattable.data.IRowIdAccessor;
import org.eclipse.nebula.widgets.nattable.data.ListDataProvider;
import org.eclipse.nebula.widgets.nattable.data.ReflectiveColumnPropertyAccessor;
import org.eclipse.nebula.widgets.nattable.data.command.RowDeleteCommandHandler;
import org.eclipse.nebula.widgets.nattable.data.command.RowInsertCommand;
import org.eclipse.nebula.widgets.nattable.data.command.RowObjectDeleteCommandHandler;
import org.eclipse.nebula.widgets.nattable.datachange.DataChangeHandler;
import org.eclipse.nebula.widgets.nattable.datachange.DataChangeLayer;
import org.eclipse.nebula.widgets.nattable.datachange.IdIndexIdentifier;
import org.eclipse.nebula.widgets.nattable.datachange.IdIndexKeyHandler;
import org.eclipse.nebula.widgets.nattable.datachange.RowDeleteDataChangeHandler;
import org.eclipse.nebula.widgets.nattable.datachange.RowInsertDataChangeHandler;
import org.eclipse.nebula.widgets.nattable.datachange.command.DiscardDataChangesCommand;
import org.eclipse.nebula.widgets.nattable.datachange.command.KeyRowInsertCommandHandler;
import org.eclipse.nebula.widgets.nattable.dataset.person.Person;
import org.eclipse.nebula.widgets.nattable.dataset.person.Person.Gender;
import org.eclipse.nebula.widgets.nattable.dataset.person.PersonService;
import org.eclipse.nebula.widgets.nattable.edit.command.UpdateDataCommand;
import org.eclipse.nebula.widgets.nattable.extension.glazedlists.GlazedListsEventLayer;
import org.eclipse.nebula.widgets.nattable.layer.DataLayer;
import org.eclipse.nebula.widgets.nattable.layer.ILayerListener;
import org.eclipse.nebula.widgets.nattable.layer.event.ILayerEvent;
import org.eclipse.nebula.widgets.nattable.layer.event.RowStructuralRefreshEvent;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import ca.odell.glazedlists.EventList;
import ca.odell.glazedlists.FilterList;
import ca.odell.glazedlists.GlazedLists;
import ca.odell.glazedlists.SortedList;
import ca.odell.glazedlists.matchers.Matcher;

@SuppressWarnings("unchecked")
public class RowStructuralDataChangeLayerIntegrationTest {

    private List<Person> dataModel;
    private EventList<Person> eventList;
    private SortedList<Person> sortedList;
    private FilterList<Person> filterList;
    private IRowDataProvider<Person> dataProvider;
    private DataLayer dataLayer;
    private DataChangeLayer dataChangeLayer;
    private RowInsertDataChangeHandler insertHandler;
    private RowDeleteDataChangeHandler deleteHandler;

    private CountDownLatch lock = new CountDownLatch(1);

    @Before
    public void setup() {
        this.dataModel = PersonService.getFixedPersons();
        this.eventList = GlazedLists.eventList(this.dataModel);
        this.sortedList = new SortedList<>(this.eventList, null);
        this.filterList = new FilterList<>(this.sortedList);

        IColumnPropertyAccessor<Person> columnPropertyAccessor = new ReflectiveColumnPropertyAccessor<>(new String[] {
                "firstName",
                "lastName",
                "gender",
                "married",
                "birthday" });

        IRowIdAccessor<Person> rowIdAccessor = new IRowIdAccessor<Person>() {

            @Override
            public Serializable getRowId(Person rowObject) {
                return rowObject.getId();
            }
        };

        this.dataProvider = new ListDataProvider<>(
                this.filterList,
                columnPropertyAccessor);
        this.dataLayer = new DataLayer(this.dataProvider);

        // register the RowDeleteCommandHandler for delete operations by
        // index, e.g. used for reverting row insert operations
        this.dataLayer.registerCommandHandler(new RowDeleteCommandHandler<>(this.eventList));
        // register the RowObjectDeleteCommandHandler for delete operations
        // by object, e.g. delete by UI interaction
        this.dataLayer.registerCommandHandler(new RowObjectDeleteCommandHandler<>(this.eventList));
        // register the KeyRowInsertCommandHandler to be able to revert key
        // insert operations by firing KeyRowInsertEvents
        // uses an IdIndexKeyHandler with an alternative ListDataProvider on the
        // base list in order to be able to discard the change on the base list
        this.dataLayer.registerCommandHandler(
                new KeyRowInsertCommandHandler<>(
                        this.eventList,
                        new IdIndexKeyHandler<>(new ListDataProvider<>(this.eventList, columnPropertyAccessor), rowIdAccessor)));

        GlazedListsEventLayer<Person> glazedListsEventLayer =
                new GlazedListsEventLayer<>(this.dataLayer, this.filterList);
        glazedListsEventLayer.setTestMode(true);

        this.dataChangeLayer = new DataChangeLayer(glazedListsEventLayer,
                new IdIndexKeyHandler<>(
                        this.dataProvider,
                        rowIdAccessor),
                // configure persistence mode for data changes
                false,
                // enable tracking of row structural changes
                true);

        this.dataChangeLayer.addLayerListener(new ILayerListener() {

            @Override
            public void handleLayerEvent(ILayerEvent event) {
                if (event instanceof RowStructuralRefreshEvent) {
                    RowStructuralDataChangeLayerIntegrationTest.this.lock.countDown();
                }
            }
        });

        for (DataChangeHandler h : this.dataChangeLayer.getDataChangeHandler()) {
            if (h instanceof RowInsertDataChangeHandler) {
                this.insertHandler = (RowInsertDataChangeHandler) h;
            } else if (h instanceof RowDeleteDataChangeHandler) {
                this.deleteHandler = (RowDeleteDataChangeHandler) h;
            }
        }
        assertNotNull("RowInsertDataChangeHandler not found", this.insertHandler);
        assertNotNull("RowDeleteDataChangeHandler not found", this.deleteHandler);

    }

    @After
    public void tearDown() {
        this.dataChangeLayer.doCommand(new DisposeResourcesCommand());
    }

    @Test
    public void shouldUpdateDataInDataLayer() {
        assertEquals("Simpson", this.dataLayer.getDataValue(1, 1));

        this.dataChangeLayer.doCommand(new UpdateDataCommand(this.dataChangeLayer, 1, 1, "Lovejoy"));

        assertEquals("Lovejoy", this.dataLayer.getDataValue(1, 1));
        assertEquals("Lovejoy", this.dataChangeLayer.getDataValueByPosition(1, 1));
        assertTrue("Dirty label not set", this.dataChangeLayer.getConfigLabelsByPosition(1, 1).hasLabel(DataChangeLayer.DIRTY));
        assertTrue("Column 1 is not dirty", this.dataChangeLayer.isColumnDirty(1));
        assertTrue("Row 1 is not dirty", this.dataChangeLayer.isRowDirty(1));
        assertTrue("Cell is not dirty", this.dataChangeLayer.isCellDirty(1, 1));
    }

    @Test
    public void shouldTrackRowInsert() {
        Person ralph = new Person(42, "Ralph", "Wiggum", Gender.MALE, false, new Date());
        this.dataChangeLayer.doCommand(new RowInsertCommand<>(ralph));

        int ralphIndex = this.eventList.indexOf(ralph);
        Object key = this.insertHandler.getKeyHandler().getKey(-1, ralphIndex);

        assertEquals(19, this.eventList.size());

        // row added so all columns are actually dirty
        assertTrue("Column 0 is not dirty", this.dataChangeLayer.isColumnDirty(0));
        assertTrue("Column 1 is not dirty", this.dataChangeLayer.isColumnDirty(1));
        assertTrue("Column 2 is not dirty", this.dataChangeLayer.isColumnDirty(2));
        assertTrue("Column 3 is not dirty", this.dataChangeLayer.isColumnDirty(3));
        assertTrue("Column 4 is not dirty", this.dataChangeLayer.isColumnDirty(4));

        assertTrue("Row " + ralphIndex + " is not dirty", this.dataChangeLayer.isRowDirty(ralphIndex));

        assertTrue("Cell 0/" + ralphIndex + " is not dirty", this.dataChangeLayer.isCellDirty(0, ralphIndex));
        assertTrue("Cell 1/" + ralphIndex + " is not dirty", this.dataChangeLayer.isCellDirty(1, ralphIndex));
        assertTrue("Cell 2/" + ralphIndex + " is not dirty", this.dataChangeLayer.isCellDirty(2, ralphIndex));
        assertTrue("Cell 3/" + ralphIndex + " is not dirty", this.dataChangeLayer.isCellDirty(3, ralphIndex));
        assertTrue("Cell 4/" + ralphIndex + " is not dirty", this.dataChangeLayer.isCellDirty(4, ralphIndex));

        assertTrue("Dirty label not set", this.dataChangeLayer.getConfigLabelsByPosition(0, ralphIndex).hasLabel(DataChangeLayer.DIRTY));
        assertTrue("Dirty label not set", this.dataChangeLayer.getConfigLabelsByPosition(1, ralphIndex).hasLabel(DataChangeLayer.DIRTY));
        assertTrue("Dirty label not set", this.dataChangeLayer.getConfigLabelsByPosition(2, ralphIndex).hasLabel(DataChangeLayer.DIRTY));
        assertTrue("Dirty label not set", this.dataChangeLayer.getConfigLabelsByPosition(3, ralphIndex).hasLabel(DataChangeLayer.DIRTY));
        assertTrue("Dirty label not set", this.dataChangeLayer.getConfigLabelsByPosition(4, ralphIndex).hasLabel(DataChangeLayer.DIRTY));

        assertEquals(1, this.dataChangeLayer.getDataChanges().size());
        assertEquals(1, this.insertHandler.getDataChanges().size());
        // we use the IdIndexKeyHandler so casting is fine
        IdIndexIdentifier<Person> identifier = (IdIndexIdentifier<Person>) this.insertHandler.getDataChanges().get(key).getKey();
        assertEquals(ralph, identifier.rowObject);
        assertEquals(42, identifier.rowId);
    }

    @Test
    public void shouldTrackRowInsertOnSort() {
        Person ralph = new Person(42, "Ralph", "Wiggum", Gender.MALE, false, new Date());
        this.dataChangeLayer.doCommand(new RowInsertCommand<>(ralph));

        assertEquals(18, this.sortedList.indexOf(ralph));
        assertEquals(19, this.sortedList.size());

        // trigger DESC sorting
        this.sortedList.setComparator(Comparator.comparing(Person::getLastName, (p1, p2) -> {
            return p2.compareTo(p1);
        }));

        int ralphIndex = this.sortedList.indexOf(ralph);
        Object key = this.insertHandler.getKeyHandler().getKey(-1, ralphIndex);

        assertEquals(0, ralphIndex);
        assertTrue("Column 0 is not dirty", this.dataChangeLayer.isColumnDirty(0));
        assertTrue("Row " + ralphIndex + " is not dirty", this.dataChangeLayer.isRowDirty(ralphIndex));
        assertTrue("Cell 0/" + ralphIndex + " is not dirty", this.dataChangeLayer.isCellDirty(0, ralphIndex));
        assertTrue("Dirty label not set", this.dataChangeLayer.getConfigLabelsByPosition(0, ralphIndex).hasLabel(DataChangeLayer.DIRTY));

        assertEquals(1, this.dataChangeLayer.getDataChanges().size());
        assertEquals(1, this.insertHandler.getDataChanges().size());
        // we use the IdIndexKeyHandler so casting is fine
        IdIndexIdentifier<Person> identifier = (IdIndexIdentifier<Person>) this.insertHandler.getDataChanges().get(key).getKey();
        assertEquals(ralph, identifier.rowObject);
        assertEquals(42, identifier.rowId);
    }

    @Test
    public void shouldTrackRowInsertInSortedState() {
        assertEquals(18, this.sortedList.size());

        // trigger DESC sorting
        this.sortedList.setComparator(Comparator.comparing(Person::getLastName, (p1, p2) -> {
            return p2.compareTo(p1);
        }));

        // insert while the list is sorted
        Person ralph = new Person(42, "Ralph", "Wiggum", Gender.MALE, false, new Date());
        this.dataChangeLayer.doCommand(new RowInsertCommand<>(ralph));

        assertEquals(19, this.sortedList.size());
        int ralphIndex = this.sortedList.indexOf(ralph);
        Object key = this.insertHandler.getKeyHandler().getKey(-1, ralphIndex);

        assertEquals(0, ralphIndex);
        assertTrue("Column 0 is not dirty", this.dataChangeLayer.isColumnDirty(0));
        assertTrue("Row " + ralphIndex + " is not dirty", this.dataChangeLayer.isRowDirty(ralphIndex));
        assertTrue("Cell 0/" + ralphIndex + " is not dirty", this.dataChangeLayer.isCellDirty(0, ralphIndex));
        assertTrue("Dirty label not set", this.dataChangeLayer.getConfigLabelsByPosition(0, ralphIndex).hasLabel(DataChangeLayer.DIRTY));

        assertEquals(1, this.dataChangeLayer.getDataChanges().size());
        assertEquals(1, this.insertHandler.getDataChanges().size());
        // we use the IdIndexKeyHandler so casting is fine
        IdIndexIdentifier<Person> identifier = (IdIndexIdentifier<Person>) this.insertHandler.getDataChanges().get(key).getKey();
        assertEquals(ralph, identifier.rowObject);
        assertEquals(42, identifier.rowId);
    }

    @Test
    public void shouldDiscardRowInsertInSortedState() {
        Person ralph = new Person(42, "Ralph", "Wiggum", Gender.MALE, false, new Date());
        this.dataChangeLayer.doCommand(new RowInsertCommand<>(ralph));

        assertEquals(18, this.sortedList.indexOf(ralph));
        assertEquals(19, this.sortedList.size());

        // trigger DESC sorting
        this.sortedList.setComparator(Comparator.comparing(Person::getLastName, (p1, p2) -> {
            return p2.compareTo(p1);
        }));

        assertEquals(0, this.sortedList.indexOf(ralph));

        // discard the change
        this.dataChangeLayer.doCommand(new DiscardDataChangesCommand());

        assertEquals(18, this.sortedList.size());

        assertTrue(this.dataChangeLayer.getDataChanges().isEmpty());
        assertTrue(this.insertHandler.getDataChanges().isEmpty());

        // check for states on row 0
        assertFalse("Column 0 is dirty", this.dataChangeLayer.isColumnDirty(0));
        assertFalse("Row 0 is dirty", this.dataChangeLayer.isRowDirty(0));
        assertFalse("Cell 0/0 is dirty", this.dataChangeLayer.isCellDirty(0, 0));
        assertFalse("Dirty label set", this.dataChangeLayer.getConfigLabelsByPosition(0, 0).hasLabel(DataChangeLayer.DIRTY));

        assertFalse("Ralph is still here", this.sortedList.contains(ralph));
    }

    @Test
    public void shouldDiscardRowInsertOnChangeSortedState() {
        // trigger DESC sorting
        this.sortedList.setComparator(Comparator.comparing(Person::getLastName, (p1, p2) -> {
            return p2.compareTo(p1);
        }));

        Person ralph = new Person(42, "Ralph", "Wiggum", Gender.MALE, false, new Date());
        this.dataChangeLayer.doCommand(new RowInsertCommand<>(ralph));

        assertEquals(0, this.sortedList.indexOf(ralph));
        assertEquals(19, this.sortedList.size());

        this.sortedList.setComparator(null);

        assertEquals(18, this.sortedList.indexOf(ralph));

        // discard the change
        this.dataChangeLayer.doCommand(new DiscardDataChangesCommand());

        assertEquals(18, this.sortedList.size());

        assertTrue(this.dataChangeLayer.getDataChanges().isEmpty());
        assertTrue(this.insertHandler.getDataChanges().isEmpty());

        // check that no row is dirty
        for (int row = 0; row < this.sortedList.size(); row++) {
            assertFalse("Row " + row + " is dirty", this.dataChangeLayer.isRowDirty(row));
        }

        assertFalse("Ralph is still here", this.sortedList.contains(ralph));
    }

    @Test
    public void shouldDiscardMultipleRowInsertOnChangeSortedStateAppending() {
        // trigger DESC sorting
        this.sortedList.setComparator(Comparator.comparing(Person::getLastName, (p1, p2) -> {
            return p2.compareTo(p1);
        }));

        Person clancy = new Person(40, "Clancy", "Wiggum", Gender.MALE, true, new Date());
        Person sarah = new Person(41, "Sarah", "Wiggum", Gender.FEMALE, true, new Date());
        Person ralph = new Person(42, "Ralph", "Wiggum", Gender.MALE, false, new Date());
        this.dataChangeLayer.doCommand(new RowInsertCommand<>(this.dataChangeLayer, -1, clancy, sarah, ralph));

        assertEquals(0, this.sortedList.indexOf(clancy));
        assertEquals(1, this.sortedList.indexOf(sarah));
        assertEquals(2, this.sortedList.indexOf(ralph));
        assertEquals(21, this.sortedList.size());

        this.sortedList.setComparator(null);

        assertEquals(18, this.sortedList.indexOf(clancy));
        assertEquals(19, this.sortedList.indexOf(sarah));
        assertEquals(20, this.sortedList.indexOf(ralph));

        assertTrue("Row 18 is not dirty", this.dataChangeLayer.isRowDirty(18));
        assertTrue("Row 19 is not dirty", this.dataChangeLayer.isRowDirty(19));
        assertTrue("Row 20 is not dirty", this.dataChangeLayer.isRowDirty(20));

        // discard the change
        this.dataChangeLayer.doCommand(new DiscardDataChangesCommand());

        assertEquals(18, this.sortedList.size());

        assertTrue(this.dataChangeLayer.getDataChanges().isEmpty());
        assertTrue(this.insertHandler.getDataChanges().isEmpty());

        // check that no row is dirty
        for (int row = 0; row < this.sortedList.size(); row++) {
            assertFalse("Row " + row + " is dirty", this.dataChangeLayer.isRowDirty(row));
        }

        assertFalse("Clancy is still here", this.sortedList.contains(clancy));
        assertFalse("Sarah is still here", this.sortedList.contains(sarah));
        assertFalse("Ralph is still here", this.sortedList.contains(ralph));
    }

    @Test
    public void shouldDiscardMultipleRowInsertOnChangeSortedState() {
        // trigger DESC sorting
        this.sortedList.setComparator(Comparator.comparing(Person::getLastName, (p1, p2) -> {
            return p2.compareTo(p1);
        }));

        Person clancy = new Person(40, "Clancy", "Wiggum", Gender.MALE, true, new Date());
        Person sarah = new Person(41, "Sarah", "Wiggum", Gender.FEMALE, true, new Date());
        Person ralph = new Person(42, "Ralph", "Wiggum", Gender.MALE, false, new Date());
        this.dataChangeLayer.doCommand(new RowInsertCommand<>(this.dataChangeLayer, 10, clancy, sarah, ralph));

        assertEquals(0, this.sortedList.indexOf(clancy));
        assertEquals(1, this.sortedList.indexOf(sarah));
        assertEquals(2, this.sortedList.indexOf(ralph));
        assertEquals(21, this.sortedList.size());

        this.sortedList.setComparator(null);

        assertEquals(10, this.sortedList.indexOf(clancy));
        assertEquals(11, this.sortedList.indexOf(sarah));
        assertEquals(12, this.sortedList.indexOf(ralph));

        assertTrue("Row 10 is not dirty", this.dataChangeLayer.isRowDirty(10));
        assertTrue("Row 11 is not dirty", this.dataChangeLayer.isRowDirty(11));
        assertTrue("Row 12 is not dirty", this.dataChangeLayer.isRowDirty(12));

        // discard the change
        this.dataChangeLayer.doCommand(new DiscardDataChangesCommand());

        assertEquals(18, this.sortedList.size());

        assertTrue(this.dataChangeLayer.getDataChanges().isEmpty());
        assertTrue(this.insertHandler.getDataChanges().isEmpty());

        // check that no row is dirty
        for (int row = 0; row < this.sortedList.size(); row++) {
            assertFalse("Row " + row + " is dirty", this.dataChangeLayer.isRowDirty(row));
        }

        assertFalse("Clancy is still here", this.sortedList.contains(clancy));
        assertFalse("Sarah is still here", this.sortedList.contains(sarah));
        assertFalse("Ralph is still here", this.sortedList.contains(ralph));
    }

    @Test
    public void shouldKeepChangeOnFilter() throws InterruptedException {
        this.dataChangeLayer.doCommand(new UpdateDataCommand(this.dataChangeLayer, 1, 1, "Lovejoy"));

        this.filterList.setMatcher(new Matcher<Person>() {

            @Override
            public boolean matches(Person item) {
                return item.getLastName().equals("Simpson");
            }
        });

        // give the GlazedListsEventLayer some time to trigger the
        // RowStructuralRefreshEvent
        boolean completed = this.lock.await(1000, TimeUnit.MILLISECONDS);

        assertTrue("Timeout - no event received", completed);

        assertEquals(9, this.filterList.size());
        assertFalse(this.dataChangeLayer.getDataChanges().isEmpty());
        assertFalse("Column 1 is dirty", this.dataChangeLayer.isColumnDirty(1));

        this.lock = new CountDownLatch(1);
        this.filterList.setMatcher(null);

        // give the GlazedListsEventLayer some time to trigger the
        // RowStructuralRefreshEvent
        completed = this.lock.await(1000, TimeUnit.MILLISECONDS);

        assertTrue("Timeout - no event received", completed);

        assertEquals(18, this.filterList.size());
        assertFalse(this.dataChangeLayer.getDataChanges().isEmpty());
        assertTrue("Column 1 is not dirty", this.dataChangeLayer.isColumnDirty(1));
    }

    @Test
    public void shouldNotThrowAnExceptionOnResize() throws InterruptedException {
        this.dataChangeLayer.doCommand(new UpdateDataCommand(this.dataChangeLayer, 1, 1, "Lovejoy"));

        this.filterList.setMatcher(new Matcher<Person>() {

            @Override
            public boolean matches(Person item) {
                return item.getLastName().equals("Simpson");
            }
        });

        this.dataLayer.setColumnWidthByPosition(2, 75);

        assertEquals(9, this.filterList.size());
        assertFalse(this.dataChangeLayer.getDataChanges().isEmpty());
        assertFalse("Column 1 is dirty", this.dataChangeLayer.isColumnDirty(1));

        this.filterList.setMatcher(null);

        // give the GlazedListsEventLayer some time to trigger the
        // RowStructuralRefreshEvent
        boolean completed = this.lock.await(1000, TimeUnit.MILLISECONDS);

        assertTrue("Timeout - no event received", completed);

        assertEquals(18, this.filterList.size());
        assertFalse(this.dataChangeLayer.getDataChanges().isEmpty());
        assertTrue("Column 1 is not dirty", this.dataChangeLayer.isColumnDirty(1));
    }
}
