/*******************************************************************************
 * Copyright (c) 2019, 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.group.performance.command;

import java.util.HashMap;
import java.util.HashSet;

import org.eclipse.collections.api.iterator.MutableIntIterator;
import org.eclipse.collections.api.list.primitive.MutableIntList;
import org.eclipse.collections.impl.factory.primitive.IntLists;
import org.eclipse.nebula.widgets.nattable.Messages;
import org.eclipse.nebula.widgets.nattable.command.AbstractLayerCommandHandler;
import org.eclipse.nebula.widgets.nattable.group.command.CreateRowGroupCommand;
import org.eclipse.nebula.widgets.nattable.group.command.DisplayRowGroupRenameDialogCommand;
import org.eclipse.nebula.widgets.nattable.group.command.IRowGroupCommand;
import org.eclipse.nebula.widgets.nattable.group.command.RemoveRowGroupCommand;
import org.eclipse.nebula.widgets.nattable.group.command.UngroupRowCommand;
import org.eclipse.nebula.widgets.nattable.group.event.GroupRowsEvent;
import org.eclipse.nebula.widgets.nattable.group.event.UngroupRowsEvent;
import org.eclipse.nebula.widgets.nattable.group.performance.GroupModel;
import org.eclipse.nebula.widgets.nattable.group.performance.GroupModel.Group;
import org.eclipse.nebula.widgets.nattable.group.performance.RowGroupHeaderLayer;
import org.eclipse.nebula.widgets.nattable.layer.LayerUtil;
import org.eclipse.nebula.widgets.nattable.layer.event.VisualRefreshEvent;
import org.eclipse.nebula.widgets.nattable.reorder.command.MultiRowReorderCommand;
import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
import org.eclipse.nebula.widgets.nattable.ui.rename.HeaderRenameDialog;
import org.eclipse.nebula.widgets.nattable.ui.rename.HeaderRenameDialog.RenameDialogLabels;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.MessageBox;

/**
 * Command handler for handling {@link IRowGroupCommand}s to create, remove and
 * rename row groups.
 *
 * @since 1.6
 */
public class RowGroupsCommandHandler extends AbstractLayerCommandHandler<IRowGroupCommand> {

    private final RowGroupHeaderLayer contextLayer;
    private final SelectionLayer selectionLayer;

    public RowGroupsCommandHandler(RowGroupHeaderLayer contextLayer, SelectionLayer selectionLayer) {
        this.contextLayer = contextLayer;
        this.selectionLayer = selectionLayer;
    }

    @Override
    public boolean doCommand(IRowGroupCommand command) {
        if (command instanceof CreateRowGroupCommand) {
            CreateRowGroupCommand createCommand = ((CreateRowGroupCommand) command);
            if (!handleCreateRowGroupCommand(createCommand.getRowGroupName())) {
                MessageBox messageBox = new MessageBox(Display.getDefault().getActiveShell(), SWT.INHERIT_DEFAULT | SWT.ICON_ERROR | SWT.OK);
                messageBox.setText(Messages.getString("ErrorDialog.title")); //$NON-NLS-1$
                messageBox.setMessage(Messages.getString("RowGroups.selectNonGroupedRows")); //$NON-NLS-1$
                messageBox.open();
            }
            return true;
        } else if (command instanceof RemoveRowGroupCommand) {
            RemoveRowGroupCommand removeRowGroupCommand = (RemoveRowGroupCommand) command;
            int rowIndex = removeRowGroupCommand.getRowIndex();
            handleRemoveRowGroupCommand(rowIndex);
            return true;
        } else if (command instanceof UngroupRowCommand) {
            handleUngroupCommand();
            return true;
        } else if (command instanceof DisplayRowGroupRenameDialogCommand) {
            return displayRowGroupRenameDialog((DisplayRowGroupRenameDialogCommand) command);
        }
        return false;
    }

    /**
     * Creates a new row group with the given name out of the currently fully
     * selected row positions. If a selected row is part of an existing group,
     * the existing group will be removed and all rows belonging to that group
     * will be also part of the new group.
     *
     * @param rowGroupName
     *            The name of the new row group.
     * @return <code>true</code> if the row group could be created,
     *         <code>false</code> if there are no rows fully selected.
     */
    protected boolean handleCreateRowGroupCommand(String rowGroupName) {
        int[] fullySelectedRows = this.selectionLayer.getFullySelectedRowPositions();

        // we operate on the GroupModel directly to avoid the position
        // transformation
        GroupModel model = this.contextLayer.getGroupModel();

        MutableIntList positionsToGroup = IntLists.mutable.empty();
        if (fullySelectedRows != null && fullySelectedRows.length > 0) {
            for (int row : fullySelectedRows) {
                // convert to position layer
                // needed because the group model takes the positions based on
                // the position layer
                int converted = LayerUtil.convertRowPosition(this.selectionLayer, row, this.contextLayer.getPositionLayer());
                if (converted > -1) {
                    positionsToGroup.add(converted);
                }
            }

            HashSet<Group> existingGroups = new HashSet<Group>();
            for (MutableIntIterator it = positionsToGroup.intIterator(); it.hasNext();) {
                int row = it.next();
                Group group = model.getGroupByPosition(row);
                if (group != null) {
                    if (!group.isUnbreakable()) {
                        existingGroups.add(group);
                    } else {
                        // if a position of an unbreakable group was found, we
                        // ignore that position
                        it.remove();
                    }
                }
            }

            if (!existingGroups.isEmpty()) {
                // expand those groups
                this.contextLayer.doCommand(new RowGroupExpandCommand(model, existingGroups));
                // get all positions from the other groups
                for (Group group : existingGroups) {
                    positionsToGroup.addAll(group.getVisiblePositions());
                    // remove existing group and create a new one
                    this.contextLayer.removeGroup(group);
                }
            }

            positionsToGroup.sortThis();
            MutableIntList selectedPositions = IntLists.mutable.ofAll(positionsToGroup.distinct());

            if (selectedPositions.size() > 1) {
                // if a group is created for more than one row, reorder so
                // the positions are consecutive which is necessary for grouping
                this.selectionLayer.doCommand(
                        new MultiRowReorderCommand(this.selectionLayer, selectedPositions.toArray(), selectedPositions.get(0)));
            }

            // create the row group
            this.contextLayer.addGroup(rowGroupName, this.selectionLayer.getRowIndexByPosition(selectedPositions.get(0)), selectedPositions.size());

            this.selectionLayer.clear();

            this.contextLayer.fireLayerEvent(new GroupRowsEvent(this.contextLayer));

            return true;
        }
        return false;
    }

