001package com.ericlam.mc.bungee.hnmc.commands.caxerx;
002
003
004import com.ericlam.mc.bungee.hnmc.commands.caxerx.exception.CommandArgumentException;
005import com.ericlam.mc.bungee.hnmc.commands.caxerx.exception.CommandPermissionException;
006import com.ericlam.mc.bungee.hnmc.permission.Perm;
007import net.md_5.bungee.api.CommandSender;
008
009import java.util.ArrayList;
010import java.util.Arrays;
011import java.util.List;
012
013/**
014 * @author caxerx
015 */
016public abstract class CommandNode {
017
018    private final String description;
019    private final String placeholder;
020    private final String command;
021
022
023    private final ArrayList<CommandNode> subCommands = new ArrayList<>();
024
025
026    private final ArrayList<String> alias = new ArrayList<>();
027
028    private final String permission;
029
030
031    private CommandNode parent;
032
033
034    /**
035     * @param parent      父類節點
036     * @param command     指令
037     * @param permission  權限
038     * @param description 介紹
039     * @param placeholder       用法
040     * @param alias       縮寫
041     */
042    public CommandNode(CommandNode parent, String command, String permission, String description, String placeholder, String... alias) {
043        this.parent = parent;
044        this.command = command;
045        this.alias.add(command);
046        this.alias.addAll(List.of(alias));
047        this.permission = permission;
048        this.description = description;
049        this.placeholder = placeholder;
050    }
051
052    public String getCommand() {
053        return command;
054    }
055
056    public String getDescription() {
057        return description;
058    }
059
060    public String getPlaceholder() {
061        return placeholder;
062    }
063
064    public ArrayList<CommandNode> getSubCommands() {
065        return subCommands;
066    }
067
068    public CommandNode getParent() {
069        return parent;
070    }
071
072    void setParent(CommandNode node) {
073        this.parent = node;
074    }
075
076    public ArrayList<String> getAlias() {
077        return alias;
078    }
079
080    public String getPermission() {
081        return permission;
082    }
083
084    @Deprecated
085    public void addAlias(String ali) {
086        if (!alias.contains(ali)) {
087            this.alias.add(ali);
088        }
089    }
090
091    @Deprecated
092    public void addAllAliases(List<String> aliases) {
093        aliases.forEach(ali -> {
094            if (!alias.contains(ali)) {
095                alias.add(ali);
096            }
097        });
098    }
099
100    /**
101     * @param c 分支指令
102     */
103    public void addSub(CommandNode c) {
104        subCommands.add(c);
105    }
106
107    /**
108     * @param sender 指令發送者
109     * @param args   指令參數
110     */
111    public abstract void executeCommand(CommandSender sender, List<String> args);
112
113    /**
114     * @param sender 指令發送者
115     * @param args   指令參數
116     * @return Tab 列
117     */
118    public abstract List<String> executeTabCompletion(CommandSender sender, List<String> args);
119
120    public void invokeCommand(CommandSender sender, List<String> args) {
121
122        if (permission != null && !Perm.hasPermission(sender, permission)) {
123            throw new CommandPermissionException(permission);
124        }
125
126        if (args.size() > 0) {
127            for (CommandNode subCommand : subCommands) {
128                if (subCommand.match(args.get(0))) {
129                    List<String> passArg = new ArrayList<>(args);
130                    passArg.remove(0);
131                    if (subCommand.getPlaceholder() != null) {
132                        String[] placeholders = Arrays.stream(subCommand.getPlaceholder().split(" ")).filter(holder -> holder.startsWith("<") && holder.endsWith(">")).toArray(String[]::new);
133                        if (passArg.size() < placeholders.length) {
134                            throw new CommandArgumentException(String.join(" ", placeholders));
135                        }
136                    }
137
138                    subCommand.invokeCommand(sender, passArg);
139                    return;
140                }
141            }
142        }
143
144        if (this.getPlaceholder() != null) {
145            String[] placeholders = Arrays.stream(this.getPlaceholder().split(" ")).filter(holder -> holder.startsWith("<") && holder.endsWith(">")).toArray(String[]::new);
146            if (args.size() < placeholders.length) {
147                throw new CommandArgumentException(String.join(" ", placeholders));
148            }
149        }
150        executeCommand(sender, args);
151    }
152
153    public List<String> invokeTabCompletion(CommandSender sender, List<String> args) {
154        if (permission != null && !Perm.hasPermission(sender, permission)) {
155            throw new CommandPermissionException(permission);
156        }
157
158        if (args.size() > 0) {
159            for (CommandNode subCommand : subCommands) {
160                if (subCommand.match(args.get(0))) {
161                    List<String> passArg = new ArrayList<>(args);
162                    passArg.remove(0);
163                    return subCommand.invokeTabCompletion(sender, passArg);
164                }
165            }
166        }
167
168        return executeTabCompletion(sender, args);
169    }
170
171    public boolean match(String args) {
172        for (String ali : alias) {
173            if (args.equalsIgnoreCase(ali)) {
174                return true;
175            }
176        }
177        return false;
178    }
179}