/*
* This file is part of Technic Launcher Core.
* Copyright ©2015 Syndicate, LLC
*
* Technic Launcher Core is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Technic Launcher Core is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License,
* as well as a copy of the GNU Lesser General Public License,
* along with Technic Launcher Core. If not, see <http://www.gnu.org/licenses/>.
*/
package net.technicpack.launchercore.image;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.LinkedList;
import java.util.concurrent.atomic.AtomicReference;
public class ImageJob<T> {
protected IImageMapper<T> mapper;
protected IImageStore<T> store;
private T lastJobData;
protected boolean canRetry = true;
private AtomicReference<BufferedImage> imageReference;
private Collection<IImageJobListener<T>> jobListeners = new LinkedList<IImageJobListener<T>>();
public ImageJob(IImageMapper<T> mapper, IImageStore<T> store) {
this.mapper = mapper;
this.store = store;
imageReference = new AtomicReference<BufferedImage>();
imageReference.set(mapper.getDefaultImage());
}
public BufferedImage getImage() {
return imageReference.get();
}
public void addJobListener(IImageJobListener listener) {
synchronized (jobListeners) {
jobListeners.add(listener);
}
}
public void removeJobListener(IImageJobListener listener) {
synchronized (jobListeners) {
jobListeners.remove(listener);
}
}
public boolean canRetry() {
return canRetry;
}
public void refreshRetry() {
canRetry = true;
}
public T getJobData() {
return lastJobData;
}
protected void setImage(BufferedImage image) {
canRetry = false;
imageReference.set(image);
notifyComplete();
}
protected void notifyComplete() {
if (EventQueue.isDispatchThread()) {
synchronized (jobListeners) {
for (IImageJobListener listener : jobListeners) {
listener.jobComplete(this);
}
}
} else {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
notifyComplete();
}
});
}
}
public void start(final T jobData) {
lastJobData = jobData;
Thread imageThread = new Thread("Image Download: " + store.getJobKey(jobData)) {
@Override
public void run() {
try {
File imageLocation = mapper.getImageLocation(jobData);
BufferedImage existingImage = null;
if (imageLocation != null && imageLocation.exists()) {
try {
existingImage = ImageIO.read(imageLocation);
} catch (IOException ex) {
//Corrupt or missing- that's fine, just redownload it
}
}
if (existingImage != null)
setImage(existingImage);
if (store.canDownloadImage(jobData, imageLocation) && (existingImage == null || mapper.shouldDownloadImage(jobData))) {
if (imageLocation != null && !imageLocation.getParentFile().exists())
imageLocation.getParentFile().mkdirs();
store.downloadImage(jobData, imageLocation);
try {
BufferedImage newImage = ImageIO.read(imageLocation);
if (newImage != null)
setImage(newImage);
} catch (IOException ex) {
//Again- probably something wrong with the image, so we'll just show the default
}
}
} finally {
if (canRetry)
canRetry = store.canRetry(jobData);
}
}
};
imageThread.start();
}
}