/*******************************************************************************
 * Copyright (c) 2013, 2020 Dirk Fauth and others.
 *
 * 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.reorder;

import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Properties;
import java.util.StringTokenizer;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.collections.api.list.primitive.MutableIntList;
import org.eclipse.collections.api.map.primitive.MutableIntIntMap;
import org.eclipse.collections.impl.factory.primitive.IntIntMaps;
import org.eclipse.collections.impl.factory.primitive.IntLists;
import org.eclipse.nebula.widgets.nattable.command.ILayerCommand;
import org.eclipse.nebula.widgets.nattable.coordinate.PositionUtil;
import org.eclipse.nebula.widgets.nattable.coordinate.Range;
import org.eclipse.nebula.widgets.nattable.layer.AbstractLayerTransform;
import org.eclipse.nebula.widgets.nattable.layer.ILayer;
import org.eclipse.nebula.widgets.nattable.layer.IUniqueIndexLayer;
import org.eclipse.nebula.widgets.nattable.layer.LayerUtil;
import org.eclipse.nebula.widgets.nattable.layer.command.ConfigureScalingCommand;
import org.eclipse.nebula.widgets.nattable.layer.event.ILayerEvent;
import org.eclipse.nebula.widgets.nattable.layer.event.IStructuralChangeEvent;
import org.eclipse.nebula.widgets.nattable.layer.event.RowStructuralRefreshEvent;
import org.eclipse.nebula.widgets.nattable.layer.event.StructuralChangeEventHelper;
import org.eclipse.nebula.widgets.nattable.layer.event.StructuralDiff;
import org.eclipse.nebula.widgets.nattable.persistence.IPersistable;
import org.eclipse.nebula.widgets.nattable.reorder.command.MultiRowReorderCommandHandler;
import org.eclipse.nebula.widgets.nattable.reorder.command.ResetRowReorderCommandHandler;
import org.eclipse.nebula.widgets.nattable.reorder.command.RowReorderCommandHandler;
import org.eclipse.nebula.widgets.nattable.reorder.command.RowReorderEndCommandHandler;
import org.eclipse.nebula.widgets.nattable.reorder.command.RowReorderStartCommandHandler;
import org.eclipse.nebula.widgets.nattable.reorder.config.DefaultRowReorderLayerConfiguration;
import org.eclipse.nebula.widgets.nattable.reorder.event.RowReorderEvent;
import org.eclipse.nebula.widgets.nattable.util.ArrayUtil;

/**
 * Layer that is used to add the functionality for row reordering.
 *
 * @see DefaultRowReorderLayerConfiguration
 */
public class RowReorderLayer extends AbstractLayerTransform implements IUniqueIndexLayer {

    private static final Log LOG = LogFactory.getLog(RowReorderLayer.class);

    public static final String PERSISTENCE_KEY_ROW_INDEX_ORDER = ".rowIndexOrder"; //$NON-NLS-1$

    private final IUniqueIndexLayer underlying;

    /**
     * The local cache of the row index order. Used to track the reordering
     * performed by this layer. Position Y in the List contains the index of row
     * at position Y.
     */
    protected final MutableIntList rowIndexOrder = IntLists.mutable.empty();

    /**
     * The internal mapping of index to position values. Used for performance
     * reasons in {@link #getColumnPositionByIndex(int)} because
     * {@link List#indexOf(Object)} doesn't scale well.
     *
     * @since 1.5
     */
    protected final MutableIntIntMap indexPositionMapping = IntIntMaps.mutable.empty();

    /**
     * Caching of the starting y positions of the rows. Used to reduce
     * calculation time on rendering
     */
    private final MutableIntIntMap startYCache = IntIntMaps.mutable.empty();

    /**
     * Local cached position of the row that is currently reordered.
     */
    private int reorderFromRowPosition;

    /**
     * Creates a {@link RowReorderLayer} on top of the given
     * {@link IUniqueIndexLayer} and adds the
     * {@link DefaultRowReorderLayerConfiguration}.
     *
     * @param underlyingLayer
     *            The underlying layer.
     */
    public RowReorderLayer(IUniqueIndexLayer underlyingLayer) {
        this(underlyingLayer, true);
    }

