package magic.ui.screen.images.download;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.Files;
import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import magic.data.CardImageFile;
import magic.data.DownloadableFile;
import magic.data.ImagesDownloadList;
import magic.exception.DownloadException;
import magic.ui.CardTextLanguage;
import magic.ui.MagicImages;
import magic.ui.MagicLogFile;
import magic.ui.PrintedCardImage;
import magic.ui.ProxyCardImage;
import magic.utility.MagicSystem;
class DownloadWorker extends SwingWorker<Void, Integer> {
private static final MagicLogFile missingLog = new MagicLogFile("downloaded-images");
private ImagesDownloadList downloadList;
private final IDownloadListener listener;
private final CardImageDisplayMode displayMode;
private boolean updateDownloadDate = true;
private boolean isLogging = true;
private int serverBusyCooldown = 1; // in millisecs
DownloadWorker(IDownloadListener aListener, CardImageDisplayMode aMode) {
this.listener = aListener;
this.displayMode = aMode;
}
@Override
protected Void doInBackground() throws MalformedURLException {
this.downloadList = ScanWorker.getImagesDownloadList((IScanListener)listener, displayMode);
doDownloadImages();
return null;
}
@Override
protected void done() {
try {
get();
} catch (ExecutionException | InterruptedException ex) {
throw new RuntimeException(ex);
} catch (CancellationException ex) {
System.err.println("ImageDownloadWorker cancelled.");
}
listener.setButtonState(false);
resetProgressBar();
MagicImages.clearCache();
listener.buildDownloadImagesList();
}
@Override
protected void process(List<Integer> chunks) {
final int countInteger = chunks.get(chunks.size() - 1);
if (!isCancelled()) {
listener.showProgress(countInteger, downloadList.size());
}
}
private boolean isLoggingOn() {
return isLogging && MagicSystem.isDevMode();
}
/**
* Experimental, currently only available in devMode and missing mode.
*/
private void doLog(String cardName, CardTextLanguage aLang, URL cardUrl) {
if (isLoggingOn()) {
synchronized (missingLog) {
try {
missingLog.log(cardName, aLang, cardUrl);
} catch (IOException ex) {
System.err.println("doLog: " + ex);
isLogging = false;
}
}
}
}
/**
* Initializes log files for capturing useful info (DEVMODE ONLY!).
*/
private void initializeLogFiles() {
if (isLoggingOn()) {
synchronized (missingLog) {
try {
missingLog.deleteLogFileIfExists();
missingLog.log("# " + LocalDateTime.now());
missingLog.log("#");
} catch (IOException ex) {
System.err.println("initializeLogFiles: " + ex);
isLogging = false;
}
}
}
}
private void setServerBusyCooldown(String errmsg) {
if (errmsg.contains("HTTP response code: 503")) {
serverBusyCooldown += 100;
}
}
private boolean doDeleteLocalImageFile(File aFile) {
try {
Files.deleteIfExists(aFile.toPath());
} catch (IOException ex) {
listener.setMessage(String.format("%s [%s]", ex.toString(), aFile.getName()));
return false;
}
return true;
}
private void downloadPrintedImage(CardImageFile imageFile) {
try {
PrintedCardImage.tryDownloadingPrintedImage(imageFile);
} catch (DownloadException ex) {
listener.setMessage(ex.getMessage());
setServerBusyCooldown(ex.toString());
if (ex.getCause() instanceof IOException) {
// if local image file already existed before download then
// download was triggered by the 'image_updated' script property.
// As download failed remove local image so it gets picked up
// by the missing image trigger instead. If unable to remove
// local image then don't update 'imageDownloaderRunDate'.
updateDownloadDate = doDeleteLocalImageFile(imageFile.getLocalFile());
}
}
}
private boolean tryDownloadingCroppedImage(CardImageFile imageFile) {
try {
return ProxyCardImage.tryDownloadingCroppedImage(imageFile);
} catch (DownloadException | MalformedURLException ex) {
System.err.println(String.format("%s [%s]", ex.toString(), imageFile.getFilename()));
}
return false;
}
private void doPause(int millisecs) {
try {
Thread.sleep(millisecs);
} catch (InterruptedException ex) {
System.err.println(ex);
}
}
private void doDownloadImages() throws MalformedURLException {
assert !SwingUtilities.isEventDispatchThread();
initializeLogFiles();
int fileCount = 0;
for (DownloadableFile dFile : downloadList) {
final CardImageFile imageFile = (CardImageFile) dFile;
if (displayMode == CardImageDisplayMode.PROXY) {
if (!tryDownloadingCroppedImage(imageFile)) {
downloadPrintedImage(imageFile);
}
} else {
downloadPrintedImage(imageFile);
}
doPause(serverBusyCooldown);
fileCount++;
if (isCancelled()) {
return;
} else {
publish(new Integer(fileCount));
}
}
if (updateDownloadDate) {
listener.doCustomActionAfterDownload();
}
}
private void resetProgressBar() {
assert SwingUtilities.isEventDispatchThread();
listener.resetProgress();
}
}