package CH.ifa.draw.standard;

import java.util.Collections;
import java.util.List;
import java.util.Vector;
import java.util.stream.Collectors;

import CH.ifa.draw.framework.FigureWithID;
import de.renew.draw.storables.ontology.Figure;
import de.renew.draw.ui.api.EditorApi;
import de.renew.draw.ui.ontology.AbstractCommand;
import de.renew.draw.ui.ontology.DrawingEditor;
import de.renew.draw.ui.ontology.undoredo.SnapshotHistory;

/**
 * Restores one undo or redo step.
 * <br>
 * UndoRedoCommand.java
 * Created: Wed Dec 13  2000
 * @author Michael Duvigneau
 *
 * See {@link CH.ifa.draw.framework.UndoRedoManager}.
 * @deprecated This class is not to be used externally and will later be hidden.
 */
@Deprecated(since = "5.0", forRemoval = true)
@SuppressWarnings("removal")
public class UndoRedoCommand extends AbstractCommand {
    public enum Mode {
        UNDO, REDO
    }

    private final Mode _mode;

    public UndoRedoCommand(String name, Mode mode) {
        super(name);
        this._mode = mode;
    }

    private DrawingEditor getEditor() {
        return EditorApi.getCurrentEditor();
    }

    @Override
    public boolean isExecutable() {
        if (!super.isExecutable()) {
            return false;
        }
        if (getEditor() == EditorApi.getNullDrawingEditor()) {
            return false;
        }
        SnapshotHistory history = switch (_mode) {
            case UNDO -> getEditor().getUndoRedoManager().getUndoHistory(getEditor().drawing());
            case REDO -> getEditor().getUndoRedoManager().getRedoHistory(getEditor().drawing());
        };
        return (history != null) && (!history.isEmpty());
    }

    @Override
    public void execute() {
        if (isExecutable()) {
            Vector<Figure> selectionBefore = getEditor().view().selection();
            List<Integer> selectedIds =
                selectionBefore.stream().filter(FigureWithID.class::isInstance)
                    .map(FigureWithID.class::cast).map(FigureWithID::getID).toList();

            getEditor().toolDone();
            switch (_mode) {
                case UNDO:
                    getEditor().getUndoRedoManager().restoreUndoSnapshot(getEditor().drawing());
                    break;
                case REDO:
                    getEditor().getUndoRedoManager().restoreRedoSnapshot(getEditor().drawing());
                    break;
            }

            Vector<Figure> selectionAfter = Collections.list(getEditor().drawing().figures())
                .stream().filter(FigureWithID.class::isInstance).map(FigureWithID.class::cast)
                .filter(f -> selectedIds.contains(f.getID()))
                .collect(Collectors.toCollection(Vector::new));
            // reselect the figures if sizes of selections match (might not be 
            // true if ids are not unique).  
            if (selectionBefore.size() == selectionAfter.size()) {
                getEditor().view().addToSelectionAll(selectionAfter);
            }
            getEditor().selectionChanged(getEditor().view());
        }
    }
}