    /**
     * Creates a {@link RowReorderLayer} on top of the given
     * {@link IUniqueIndexLayer}.
     *
     * @param underlyingLayer
     *            The underlying layer.
     * @param useDefaultConfiguration
     *            <code>true</code> to add the
     *            {@link DefaultRowReorderLayerConfiguration}
     */
    public RowReorderLayer(IUniqueIndexLayer underlyingLayer, boolean useDefaultConfiguration) {
        super(underlyingLayer);
        this.underlying = underlyingLayer;

        populateIndexOrder();

        registerCommandHandlers();

        if (useDefaultConfiguration) {
            addConfiguration(new DefaultRowReorderLayerConfiguration());
        }
    }

    @Override
    public void handleLayerEvent(ILayerEvent event) {
        if (event instanceof IStructuralChangeEvent) {
            IStructuralChangeEvent structuralChangeEvent = (IStructuralChangeEvent) event;
            if (structuralChangeEvent.isVerticalStructureChanged()) {
                Collection<StructuralDiff> structuralDiffs = structuralChangeEvent.getRowDiffs();
                if (structuralDiffs == null) {
                    // Assume everything changed
                    populateIndexOrder();
                } else {
                    // only react on ADD or DELETE and not on CHANGE
                    StructuralChangeEventHelper.handleRowDelete(
                            structuralDiffs, this.underlying, this.rowIndexOrder, true);
                    StructuralChangeEventHelper.handleRowInsert(
                            structuralDiffs, this.underlying, this.rowIndexOrder, true);
                    // update index-position mapping
                    refreshIndexPositionMapping();
                }
                invalidateCache();
            }
        }
        super.handleLayerEvent(event);
    }

    @Override
    public boolean doCommand(ILayerCommand command) {
        if (command instanceof ConfigureScalingCommand) {
            // if we change the scaling, the cached start coordinates become
            // invalid
            invalidateCache();
        }
        return super.doCommand(command);
    }

    // Configuration

    @Override
    protected void registerCommandHandlers() {
        registerCommandHandler(new RowReorderCommandHandler(this));
        registerCommandHandler(new RowReorderStartCommandHandler(this));
        registerCommandHandler(new RowReorderEndCommandHandler(this));
        registerCommandHandler(new MultiRowReorderCommandHandler(this));
        registerCommandHandler(new ResetRowReorderCommandHandler(this));
    }

    // Persistence

    @Override
    public void saveState(String prefix, Properties properties) {
        super.saveState(prefix, properties);
        if (this.rowIndexOrder.size() > 0) {
            properties.setProperty(
                    prefix + PERSISTENCE_KEY_ROW_INDEX_ORDER,
                    this.rowIndexOrder.makeString(IPersistable.VALUE_SEPARATOR));
        }
    }

    @Override
    public void loadState(String prefix, Properties properties) {
        super.loadState(prefix, properties);
        String property = properties.getProperty(prefix + PERSISTENCE_KEY_ROW_INDEX_ORDER);

        if (property != null) {
            MutableIntList newRowIndexOrder = IntLists.mutable.empty();
            StringTokenizer tok = new StringTokenizer(property, IPersistable.VALUE_SEPARATOR);
            while (tok.hasMoreTokens()) {
                String index = tok.nextToken();
                newRowIndexOrder.add(Integer.parseInt(index));
            }

            if (isRestoredStateValid(newRowIndexOrder.toArray())) {
                this.rowIndexOrder.clear();
                this.rowIndexOrder.addAll(newRowIndexOrder);
                // refresh index-position mapping
                refreshIndexPositionMapping();
            }

        }
        invalidateCache();
        fireLayerEvent(new RowStructuralRefreshEvent(this));
    }

    /**
     * Ensure that rows haven't changed in the underlying data source
     *
     * @param newRowIndexOrder
     *            restored from the properties file.
     * @since 2.0
     */
    protected boolean isRestoredStateValid(int[] newRowIndexOrder) {
        if (newRowIndexOrder.length != getRowCount()) {
            LOG.error("Number of persisted rows (" + newRowIndexOrder.length + ") " + //$NON-NLS-1$ //$NON-NLS-2$
                    "is not the same as the number of rows in the data source (" //$NON-NLS-1$
                    + getRowCount() + ").\n" + //$NON-NLS-1$
                    "Skipping restore of row ordering"); //$NON-NLS-1$
            return false;
        }

        for (int index : newRowIndexOrder) {
            if (!this.indexPositionMapping.containsKey(index)) {
                LOG.error("Row index: " + index + " being restored, is not a available in the data soure.\n" + //$NON-NLS-1$ //$NON-NLS-2$
                        "Skipping restore of row ordering"); //$NON-NLS-1$
                return false;
            }
        }
        return true;
    }