    /**
     * Remove the row group at the given row index.
     *
     * @param rowIndex
     *            The row index to retrieve the row group to remove.
     */
    protected void handleRemoveRowGroupCommand(int rowIndex) {
        int selectedPosition = this.selectionLayer.getRowPositionByIndex(rowIndex);
        int converted = LayerUtil.convertRowPosition(this.selectionLayer, selectedPosition, this.contextLayer.getPositionLayer());
        GroupModel model = this.contextLayer.getGroupModel();
        Group group = model.getGroupByPosition(converted);
        if (group != null && !group.isUnbreakable()) {
            if (group.isCollapsed()) {
                this.contextLayer.doCommand(new RowGroupExpandCommand(model, group));
            }
            model.removeGroup(group);

            this.contextLayer.fireLayerEvent(new GroupRowsEvent(this.contextLayer));
        }
    }

    /**
     * Remove the currently fully selected rows from their corresponding groups.
     * Will also trigger a reorder to ensure a consistent group rendering
     */
    protected void handleUngroupCommand() {
        // Grab fully selected row positions
        int[] fullySelectedRows = this.selectionLayer.getFullySelectedRowPositions();

        if (fullySelectedRows != null && fullySelectedRows.length > 0) {
            MutableIntList positionsToUngroup = IntLists.mutable.empty();
            for (int row : fullySelectedRows) {
                // convert to position layer
                // needed because the group model takes the positions based on
                // the position layer
                int converted = LayerUtil.convertRowPosition(this.selectionLayer, row, this.contextLayer.getPositionLayer());
                if (converted > -1) {
                    positionsToUngroup.add(converted);
                }
            }

            // we operate on the GroupModel directly to avoid the position
            // transformation
            GroupModel model = this.contextLayer.getGroupModel();
            HashMap<Group, MutableIntList> toRemove = new HashMap<>();
            positionsToUngroup.forEach(pos -> {
                Group group = model.getGroupByPosition(pos);
                if (group != null) {
                    int endPos = group.getVisibleStartPosition() + group.getVisibleSpan();
                    if (pos < endPos && !group.isGroupStart(pos)) {
                        // remember position to remove
                        MutableIntList remove = toRemove.get(group);
                        if (remove == null) {
                            remove = IntLists.mutable.empty();
                            toRemove.put(group, remove);
                        }
                        remove.add(pos);
                    } else {
                        model.removePositionsFromGroup(group, pos);
                    }
                }
            });

            if (!toRemove.isEmpty()) {
                toRemove.entrySet().forEach(entry -> {
                    Group group = entry.getKey();
                    int endPos = group.getVisibleStartPosition() + group.getVisibleSpan();

                    this.selectionLayer.doCommand(new MultiRowReorderCommand(this.selectionLayer, entry.getValue().toArray(), endPos));

                    MutableIntList value = entry.getValue();
                    int start = endPos - value.size();
                    int[] positionsToRemove = new int[value.size()];
                    for (int i = 0; i < entry.getValue().size(); i++) {
                        positionsToRemove[i] = start + i;
                    }

                    model.removePositionsFromGroup(group, positionsToRemove);
                });
            }

            this.selectionLayer.clear();

            this.contextLayer.fireLayerEvent(new UngroupRowsEvent(this.contextLayer));
        }
    }

    // TODO NatTable 2.0 - Dialog should not be opened by the command handler
    protected boolean displayRowGroupRenameDialog(DisplayRowGroupRenameDialogCommand command) {
        int rowPosition = command.getRowPosition();

        HeaderRenameDialog dialog = new HeaderRenameDialog(Display.getDefault().getActiveShell(), null, null, RenameDialogLabels.ROW_RENAME);
        Rectangle rowHeaderBounds = this.contextLayer.getBoundsByPosition(rowPosition, 0);
        Point point = new Point(rowHeaderBounds.x, rowHeaderBounds.y + rowHeaderBounds.height);
        dialog.setLocation(command.toDisplayCoordinates(point));
        dialog.open();

        if (!dialog.isCancelPressed()) {
            Group rowGroup = this.contextLayer.getGroupByPosition(rowPosition);
            rowGroup.setName(dialog.getNewLabel());
            this.contextLayer.fireLayerEvent(new VisualRefreshEvent(this.contextLayer));
        }

        return true;
    }

    @Override
    public Class<IRowGroupCommand> getCommandClass() {
        return IRowGroupCommand.class;
    }

}
