package net.krazyweb.starmodmanager.data;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javafx.concurrent.Task;
import javafx.concurrent.WorkerStateEvent;
import javafx.event.EventHandler;
import net.krazyweb.helpers.FileHelper;
import net.krazyweb.starmodmanager.data.Mod.ModOrderComparator;
import net.krazyweb.starmodmanager.dialogue.MessageDialogue;
import net.krazyweb.starmodmanager.dialogue.MessageDialogue.MessageType;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class GetModListTask extends Task<Void> {
private static final Logger log = LogManager.getLogger(GetModListTask.class);
private List<Mod> mods;
private SettingsModelInterface settings;
private LocalizerModelInterface localizer;
private DatabaseModelInterface database;
private boolean recoverableErrorOccurred = false;
protected GetModListTask(final ModList modList) {
settings = new SettingsFactory().getInstance();
localizer = new LocalizerFactory().getInstance();
database = new DatabaseFactory().getInstance();
setOnSucceeded(new EventHandler<WorkerStateEvent>() {
@Override
public void handle(final WorkerStateEvent event) {
log.debug("Task Succeeded");
if (recoverableErrorOccurred) {
MessageDialogue dialogue = new MessageDialogue(localizer.getMessage("modlisttask.recoverableerror"), localizer.getMessage("modlisttask.recoverableerror.title"), MessageType.ERROR, new LocalizerFactory());
dialogue.getResult();
}
modList.setModList(mods);
}
});
setOnFailed(new EventHandler<WorkerStateEvent>() {
@Override
public void handle(final WorkerStateEvent event) {
log.error("", getException());
MessageDialogue dialogue = new MessageDialogue(localizer.getMessage("modlisttask.error"), localizer.getMessage("modlisttask.error.title"), MessageType.ERROR, new LocalizerFactory());
dialogue.getResult();
}
});
}
@Override
protected Void call() throws Exception {
// TODO Remove mods from database when archive has been deleted
this.updateMessage("Loading Mod List");
this.updateProgress(0.0, 1.0);
List<String> modsInDatabase = database.getModNames();
List<String> modNames = new ArrayList<>();
Set<String> currentArchives = new HashSet<>();
Set<Path> archives = new HashSet<>();
Set<Path> toRemove = new HashSet<>();
for (final String modData : modsInDatabase) {
modNames.add(modData.split("\n")[0]);
currentArchives.add(settings.getPropertyPath("modsdir").resolve(modData.split("\n")[1]).toAbsolutePath().toString()); //TODO Better Path manipulation
}
log.debug(modNames);
FileHelper.listFiles(settings.getPropertyString("modsdir"), archives); //TODO investigate using path
for (Path path : archives) {
if (currentArchives.contains(path.toString())) {
toRemove.add(path);
}
}
archives.removeAll(toRemove);
int count = 1;
int total = modNames.size() + archives.size();
mods = new ArrayList<>();
for (final String modName : modsInDatabase) {
Mod tempMod = null;
if ((tempMod = database.getModByName(modName.split("\n")[0])) != null) {
if (!tempMod.isHidden()) {
mods.add(tempMod);
}
}
this.updateProgress((double) count, (double) total);
count++;
}
Collections.sort(mods, new ModOrderComparator());
toRemove = new HashSet<>();
for (Path path : archives) {
Set<Mod> tempMods = Mod.load(path, mods.size(), new SettingsFactory(), new DatabaseFactory(), new LocalizerFactory());
if (tempMods == null || tempMods.isEmpty()) {
recoverableErrorOccurred = true;
continue;
}
for (Mod mod : tempMods) {
mods.add(mod);
for (Path path2 : archives) {
if (Files.isSameFile(settings.getPropertyPath("modsdir").resolve(mod.getArchiveName()), path2)) {
toRemove.add(path2);
} else {
log.debug("File is used by mod manager, will not delete: '{}' = '{}'", settings.getPropertyPath("modsdir").resolve(mod.getArchiveName()), path2);
}
}
}
this.updateProgress((double) count, (double) total);
count++;
}
archives.removeAll(toRemove);
for (Path path : archives) {
log.debug("File is not used by mod manager, deleting: '{}'", path);
try {
FileHelper.deleteFile(path);
} catch (final IOException e) {
log.error("", e);
}
}
for (Mod mod : mods) {
mod.setOrder(mods.indexOf(mod));
database.updateMod(mod);
}
this.updateProgress(1.0, 1.0);
/*
* This gives the UI thread time to visually update to 100%
* before the dialogue closes without adding noticeable time
* to the loading process.
*/
Thread.sleep(15);
return null;
}
}