import com.runemate.game.api.hybrid.Environment;
import com.runemate.game.api.script.framework.AbstractScript;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.EventListener;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.function.Consumer;
/**
* Author: Tom
* Date: 04/03/2015
* Time: 20:38
*/
public class ImageManager {
private static final Image NIL_IMAGE = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
private final AbstractScript script;
private final LRUImageCache cache = new LRUImageCache(this);
private final LinkedList<ImageLoadExceptionEventListener> listeners = new LinkedList<>();
private int maxImageCount;
public ImageManager(AbstractScript script, int maxImageCount) {
this.script = script;
this.maxImageCount = maxImageCount;
}
public ImageManager(AbstractScript script) {
this(script, -1);
}
public final int getMaxImageCount() {
return maxImageCount;
}
public final void setMaxImageCount(int maxImageCount) {
this.maxImageCount = maxImageCount;
}
public final void submitLoadExceptionListener(ImageLoadExceptionEventListener listener) {
listeners.add(listener);
}
public final void removeLoadExceptionListener(ImageLoadExceptionEventListener listener) {
listeners.remove(listener);
}
public final Image get(String path, boolean forceLoad, ImageLoadMode imageLoadMode) {
String imageTag = imageLoadMode.name().concat(":").concat(path);
Image image = cache.get(imageTag);
if (forceLoad || image == null) {
synchronized (cache) {
image = cache.get(imageTag);
if (image == null) {
cache.put(imageTag, image = imageLoadMode.get(this, path));
}
}
}
return image;
}
public enum ImageLoadMode {
RESOURCE() {
@Override
Image get(ImageManager instance, String path) {
try (InputStream stream = instance.script.getClass().getResourceAsStream(path)) {
return ImageIO.read(stream);
} catch (IOException e) {
onError(instance, new ImageLoadExceptionEvent(path, this, e));
}
return NIL_IMAGE;
}
},
LOCAL_SCRIPT() {
@Override
Image get(ImageManager instance, String path) {
path = Environment.getStorageDirectory().getAbsolutePath().concat(File.separator).concat(path);
try (InputStream stream = new FileInputStream(path)) {
return ImageIO.read(stream);
} catch (IOException e) {
onError(instance, new ImageLoadExceptionEvent(path, this, e));
}
return NIL_IMAGE;
}
},
LOCAL_GENERAL() {
@Override
Image get(ImageManager instance, String path) {
path = Environment.getGeneralStorageDirectory().getAbsolutePath().concat(File.separator).concat(path);
try (InputStream stream = new FileInputStream(path)) {
return ImageIO.read(stream);
} catch (IOException e) {
onError(instance, new ImageLoadExceptionEvent(path, this, e));
}
return NIL_IMAGE;
}
};
abstract Image get(ImageManager instance, String path);
final void onError(ImageManager manager, final ImageLoadExceptionEvent exception) {
manager.listeners.forEach(new Consumer<ImageLoadExceptionEventListener>() {
@Override
public void accept(ImageLoadExceptionEventListener listener) {
listener.onEvent(exception);
}
});
}
}
public static interface ImageLoadExceptionEventListener extends EventListener {
public void onEvent(ImageLoadExceptionEvent event);
}
public static final class ImageLoadExceptionEvent {
private final String path;
private final ImageLoadMode imageLoadMode;
private final IOException exception;
public ImageLoadExceptionEvent(String path, ImageLoadMode imageLoadMode, IOException exception) {
this.path = path;
this.imageLoadMode = imageLoadMode;
this.exception = exception;
}
public final String getPath() {
return path;
}
public final ImageLoadMode getImageLoadMode() {
return imageLoadMode;
}
public final IOException getException() {
return exception;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("IOExceptionEvent{");
sb.append("path='").append(path).append('\'');
sb.append(", mode=").append(imageLoadMode.name());
sb.append(", exception=").append(exception.getMessage());
sb.append('}');
return sb.toString();
}
}
private final class LRUImageCache extends LinkedHashMap<String, Image> {
private final ImageManager manager;
private LRUImageCache(ImageManager manager) {
this.manager = manager;
}
@Override
protected final boolean removeEldestEntry(Map.Entry<String, Image> eldest) {
return manager.maxImageCount == -1 || size() > manager.maxImageCount;
}
}
}