package de.renew.draw.ui.impl.services;

import CH.ifa.draw.application.VersionInfoCommand;
import CH.ifa.draw.figures.GroupCommand;
import CH.ifa.draw.figures.SelectCommand;
import CH.ifa.draw.figures.UngroupCommand;
import CH.ifa.draw.standard.AlignCommand;
import CH.ifa.draw.standard.ChangeAttributeCommand;
import CH.ifa.draw.standard.SpreadCommand;
import de.renew.draw.storables.ontology.FigureFilter;
import de.renew.draw.ui.api.services.CommandService;
import de.renew.draw.ui.ontology.AbstractCommand;
import de.renew.draw.ui.ontology.Alignment;
import de.renew.draw.ui.ontology.Anchor;
import de.renew.draw.ui.ontology.SelectionMode;
import de.renew.draw.ui.ontology.SpreadMode;
import de.renew.plugin.IPlugin;

/**
 * Provides functionality for the {@link CommandService} interface.
 */
public final class CommandServiceImpl implements CommandService {

    @Override
    public AbstractCommand createCommand(String name, Runnable runnable) {
        return new AbstractCommand(name) {
            @Override
            public void execute() {
                runnable.run();
            }
        };
    }

    @Override
    public AbstractCommand createVersionInfoCommand(IPlugin plugin) {
        return new VersionInfoCommand(plugin);
    }

    @Override
    public AbstractCommand createGroupCommand(String name) {
        return new GroupCommand(name);
    }

    @Override
    public AbstractCommand createUngroupCommand(String name) {
        return new UngroupCommand(name);
    }

    @Override
    public AbstractCommand createSelectCommand(
        String name, Class<?> figureClass, SelectionMode mode)
    {
        return new SelectCommand(name, figureClass, mode.ordinal());
    }

    @Override
    public AbstractCommand createSelectCommand(
        String name, Class<?> figureClass, Class<?> parentClass, SelectionMode mode)
    {
        return new SelectCommand(name, figureClass, parentClass, mode.ordinal());
    }

    @Override
    public AbstractCommand createSelectCommand(
        String name, FigureFilter filter, SelectionMode mode)
    {
        int code = switch (mode) {
            case SELECT -> SelectCommand.SELECT;
            case ADD -> SelectCommand.ADD;
            case REMOVE -> SelectCommand.REMOVE;
            case RESTRICT -> SelectCommand.RESTRICT;
        };
        return new SelectCommand(name, filter, code);
    }

    @Override
    public AbstractCommand createAlignCommand(String name, Alignment alignment) {
        int code = switch (alignment) {
            case LEFTS -> AlignCommand.LEFTS;
            case CENTERS -> AlignCommand.CENTERS;
            case RIGHTS -> AlignCommand.RIGHTS;
            case TOPS -> AlignCommand.TOPS;
            case MIDDLES -> AlignCommand.MIDDLES;
            case BOTTOMS -> AlignCommand.BOTTOMS;
        };
        return new AlignCommand(name, code);
    }

    @Override
    public AbstractCommand createAlignCommand(String name, Alignment alignment, Anchor anchor) {
        int anchorCode = switch (anchor) {
            case ANCHOR_LAST -> AlignCommand.ANCHOR_LAST;
            case ANCHOR_FIRST -> AlignCommand.ANCHOR_FIRST;
            case ANCHOR_BIGGEST -> AlignCommand.ANCHOR_BIGGEST;
            case ANCHOR_SMALLEST -> AlignCommand.ANCHOR_SMALLEST;
            case ANCHOR_SELECTION -> AlignCommand.ANCHOR_SELECTION;
        };

        int alignmentCode = switch (alignment) {
            case LEFTS -> AlignCommand.LEFTS;
            case CENTERS -> AlignCommand.CENTERS;
            case RIGHTS -> AlignCommand.RIGHTS;
            case TOPS -> AlignCommand.TOPS;
            case MIDDLES -> AlignCommand.MIDDLES;
            case BOTTOMS -> AlignCommand.BOTTOMS;
        };
        return new AlignCommand(name, alignmentCode, anchorCode);
    }

    @Override
    public AbstractCommand createSpreadCommand(String name, SpreadMode mode) {
        int code = switch (mode) {
            case LEFTS -> SpreadCommand.LEFTS;
            case CENTERS -> SpreadCommand.CENTERS;
            case RIGHTS -> SpreadCommand.RIGHTS;
            case TOPS -> SpreadCommand.TOPS;
            case MIDDLES -> SpreadCommand.MIDDLES;
            case BOTTOMS -> SpreadCommand.BOTTOMS;
            case HORIZONTAL_DISTANCE -> SpreadCommand.HORIZONTAL_DISTANCE;
            case VERTICAL_DISTANCE -> SpreadCommand.VERTICAL_DISTANCE;
            case DIAGONAL_CENTERS -> SpreadCommand.DIAGONAL_CENTERS;
        };
        return new SpreadCommand(name, code);
    }

    @Override
    public AbstractCommand createChangeAttributeCommand(
        String commandName, String attributeName, Object attributeValue)
    {
        return new ChangeAttributeCommand(commandName, attributeName, attributeValue);
    }
}
