package co.forsaken.projectindigo.utils.ftb;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.regex.Matcher;
import org.apache.commons.io.IOUtils;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import co.forsaken.projectindigo.data.Mod;
import co.forsaken.projectindigo.data.Mod.ModType;
import co.forsaken.projectindigo.data.Server;
import co.forsaken.projectindigo.data.log.Logger;
import co.forsaken.projectindigo.log.LogManager;
import co.forsaken.projectindigo.utils.DirectoryLocations;
import co.forsaken.projectindigo.utils.FileUtils;
import co.forsaken.projectindigo.utils.ServerLoader;
import co.forsaken.projectindigo.utils.ftb.tokens.Artifact;
import co.forsaken.projectindigo.utils.ftb.tokens.VersionToken;
import co.forsaken.projectindigo.utils.ftb.tokens.VersionToken.Lib;
import com.google.gson.Gson;
public class FtbServerLoader extends ServerLoader {
private static final String FTB_BaseInfoLoc = "http://ftb.cursecdn.com/FTB2/static/";
private static final String FTB_BaseDownloadLoc = "http://ftb.cursecdn.com/FTB2/modpacks/";
private static final String FTB_PrivateDownloadLoc = "http://ftb.cursecdn.com/FTB2/privatepacks/";
private boolean isPrivatePack = false;
private static HashMap<String, Document> ftbModpackInfo = new HashMap<String, Document>();
public FtbServerLoader(Server _server) {
super(_server, true);
}
private static Document getFtbModpackInfo(String secondaryInfo) {
String url = FTB_BaseInfoLoc + secondaryInfo;
if (!ftbModpackInfo.containsKey(secondaryInfo)) {
File baseModTypeFile = new File(DirectoryLocations.BACKEND_DATA_DIR.format("ftb/"));
if (!baseModTypeFile.exists()) baseModTypeFile.mkdirs();
File modpackFile = new File(baseModTypeFile, secondaryInfo);
try {
if (!modpackFile.exists()) modpackFile.createNewFile();
FileUtils.writeStreamToFile(new URL(url).openStream(), modpackFile);
} catch (IOException e) {
LogManager.warn("Failed to load modpacks, loading from backup");
}
InputStream modPackStream = null;
try {
modPackStream = new FileInputStream(modpackFile);
} catch (IOException e) {
LogManager.warn("Failed to read modpack file - falling back to direct download");
}
if (modPackStream == null) {
try {
modPackStream = new URL(url).openStream();
} catch (IOException e) {
Logger.logError("Completely unable to download the modpack file - check your connection");
}
}
if (modPackStream != null) {
try {
ftbModpackInfo.put(secondaryInfo, FileUtils.getXML(modPackStream));
} catch (Exception e) {
LogManager.error("Exception reading modpack file");
return null;
}
if (ftbModpackInfo == null) {
LogManager.error("Error: could not load modpack data!");
return null;
}
}
}
return ftbModpackInfo.get(secondaryInfo);
}
@Override public boolean load(Server server) {
if (!(loadPack("modpacks.xml", server) | loadPack("thirdparty.xml", server))) {
if (loadPack(server.getToken().friendlyName + ".xml", server)) {
isPrivatePack = true;
return true;
}
return false;
}
return true;
}
private boolean loadPack(String type, Server server) {
Document doc = getFtbModpackInfo(type);
if (doc == null) { return false; }
NodeList modPacks = doc.getElementsByTagName("modpack");
boolean found = false;
for (int i = 0; i < modPacks.getLength(); i++) {
Node modPackNode = modPacks.item(i);
NamedNodeMap modPackAttr = modPackNode.getAttributes();
try {
if (!modPackAttr.getNamedItem("dir").getTextContent().equalsIgnoreCase(server.getToken().modpackRefName)) {
continue;
}
server.setUrl(modPackAttr.getNamedItem("url").getTextContent());
server.setDesc(modPackAttr.getNamedItem("description") == null ? null : modPackAttr.getNamedItem("description").getTextContent().replace("\\n", "\n"));
server.setModList(new HashMap<String, Mod>());
if (modPackAttr.getNamedItem("mods") != null) {
for (String line : modPackAttr.getNamedItem("mods").getTextContent().split(";")) {
Matcher urlMatch = REGEX_URL.matcher(line);
Matcher modMatch = REGEX_MODNAME.matcher(line);
String urlM = "";
String modName = "";
List<String> authors = new ArrayList<String>();
if (urlMatch.find()) {
urlM = urlMatch.group(1);
}
if (modMatch.find()) {
modName = modMatch.group(1).trim();
authors = Arrays.asList(modMatch.replaceAll("").trim().replaceAll("by ", "").trim().split(","));
}
server.getModList().put(modName, new Mod(modName, authors, "", urlM, ModType.mod));
}
server.getModList().put("server_download",
new Mod("server_download", new ArrayList<String>(), MOJANG_DOWNLOAD_BASE + "versions/" + modPackAttr.getNamedItem("mcVersion").getTextContent() + "/" + modPackAttr.getNamedItem("mcVersion").getTextContent() + ".jar", "", ModType.minecraft));
for (Mod m : getMojangLibraries(server, modPackAttr.getNamedItem("mcVersion").getTextContent())) {
server.getModList().put(m.getName(), m);
}
String url = String.format("http://ftb.cursecdn.com/FTB2/static/mcjsons/versions/%s/%s.json", modPackAttr.getNamedItem("mcVersion").getTextContent(), modPackAttr.getNamedItem("mcVersion").getTextContent());
VersionToken t = new Gson().fromJson(IOUtils.toString(new URL(url).openStream(), "UTF-8"), VersionToken.class);
Artifact a;
outer: for (Lib l : t.libraries) {
a = new Artifact(l.name);
String name = a.getDownloadUrl();
List<String> replace = new ArrayList<String>();
for (String s : server.getModList().keySet()) {
if (s.contains("-")) {
if (name.substring(0, name.lastIndexOf('-')).equalsIgnoreCase(s.substring(0, s.lastIndexOf('-')))) {
if (parseVersion(s.substring(s.lastIndexOf('-') + 1, s.lastIndexOf("."))) < parseVersion(name.substring(name.lastIndexOf('-') + 1, name.lastIndexOf(".")))) {
replace.add(name);
break;
}
continue outer;
}
}
}
for (String s : replace) {
LogManager.info("Removing " + s + " to make way for " + name);
server.getModList().remove(s);
}
server.getModList().put(l.name, new Mod(l.name, new ArrayList<String>(), "https://libraries.minecraft.net/" + a.getDownloadUrl(), "", ModType.library));
}
if (!found) found = true;
} else {
LogManager.info("Failed to get mods list");
return false;
}
} catch (Exception e) {
LogManager.error("Error while updating modpack info");
return false;
}
}
return found;
}
public String getDownloadUrl(Server server) {
if (isPrivatePack) { return FTB_PrivateDownloadLoc + server.getToken().modpackRefName + "/" + server.getToken().version.replace(".", "_") + "/" + server.getUrl(); }
return FTB_BaseDownloadLoc + server.getToken().modpackRefName + "/" + server.getToken().version.replace(".", "_") + "/" + server.getUrl();
}
public String getDownloadUrl(Server server, String mod) {
return null;
}
}