    // Columns

    @Override
    public int getColumnPositionByIndex(int columnIndex) {
        return this.underlying.getColumnPositionByIndex(columnIndex);
    }

    // Y

    @Override
    public int getRowPositionByY(int y) {
        return LayerUtil.getRowPositionByY(this, y);
    }

    @Override
    public int getStartYOfRowPosition(int targetRowPosition) {
        int cachedStartY = this.startYCache.getIfAbsent(targetRowPosition, -1);
        if (cachedStartY != -1) {
            return cachedStartY;
        }

        int aggregateWidth = 0;
        for (int rowPosition = 0; rowPosition < targetRowPosition; rowPosition++) {
            aggregateWidth += this.underlying.getRowHeightByPosition(localToUnderlyingRowPosition(rowPosition));
        }

        this.startYCache.put(targetRowPosition, aggregateWidth);
        return aggregateWidth;
    }

    /**
     * Initially populate the index order to the local cache.
     *
     * @since 1.6
     */
    protected void populateIndexOrder() {
        this.rowIndexOrder.clear();
        ILayer underlyingLayer = getUnderlyingLayer();
        for (int rowPosition = 0; rowPosition < underlyingLayer.getRowCount(); rowPosition++) {
            int index = underlyingLayer.getRowIndexByPosition(rowPosition);
            this.rowIndexOrder.add(index);
            this.indexPositionMapping.put(index, rowPosition);
        }
    }

    /**
     * Initializes the internal index-position-mapping to reflect the internal
     * row-index-order.
     *
     * @since 1.6
     */
    protected void refreshIndexPositionMapping() {
        this.indexPositionMapping.clear();
        for (int position = 0; position < this.rowIndexOrder.size(); position++) {
            int index = this.rowIndexOrder.get(position);
            this.indexPositionMapping.put(index, position);
        }
    }

    // Vertical features

    // Rows
    /**
     * @return The local cache of the row index order.
     */
    public List<Integer> getRowIndexOrder() {
        return ArrayUtil.asIntegerList(this.rowIndexOrder.toArray());
    }

    /**
     * @return The local cache of the row index order.
     * @since 2.0
     */
    public int[] getRowIndexOrderArray() {
        return this.rowIndexOrder.toArray();
    }

    @Override
    public int getRowIndexByPosition(int rowPosition) {
        if (rowPosition >= 0 && rowPosition < this.rowIndexOrder.size()) {
            return this.rowIndexOrder.get(rowPosition);
        } else {
            return -1;
        }
    }

    @Override
    public int getRowPositionByIndex(int rowIndex) {
        return this.indexPositionMapping.getIfAbsent(rowIndex, -1);
    }

    @Override
    public int localToUnderlyingRowPosition(int localRowPosition) {
        int rowIndex = getRowIndexByPosition(localRowPosition);
        return this.underlying.getRowPositionByIndex(rowIndex);
    }

    @Override
    public int underlyingToLocalRowPosition(ILayer sourceUnderlyingLayer, int underlyingRowPosition) {
        int rowIndex = this.underlying.getRowIndexByPosition(underlyingRowPosition);
        return getRowPositionByIndex(rowIndex);
    }

    @Override
    public Collection<Range> underlyingToLocalRowPositions(ILayer sourceUnderlyingLayer, Collection<Range> underlyingRowPositionRanges) {
        MutableIntList reorderedRowPositions = IntLists.mutable.empty();
        for (Range underlyingRowPositionRange : underlyingRowPositionRanges) {
            for (int underlyingRowPosition = underlyingRowPositionRange.start; underlyingRowPosition < underlyingRowPositionRange.end; underlyingRowPosition++) {
                int localRowPosition = underlyingToLocalRowPosition(sourceUnderlyingLayer, underlyingRowPositionRange.start);
                reorderedRowPositions.add(localRowPosition);
            }
        }

        return PositionUtil.getRanges(reorderedRowPositions.toSortedArray());
    }

