001/************************* PROJECT RON *************************/
002/* Copyright (c) 2026 StuyPulse Robotics. All rights reserved. */
003/* Use of this source code is governed by an MIT-style license */
004/* that can be found in the repository LICENSE file.           */
005/***************************************************************/
006package tools.ToolClasses;
007
008import java.util.ArrayList;
009import java.util.List;
010
011public abstract class VarArgumentedTool<V> {
012    private final Class<?> argumentType;
013    private final String description;
014
015    @SuppressWarnings("unchecked")
016    private List<V> parseArguments(String rawArgs) {
017        String[] argStrings = rawArgs.split(" (?=(?:[^\"']*[\"'][^\"']*[\"'])*[^\"']*$)"); // split by spaces if not within single or double quotes
018        List<V> arguments = new ArrayList<V>();
019        for (int i = 0; i < argStrings.length; i++) {
020            argStrings[i] = argStrings[i].replaceAll("^\"|\"$|^'|'$", ""); // remove surrounding quotes
021            if (this.argumentType == String.class) {
022                arguments.add(((V) argStrings[i]));
023                continue;
024            }
025
026            switch (this.argumentType.getSimpleName()) {
027                case "Integer", "int" -> {
028                    try {
029                        arguments.add((V) Integer.valueOf(argStrings[i]));
030                    } catch (Exception e) {
031                        System.err.println("Failed to parse argument " + argStrings[i] + " into an integer. Skipping.");
032                    }
033                }
034                case "Double", "double" -> {
035                    try {
036                        arguments.add((V) Double.valueOf(argStrings[i]));
037                    } catch (Exception e) {
038                        System.err.println("Failed to parse argument " + argStrings[i] + " into a double. Skipping.");
039                    }
040                }
041                case "Boolean", "boolean" -> {
042                    if (argStrings[i].equalsIgnoreCase("true") || argStrings[i].equalsIgnoreCase("false")) {
043                        arguments.add((V) Boolean.valueOf(argStrings[i]));
044                    } else {
045                        System.err.println("Failed to parse argument " + argStrings[i] + " into a boolean. Skipping.");
046                    }
047                }
048                default -> {
049                    if (this.argumentType.isEnum()) {
050                        try {
051                            String enumName = (String) argStrings[i];
052                            Enum<?> match = null;
053                            for (Enum<?> c : (Enum<?>[]) this.argumentType.getEnumConstants()) {
054                                if (c.name().equalsIgnoreCase(enumName)) {
055                                    match = c;
056                                    break;
057                                }
058                            }
059
060                            if (match == null) {
061                                throw new IllegalArgumentException(); // to be caught by catch block
062                            }
063                            arguments.add((V) match);
064                        } catch (Exception e) {
065                            System.err.println("Failed to parse argument " + argStrings[i] + " into an enum of type " + this.argumentType.getSimpleName() + ". Skipping.");
066                        }
067                    } else {
068                        System.err.println("Unsupported argument type: " + this.argumentType.getSimpleName());
069                    }
070                }
071            }
072        }
073
074        return arguments;
075    }
076
077    protected VarArgumentedTool(Class<?> argumentType, String description) {
078        this.argumentType = argumentType;
079        this.description = description;
080    }
081
082    protected abstract void execute(List<V> arguments);
083
084    public final void run(String rawArgs) {
085        List<V> arguments = parseArguments(rawArgs);
086        execute(arguments);
087    }
088}