package magic.ui.widget.duel.viewer;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import magic.data.GeneralConfig;
import magic.data.MagicIcon;
import magic.model.MagicCardDefinition;
import magic.ui.FontsAndBorders;
import magic.ui.MagicImages;
import magic.ui.dialog.prefs.ImageSizePresets;
import magic.ui.helpers.ImageHelper;
import magic.ui.utility.MagicStyle;
import magic.ui.widget.cards.table.ICardSelectionListener;
import magic.ui.widget.throbber.AbstractThrobber;
import magic.ui.widget.throbber.ImageThrobber;
import net.miginfocom.swing.MigLayout;
@SuppressWarnings("serial")
public class CardViewer extends JPanel implements ICardSelectionListener {
private static final Image TRANSFORM_ICON =
MagicImages.getIcon(MagicIcon.CYCLE).getImage();
private final Dimension IMAGE_SIZE = getImageSize();
private Image thisImage;
private Image gsImage;
private boolean isMouseOver = false;
private int defaultCursor = Cursor.DEFAULT_CURSOR;
private MagicCardDefinition thisCard = MagicCardDefinition.UNKNOWN;
private boolean isSwitchedAspect = false;
private CardImageWorker worker;
private MagicCardDefinition cardPending = MagicCardDefinition.UNKNOWN;
private final Timer aTimer = getCooldownTimer();
private long lastTime = System.currentTimeMillis();
private boolean isImagePending;
private final AbstractThrobber throbber;
private final JLabel cardLabel;
public CardViewer() {
setPreferredSize(IMAGE_SIZE);
setMinimumSize(IMAGE_SIZE);
setMaximumSize(IMAGE_SIZE);
setBackground(MagicStyle.getTranslucentColor(Color.DARK_GRAY, 140));
throbber = new ImageThrobber.Builder(MagicImages.loadImage("round-shield.png")).build();
throbber.setVisible(false);
cardLabel = getLabel("");
setLayout(new MigLayout("flowy, aligny center", "[fill, grow]"));
add(throbber);
add(cardLabel);
setDefaultImage();
setMouseListener();
}
private void setDefaultImage() {
setImage(getCardImage(MagicCardDefinition.UNKNOWN, getImageSize()));
}
private JLabel getLabel(String text) {
JLabel lbl = new JLabel(text);
lbl.setForeground(Color.WHITE);
lbl.setFont(FontsAndBorders.FONT2);
lbl.setHorizontalAlignment(SwingConstants.CENTER);
return lbl;
}
private void showColorImageIfGreyscale(boolean b) {
isMouseOver = b;
if (thisCard.isInvalid() || thisCard.hasMultipleAspects()) {
repaint();
}
}
private void setMouseListener() {
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (thisCard.hasMultipleAspects()) {
switchCardAspect();
}
}
@Override
public void mouseEntered(MouseEvent e) {
defaultCursor = thisCard.hasMultipleAspects()
? Cursor.HAND_CURSOR
: Cursor.DEFAULT_CURSOR;
setCursor(Cursor.getPredefinedCursor(defaultCursor));
showColorImageIfGreyscale(true);
}
@Override
public void mouseExited(MouseEvent e) {
if (isSwitchedAspect) {
switchCardAspect();
}
showColorImageIfGreyscale(false);
}
});
}
private void switchCardAspect() {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
if (thisCard.isDoubleFaced()) {
setCard(thisCard.getTransformedDefinition());
} else if (thisCard.isFlipCard()) {
setCard(thisCard.getFlippedDefinition());
}
isSwitchedAspect = !isSwitchedAspect;
setCursor(Cursor.getPredefinedCursor(defaultCursor));
}
public final void setCard(final MagicCardDefinition aCard) {
if (aCard == null) {
System.err.println("CardViewer.setCard() : aCard is null!");
return;
}
if (aCard == thisCard) {
return;
}
cardLabel.setText("..." + aCard.getName() + "...");
boolean isCooldownRequired = System.currentTimeMillis() - lastTime < 120;
lastTime = System.currentTimeMillis();
if (isCooldownRequired && worker != null) {
cardPending = aCard;
aTimer.restart();
setImage(null);
return;
}
if (worker != null && !worker.isDone()) {
worker.cancel(true);
setImage(null);
}
thisCard = aCard;
worker = new CardImageWorker(this, aCard);
worker.execute();
}
@Override
public void newCardSelected(final MagicCardDefinition card) {
SwingUtilities.invokeLater(() -> {
setCard(card);
});
}
void setImage(final Image aImage) {
if (aImage == null) {
isImagePending = true;
throbber.setVisible(true);
cardLabel.setVisible(true);
} else {
thisImage = aImage;
gsImage = thisCard.isInvalid() && aImage != MagicImages.MISSING_CARD
? ImageHelper.getGreyScaleImage(aImage)
: null;
isImagePending = false;
throbber.setVisible(false);
cardLabel.setVisible(false);
}
repaint();
}
@Override
public void paintComponent(final Graphics g) {
if (thisImage != null) {
final Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(gsImage != null && !isMouseOver ? gsImage : thisImage, 0, 0, null);
if (thisCard.hasMultipleAspects() && !isMouseOver) {
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.4f));
g2d.drawImage(TRANSFORM_ICON, (getWidth() - TRANSFORM_ICON.getWidth(null)) / 2, 60, null);
}
}
if (isImagePending) {
super.paintComponent(g);
}
}
static Dimension getImageSize() {
ImageSizePresets sizePreset = GeneralConfig.getInstance().getPreferredImageSize();
if (sizePreset == ImageSizePresets.SIZE_ORIGINAL) {
return ImageSizePresets.SIZE_312x445.getSize();
} else if (sizePreset.getSize().width < ImageSizePresets.SIZE_312x445.getSize().width) {
return ImageSizePresets.SIZE_312x445.getSize();
} else {
return sizePreset.getSize();
}
}
static Image getCardImage(MagicCardDefinition aCard, Dimension prefSize) {
if (aCard == null) {
aCard = MagicCardDefinition.UNKNOWN;
}
BufferedImage image = MagicImages.getCardImage(aCard);
if (image.getWidth() != prefSize.width || image.getHeight() != prefSize.height) {
image = ImageHelper.scale(image, prefSize.width, prefSize.height);
}
return image;
}
private Timer getCooldownTimer() {
Timer t = new Timer(150, (e) -> {
setCard(cardPending);
});
t.setRepeats(false);
return t;
}
public static Dimension getSidebarImageSize() {
Dimension size = ImageSizePresets.getDefaultSize();
return size.width < ImageSizePresets.SIZE_312x445.getSize().width
? ImageSizePresets.SIZE_312x445.getSize()
: size;
}
}