    /**
     * Moves the row at the given from position to the <i>TOP</i> of the of the
     * given to position. This is the internal implementation for reordering a
     * row.
     *
     * @param fromRowPosition
     *            row position to move
     * @param toRowPosition
     *            position to move the row to
     * @param reorderToTopEdge
     *            whether the move should be done above the given to position or
     *            not
     */
    private void moveRow(int fromRowPosition, int toRowPosition, boolean reorderToTopEdge) {
        if (!reorderToTopEdge) {
            toRowPosition++;
        }

        int fromRowIndex = this.rowIndexOrder.get(fromRowPosition);
        this.rowIndexOrder.addAtIndex(toRowPosition, fromRowIndex);
        this.rowIndexOrder.removeAtIndex(fromRowPosition + (fromRowPosition > toRowPosition ? 1 : 0));

        // update index-position mapping
        refreshIndexPositionMapping();

        invalidateCache();
    }

    /**
     * Reorders the row at the given from position to the <i>TOP</i> of the of
     * the given to position. Will calculate whether the move is done above the
     * to position or not regarding the position in the NatTable.
     *
     * @param fromRowPosition
     *            row position to move
     * @param toRowPosition
     *            position to move the row to
     */
    public void reorderRowPosition(int fromRowPosition, int toRowPosition) {
        boolean reorderToTopEdge;
        if (toRowPosition < getRowCount()) {
            reorderToTopEdge = true;
        } else {
            reorderToTopEdge = false;
            toRowPosition--;
        }
        reorderRowPosition(fromRowPosition, toRowPosition, reorderToTopEdge);
    }

    /**
     * Reorders the row at the given from position to the <i>TOP</i> of the of
     * the given to position.
     *
     * @param fromRowPosition
     *            row position to move
     * @param toRowPosition
     *            position to move the row to
     * @param reorderToTopEdge
     *            whether the move should be done above the given to position or
     *            not
     */
    public void reorderRowPosition(int fromRowPosition, int toRowPosition, boolean reorderToTopEdge) {
        // get the indexes before the move operation
        int fromRowIndex = getRowIndexByPosition(fromRowPosition);
        int toRowIndex = getRowIndexByPosition(toRowPosition);
        moveRow(fromRowPosition, toRowPosition, reorderToTopEdge);
        fireLayerEvent(new RowReorderEvent(this, fromRowPosition, fromRowIndex, toRowPosition, toRowIndex, reorderToTopEdge));
    }

    /**
     * Reorders the rows at the given from positions to the <i>TOP</i> of the of
     * the given to position. Will calculate whether the move is done above the
     * to position or not regarding the position in the NatTable.
     *
     * @param fromRowPositions
     *            row positions to move
     * @param toRowPosition
     *            position to move the rows to
     */
    public void reorderMultipleRowPositions(List<Integer> fromRowPositions, int toRowPosition) {
        reorderMultipleRowPositions(
                fromRowPositions.stream().mapToInt(Integer::intValue).toArray(),
                toRowPosition);
    }

    /**
     * Reorders the rows at the given from positions to the <i>TOP</i> of the of
     * the given to position. Will calculate whether the move is done above the
     * to position or not regarding the position in the NatTable.
     *
     * @param fromRowPositions
     *            row positions to move
     * @param toRowPosition
     *            position to move the rows to
     * @since 2.0
     */
    public void reorderMultipleRowPositions(int[] fromRowPositions, int toRowPosition) {
        boolean reorderToTopEdge;
        if (toRowPosition < getRowCount()) {
            reorderToTopEdge = true;
        } else {
            reorderToTopEdge = false;
            toRowPosition--;
        }
        reorderMultipleRowPositions(fromRowPositions, toRowPosition, reorderToTopEdge);
    }

    /**
     * Reorders the rows at the given from positions to the <i>TOP</i> of the of
     * the given to position.
     *
     * @param fromRowPositions
     *            row positions to move
     * @param toRowPosition
     *            position to move the rows to
     * @param reorderToTopEdge
     *            whether the move should be done above the given to position or
     *            not
     */
    public void reorderMultipleRowPositions(List<Integer> fromRowPositions, int toRowPosition, boolean reorderToTopEdge) {
        reorderMultipleRowPositions(
                fromRowPositions.stream().mapToInt(Integer::intValue).toArray(),
                toRowPosition,
                reorderToTopEdge);
    }

