package com.universalbits.conorganizer.badger.control;
import com.universalbits.conorganizer.badger.model.BadgeInfo;
import com.universalbits.conorganizer.badger.ui.BadgeListModel;
import javax.swing.*;
import java.io.File;
import java.io.IOException;
import java.nio.file.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Created by rjenks on 8/31/2014.
*/
public class BadgeTypeMonitor {
private static final Logger LOGGER = Logger.getLogger(BadgeTypeMonitor.class.getSimpleName());
private BadgeListModel typesList;
private Path badgeDataPath;
private WatchService watcher;
private WatchKey watchKey;
public BadgeTypeMonitor(BadgeListModel typesList) {
this.typesList = typesList;
try {
final FileSystem defaultFileSystem = FileSystems.getDefault();
watcher = defaultFileSystem.newWatchService();
badgeDataPath = Paths.get(BadgePrinter.BADGE_DATA_DIR);
File badgeDataFile = badgeDataPath.toFile();
LOGGER.fine("badgedata path = " + badgeDataFile.getAbsolutePath());
if (!badgeDataFile.exists()) {
badgeDataFile.mkdirs();
}
watchKey = badgeDataPath.register(watcher, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE);
loadTypes();
new Thread(new MonitorRunnable()).start();
} catch (IOException ioe) {
LOGGER.log(Level.SEVERE, "Error creating watcher for badge data", ioe);
}
}
private void loadTypes() throws IOException {
DirectoryStream<Path> dirStream = Files.newDirectoryStream(badgeDataPath);
for (Path file : dirStream) {
if (isPropertyFile(file)) {
String type = getTypeFromFile(file);
addType(type);
}
}
}
private void addType(String type) {
int i;
LOGGER.info("adding type " + type);
final BadgeInfo badgeInfo = new BadgeInfo();
badgeInfo.put(BadgeInfo.TYPE, type);
for (i = 0; i < typesList.size(); i++) {
String oType = typesList.get(i).get(BadgeInfo.TYPE);
if (oType.compareTo(type) > 0) {
break;
}
}
typesList.add(i, badgeInfo);
}
private void removeType(String type) {
LOGGER.info("removing type " + type);
for (int i = 0; i < typesList.size(); i++) {
if (typesList.get(i).get(BadgeInfo.TYPE).equals(type)) {
LOGGER.info("type " + type + " removed");
typesList.remove(i);
break;
}
}
}
private boolean isPropertyFile(Path file) {
return file.getFileName().toString().toUpperCase().endsWith(".PROPERTIES");
}
private String getTypeFromFile(Path file) {
String type = file.toFile().getName().toString();
return type.substring(0, type.lastIndexOf('.'));
}
private class MonitorRunnable implements Runnable {
@Override
public void run() {
while(true) {
WatchKey key;
try {
key = watcher.take();
} catch (InterruptedException x) {
return;
}
for (WatchEvent<?> event: key.pollEvents()) {
final WatchEvent.Kind<?> kind = event.kind();
if (kind == StandardWatchEventKinds.OVERFLOW) {
continue;
}
WatchEvent<Path> ev = (WatchEvent<Path>)event;
Path filename = ev.context();
final Path child = badgeDataPath.resolve(filename);
if (isPropertyFile(child)) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
final String type = getTypeFromFile(child);
if (kind == StandardWatchEventKinds.ENTRY_CREATE) {
addType(type);
} else if (kind == StandardWatchEventKinds.ENTRY_DELETE) {
removeType(type);
}
}
});
}
}
boolean valid = key.reset();
if (!valid) {
LOGGER.log(Level.SEVERE, "badge data folder can no longer be monitored as it no longer exists");
break;
}
}
}
}
}