package com.faforever.client.fa;
import com.faforever.client.game.Faction;
import org.springframework.util.StringUtils;
import java.net.URI;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class LaunchCommandBuilder {
private static final Pattern QUOTED_STRING_PATTERN = Pattern.compile("([^\"]\\S*|\".+?\")\\s*");
private Float mean;
private Float deviation;
private String country;
private String clan;
private String username;
private Integer uid;
private Path executable;
private List<String> additionalArgs;
private Integer localGpgPort;
private Path logFile;
private Path replayFile;
private Integer replayId;
private URI replayUri;
private String gameType;
private Faction faction;
private String executableDecorator;
private boolean rehost;
private LaunchCommandBuilder() {
executableDecorator = "\"%s\"";
}
public static LaunchCommandBuilder create() {
return new LaunchCommandBuilder();
}
private static List<String> split(String string) {
Matcher matcher = QUOTED_STRING_PATTERN.matcher(string);
ArrayList<String> result = new ArrayList<>();
while (matcher.find()) {
result.add(matcher.group(1).replace("\"", ""));
}
return result;
}
public LaunchCommandBuilder localGpgPort(int localGpgPort) {
this.localGpgPort = localGpgPort;
return this;
}
public LaunchCommandBuilder executable(Path executable) {
this.executable = executable;
return this;
}
public LaunchCommandBuilder uid(Integer uid) {
this.uid = uid;
return this;
}
public LaunchCommandBuilder mean(Float mean) {
this.mean = mean;
return this;
}
public LaunchCommandBuilder deviation(Float deviation) {
this.deviation = deviation;
return this;
}
public LaunchCommandBuilder country(String country) {
this.country = country;
return this;
}
public LaunchCommandBuilder clan(String clan) {
this.clan = clan;
return this;
}
public LaunchCommandBuilder username(String username) {
this.username = username;
return this;
}
public LaunchCommandBuilder logFile(Path logFile) {
this.logFile = logFile;
return this;
}
public LaunchCommandBuilder additionalArgs(List<String> additionalArgs) {
this.additionalArgs = additionalArgs;
return this;
}
public LaunchCommandBuilder replayId(Integer replayId) {
this.replayId = replayId;
return this;
}
public LaunchCommandBuilder replayFile(Path replayFile) {
this.replayFile = replayFile;
return this;
}
public LaunchCommandBuilder replayUri(URI replayUri) {
this.replayUri = replayUri;
return this;
}
public LaunchCommandBuilder gameType(String gameType) {
this.gameType = gameType;
return this;
}
public LaunchCommandBuilder faction(Faction faction) {
this.faction = faction;
return this;
}
public LaunchCommandBuilder rehost(boolean rehost) {
this.rehost = rehost;
return this;
}
public List<String> build() {
if (executableDecorator == null) {
throw new IllegalStateException("executableDecorator has not been set");
}
if (executable == null) {
throw new IllegalStateException("executable has not been set");
}
if (logFile == null) {
throw new IllegalStateException("logFile has not been set");
}
if (gameType == null) {
throw new IllegalStateException("gameType has not been set");
}
if (replayUri != null && uid != null) {
throw new IllegalStateException("uid and replayUri cannot be set at the same time");
}
if (uid != null && username == null) {
throw new IllegalStateException("username has not been set");
}
List<String> command = new ArrayList<>();
command.addAll(split(String.format(executableDecorator, executable.toAbsolutePath().toString())));
command.addAll(Arrays.asList(
"/init", String.format("init_%s.lua", gameType),
"/nobugreport"
));
if (faction != null) {
command.add(String.format("/%s", faction.getString()));
}
if (logFile != null) {
command.add("/log");
command.add(logFile.toAbsolutePath().toString());
}
if (localGpgPort != null) {
command.add("/gpgnet");
command.add("127.0.0.1:" + localGpgPort);
}
if (mean != null) {
command.add("/mean");
command.add(String.valueOf(mean));
}
if (deviation != null) {
command.add("/deviation");
command.add(String.valueOf(deviation));
}
if (replayFile != null) {
command.add("/replay");
command.add(replayFile.toAbsolutePath().toString());
} else if (replayUri != null) {
command.add("/replay");
command.add(replayUri.toASCIIString());
}
if (uid != null) {
command.add("/savereplay");
command.add("gpgnet://localhost/" + uid + "/" + username + ".SCFAreplay");
}
if (country != null) {
command.add("/country");
command.add(country);
}
if (!StringUtils.isEmpty(clan)) {
command.add("/clan");
command.add(clan);
}
if (replayId != null) {
command.add("/replayid");
command.add(String.valueOf(replayId));
}
if (rehost) {
command.add("/rehost");
}
if (additionalArgs != null) {
command.addAll(additionalArgs);
}
return command;
}
public LaunchCommandBuilder executableDecorator(String executableDecorator) {
this.executableDecorator = executableDecorator;
return this;
}
}