package magic.ui.screen.images.download;
import java.awt.Font;
import java.io.IOException;
import java.util.Collection;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Stream;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import magic.data.CardDefinitions;
import magic.data.CardImageFile;
import magic.data.DownloadableFile;
import magic.data.GeneralConfig;
import magic.data.ImagesDownloadList;
import magic.data.MagicIcon;
import magic.model.MagicCardDefinition;
import magic.translate.MText;
import magic.ui.MagicImages;
import net.miginfocom.swing.MigLayout;
@SuppressWarnings("serial")
public abstract class DownloadPanel extends JPanel implements IScanListener, IDownloadListener {
static final String CP_STATE_CHANGED = "5234acd4-e05d-4fc4-a599-95ecd34aa893";
// translatable strings
private static final String _S1 = "Cancel";
private static final Logger LOGGER = Logger.getLogger(DownloadPanel.class.getName());
protected static final GeneralConfig CONFIG = GeneralConfig.getInstance();
private final MigLayout migLayout = new MigLayout();
protected final JLabel captionLabel = getCaptionLabel(getProgressCaption());
protected final JButton downloadButton = new JButton();
private final JButton cancelButton = new JButton(MText.get(_S1));
protected final JProgressBar progressBar = new JProgressBar();
private ImagesDownloadList files;
private SwingWorker<Void, Integer> imagesDownloader;
private ScanWorker imagesScanner;
private DownloadState downloaderState = DownloadState.STOPPED;
private CardImageDisplayMode displayMode = CardImageDisplayMode.PRINTED;
private final DialogMainPanel mainPanel;
protected abstract String getProgressCaption();
protected abstract String getDownloadButtonCaption();
DownloadPanel(CardImageDisplayMode aMode, DialogMainPanel aPanel) {
this.displayMode = aMode;
this.mainPanel = aPanel;
setLookAndFeel();
refreshLayout();
setActions();
buildDownloadImagesList();
}
DownloadState getState() {
return downloaderState;
}
private void doRunImageDownloadWorker() {
setDownloadingState();
imagesDownloader = new DownloadWorker(this, displayMode);
imagesDownloader.execute();
notifyStatusChanged(DownloadState.DOWNLOADING);
}
private void setActions() {
downloadButton.addActionListener(action -> {
doRunImageDownloadWorker();
});
cancelButton.addActionListener(action -> {
doCancelImageDownloadWorker();
});
}
void doCancel() {
doCancelImageDownloadWorker();
doCancelImagesScanner();
}
private void doCancelImageDownloadWorker() {
if (imagesDownloader != null && !imagesDownloader.isCancelled() && !imagesDownloader.isDone()) {
imagesDownloader.cancel(true);
setButtonState(false);
}
}
private void doCancelImagesScanner() {
if (imagesScanner != null && !imagesScanner.isCancelled() && !imagesScanner.isDone()) {
imagesScanner.cancel(true);
}
}
@Override
public final void buildDownloadImagesList() {
if (imagesScanner != null && !imagesScanner.isDone()) {
imagesScanner.cancel(true);
}
if (imagesScanner != null && !imagesScanner.isDone()) {
LOGGER.log(Level.WARNING, "Scanner still running!");
return;
}
captionLabel.setIcon(MagicImages.getIcon(MagicIcon.BUSY16));
captionLabel.setText(getProgressCaption());
imagesScanner = new ScanWorker(this, displayMode);
imagesScanner.execute();
downloadButton.setEnabled(false);
notifyStatusChanged(DownloadState.SCANNING);
}
private void resetProgressBar() {
progressBar.setMinimum(0);
progressBar.setMaximum(files.size());
progressBar.setValue(0);
}
@Override
public void setButtonState(final boolean isDownloading) {
downloadButton.setVisible(!isDownloading);
cancelButton.setVisible(isDownloading);
refreshLayout();
}
private void setDownloadingState() {
setButtonState(true);
resetProgressBar();
captionLabel.setIcon(MagicImages.getIcon(MagicIcon.BUSY16));
}
private void refreshLayout() {
removeAll();
migLayout.setLayoutConstraints("flowx, insets 0, gap 0");
add(progressBar, "w 100%, h 26!");
add(downloadButton.isVisible() ? downloadButton : cancelButton, "w 100!");
}
private void setLookAndFeel() {
// Layout manager.
setLayout(migLayout);
// download button
downloadButton.setEnabled(false);
downloadButton.setText(getDownloadButtonCaption());
// progress bar
progressBar.setLayout(new MigLayout("insets 0 8 0 0, aligny center"));
progressBar.add(captionLabel, "w 100%, h 100%");
progressBar.setStringPainted(false);
}
private JLabel getCaptionLabel(final String text) {
final ImageIcon ii = MagicImages.getIcon(MagicIcon.BUSY16);
final JLabel lbl = new JLabel(ii);
lbl.setText(text);
lbl.setHorizontalAlignment(SwingConstants.LEFT);
lbl.setHorizontalTextPosition(SwingConstants.LEADING);
lbl.setOpaque(false);
lbl.setFont(lbl.getFont().deriveFont(Font.BOLD));
return lbl;
}
@Override
public void notifyStatusChanged(final DownloadState newState) {
assert SwingUtilities.isEventDispatchThread();
final DownloadState oldState = downloaderState;
downloaderState = newState;
firePropertyChange(CP_STATE_CHANGED, oldState, newState);
}
@Override
public void doScannerFinished(final ImagesDownloadList aList) {
files = aList;
downloadButton.setEnabled(files != null && files.size() > 0);
captionLabel.setIcon(null);
captionLabel.setText(String.format("%s = %d",
getProgressCaption(),
files == null ? 0 : files.size())
);
}
void refreshDownloadList(CardImageDisplayMode aMode) {
doCancel();
this.displayMode = aMode;
buildDownloadImagesList();
}
@Override
public void setMessage(final String message) {
mainPanel.setMessage(message);
}
@Override
public void showProgress(int count, int total) {
progressBar.setValue(count);
captionLabel.setText(String.format("%s = %d",
getProgressCaption(),
total - getCustomCount(count))
);
}
@Override
public void resetProgress() {
progressBar.setValue(0);
progressBar.setString(null);
}
protected String doFileDownloadAndGetName(final DownloadableFile file) throws IOException {
file.doDownload();
if (file instanceof CardImageFile) {
return ((CardImageFile) file).getCardName();
} else {
return "";
}
}
protected int getCustomCount(int countInteger) {
return countInteger;
}
public static Stream<MagicCardDefinition> getCards(Collection<MagicCardDefinition> cards, Date aDate, CardImageDisplayMode mode) {
return cards.stream().filter(card -> CardDefinitions.requiresNewImageDownload(card, aDate));
}
void setLocked(boolean b) {
downloadButton.setEnabled(!b && files != null && !files.isEmpty());
}
@Override
public void setEnabled(boolean b) {
super.setEnabled(b);
downloadButton.setEnabled(b && imagesScanner.isDone());
progressBar.setEnabled(b);
captionLabel.setEnabled(b);
}
}