    /**
     * Reorders the rows at the given from positions to the <i>TOP</i> of the of
     * the given to position.
     *
     * @param fromRowPositions
     *            row positions to move
     * @param toRowPosition
     *            position to move the rows to
     * @param reorderToTopEdge
     *            whether the move should be done above the given to position or
     *            not
     * @since 2.0
     */
    public void reorderMultipleRowPositions(int[] fromRowPositions, int toRowPosition, boolean reorderToTopEdge) {
        // the position collection needs to be sorted so the move works
        // correctly
        Arrays.sort(fromRowPositions);

        // get the indexes before the move operation
        int[] fromRowIndexes = Arrays.stream(fromRowPositions).map(this::getRowIndexByPosition).toArray();
        int toRowIndex = getRowIndexByPosition(toRowPosition);

        final int fromRowPositionsCount = fromRowPositions.length;

        if (toRowPosition > fromRowPositions[fromRowPositionsCount - 1]) {
            // Moving from top to bottom
            int firstRowPosition = fromRowPositions[0];

            int moved = 0;
            for (int rowCount = 0; rowCount < fromRowPositionsCount; rowCount++) {
                final int fromRowPosition = fromRowPositions[rowCount] - moved;
                moveRow(fromRowPosition, toRowPosition, reorderToTopEdge);
                moved++;
                if (fromRowPosition < firstRowPosition) {
                    firstRowPosition = fromRowPosition;
                }
            }
        } else if (toRowPosition < fromRowPositions[fromRowPositionsCount - 1]) {
            // Moving from bottom to top
            int targetRowPosition = toRowPosition;
            for (int fromRowPosition : fromRowPositions) {
                final int fromRowPositionInt = fromRowPosition;
                moveRow(fromRowPositionInt, targetRowPosition++, reorderToTopEdge);
            }
        }

        fireLayerEvent(new RowReorderEvent(this, fromRowPositions, fromRowIndexes, toRowPosition, toRowIndex, reorderToTopEdge));
    }

    /**
     * Reorders the given from-rows identified by index to the specified edge of
     * the row to move to and fires a {@link RowReorderEvent}. This method can
     * be used to reorder rows that are hidden in a higher level, e.g. to
     * reorder a row group that has hidden rows.
     *
     * @param fromRowIndexes
     *            row indexes to move
     * @param toRowPosition
     *            position to move the rows to
     * @param reorderToTopEdge
     *            whether the move should be done above the given to position or
     *            not
     *
     * @since 1.6
     */
    public void reorderMultipleRowIndexes(List<Integer> fromRowIndexes, int toRowPosition, boolean reorderToTopEdge) {
        reorderMultipleRowIndexes(
                fromRowIndexes.stream().mapToInt(Integer::intValue).toArray(),
                toRowPosition,
                reorderToTopEdge);
    }

    /**
     * Reorders the given from-rows identified by index to the specified edge of
     * the row to move to and fires a {@link RowReorderEvent}. This method can
     * be used to reorder rows that are hidden in a higher level, e.g. to
     * reorder a row group that has hidden rows.
     *
     * @param fromRowIndexes
     *            row indexes to move
     * @param toRowPosition
     *            position to move the rows to
     * @param reorderToTopEdge
     *            whether the move should be done above the given to position or
     *            not
     *
     * @since 2.0
     */
    public void reorderMultipleRowIndexes(int[] fromRowIndexes, int toRowPosition, boolean reorderToTopEdge) {
        // calculate positions from indexes
        int[] fromRowPositions = Arrays.stream(fromRowIndexes).map(this::getRowPositionByIndex).toArray();
        reorderMultipleRowPositions(fromRowPositions, toRowPosition, reorderToTopEdge);
    }

    /**
     * Clear the caching of the starting Y positions
     *
     * @since 1.6
     */
    protected void invalidateCache() {
        this.startYCache.clear();
    }

    /**
     * @return Local cached position of the row that is currently reordered.
     */
    public int getReorderFromRowPosition() {
        return this.reorderFromRowPosition;
    }

    /**
     * Locally cache the position of the row that is currently reordered.
     *
     * @param fromRowPosition
     *            Position of the row that is currently reordered.
     */
    public void setReorderFromRowPosition(int fromRowPosition) {
        this.reorderFromRowPosition = fromRowPosition;
    }

    /**
     * Resets the reordering tracked by this layer.
     *
     * @since 1.6
     */
    public void resetReorder() {
        populateIndexOrder();
        invalidateCache();
        fireLayerEvent(new RowStructuralRefreshEvent(this));
    }

}
