package magic.ui.screen.duel.player;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import magic.model.player.IPlayerProfileListener;
import magic.model.player.PlayerProfile;
import magic.model.player.PlayerProfiles;
import magic.translate.MText;
import magic.ui.FontsAndBorders;
import magic.ui.MagicImages;
import magic.ui.ScreenController;
import magic.ui.helpers.KeyEventAction;
import magic.ui.helpers.MouseHelper;
import magic.ui.screen.HeaderFooterScreen;
import magic.ui.screen.interfaces.IAvatarImageConsumer;
import magic.ui.screen.interfaces.IThemeStyle;
import magic.ui.screen.widget.ActionBarButton;
import magic.ui.screen.widget.MenuButton;
import magic.ui.theme.Theme;
import magic.ui.utility.MagicStyle;
import magic.ui.widget.TexturedPanel;
import net.miginfocom.swing.MigLayout;
@SuppressWarnings("serial")
public abstract class SelectPlayerScreen extends HeaderFooterScreen
implements IAvatarImageConsumer {
// translatable strings
private static final String _S1 = "Avatar";
private static final String _S2 = "Choose an avatar image for the selected player profile.";
private static final String _S3 = "There must be at least one player defined.";
private static final String _S4 = "This will delete the <b>%s</b> player profile.";
private static final String _S5 = "Delete Player?";
private static final String _S6 = "Delete";
private static final String _S7 = "Cancel";
private static final String _S9 = "Select";
private static final String _S10 = "Settings";
private static final String _S11 = "Update player profile settings.";
private static final String _S12 = "New";
private static final String _S13 = "Create a new player profile.";
private static final String _S15 = "Delete selected player profile (confirmation required).";
private static final String _S16 = "All associated information such as player stats will also be removed.";
private static final String _S17 = "This action cannot be undone!";
private final List<IPlayerProfileListener> listeners = new ArrayList<>();
private final JList<? extends PlayerProfile> playersJList;
protected HashMap<String, PlayerProfile> profilesMap = new HashMap<>();
protected abstract void createDefaultPlayerProfiles() throws IOException;
protected abstract int getPreferredWidth();
protected abstract void refreshProfilesJList();
protected abstract void refreshProfilesJList(final PlayerProfile playerProfile);
protected abstract HashMap<String, PlayerProfile> getPlayerProfilesMap();
protected abstract void doNewPlayerAction();
protected abstract void doEditPlayerAction();
// CTR
protected SelectPlayerScreen(String name, final JList<? extends PlayerProfile> playersJList) {
super(name);
this.playersJList = playersJList;
this.playersJList.addMouseListener(new DoubleClickAdapter());
setMainContent(new ScreenContent());
setFooter();
setKeyEvents();
}
private void setFooter() {
setLeftFooter(MenuButton.getCloseScreenButton(MText.get(_S7)));
setRightFooter(MenuButton.build(this::doNextAction, MText.get(_S9)));
addToFooter(MenuButton.build(this::doEditPlayerAction,
MText.get(_S10), MText.get(_S11)
),
MenuButton.build(this::doNewPlayerAction,
MText.get(_S12), MText.get(_S13)
),
MenuButton.build(this::deleteSelectedPlayer,
MText.get(_S6), MText.get(_S15)
),
new SelectAvatarActionButton()
);
}
private void setKeyEvents() {
KeyEventAction.doAction(this, this::doNextAction)
.onFocus(0, KeyEvent.VK_ENTER);
}
protected void setFocusInProfilesJList(final JList<? extends PlayerProfile> profilesJList) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
profilesJList.requestFocusInWindow();
}
});
}
protected void setSelectedListItem(final PlayerProfile playerProfile) {
if (playerProfile == null) {
playersJList.setSelectedIndex(0);
} else {
playersJList.setSelectedValue(profilesMap.get(playerProfile.getId()), true);
}
setFocusInProfilesJList(playersJList);
}
protected List<PlayerProfile> getSortedPlayersList() {
profilesMap = getPlayerProfilesMap();
final List<PlayerProfile> profilesByName = new ArrayList<>(profilesMap.values());
Collections.sort(profilesByName, new Comparator<PlayerProfile>() {
@Override
public int compare(PlayerProfile o1, PlayerProfile o2) {
return o1.getPlayerName().compareToIgnoreCase(o2.getPlayerName());
}
});
return profilesByName;
}
protected void updateAvatarImage(final Path imagePath, final PlayerProfile playerProfile) {
final Path targetPath = playerProfile.getProfilePath().resolve("player.avatar");
try {
Files.copy(imagePath, targetPath, StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
MagicImages.getClearAvatarsCache();
}
@Override
public void setSelectedAvatarPath(final Path imagePath) {
final PlayerProfile profile = getSelectedPlayer();
updateAvatarImage(imagePath, profile);
refreshProfilesJList(profile);
notifyPlayerUpdated(profile);
}
protected PlayerProfile getSelectedPlayer() {
return playersJList.getSelectedValue();
}
protected class SelectAvatarActionButton extends ActionBarButton {
public SelectAvatarActionButton() {
super(MText.get(_S1), MText.get(_S2), new SelectAvatarAction());
}
}
private class SelectAvatarAction extends AbstractAction {
@Override
public void actionPerformed(ActionEvent e) {
ScreenController.showAvatarImagesScreen(SelectPlayerScreen.this);
}
}
private boolean isDeletePlayerConfirmedByUser(final PlayerProfile profile) {
final int action = JOptionPane.showOptionDialog(ScreenController.getFrame(),
String.format("<html>%s<br>%s<br><br><b>%s</b></html>",
MText.get(_S4, profile.getPlayerName()),
MText.get(_S16),
MText.get(_S17)),
MText.get(_S5),
JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE,
null,
new String[]{MText.get(_S6), MText.get(_S7)}, MText.get(_S7));
return (action == JOptionPane.YES_OPTION);
}
private void deleteSelectedPlayer() {
final PlayerProfile condemnedPlayer = getSelectedPlayer();
if (PlayerProfiles.canDeleteProfile(condemnedPlayer)) {
if (isDeletePlayerConfirmedByUser(condemnedPlayer)) {
PlayerProfiles.deletePlayer(condemnedPlayer);
refreshProfilesJList();
notifyPlayerDeleted(condemnedPlayer);
}
} else {
ScreenController.showWarningMessage(MText.get(_S3));
}
}
private class ScreenContent extends JPanel {
public ScreenContent() {
setOpaque(false);
setLayout(new MigLayout("insets 2, center, center"));
add(new ContainerPanel(playersJList), "w " + getPreferredWidth() + "!, h 80%");
}
}
protected class ContainerPanel extends TexturedPanel implements IThemeStyle {
public ContainerPanel(final JList<? extends PlayerProfile> profilesJList) {
profilesJList.setOpaque(false);
refreshStyle();
setLayout(new MigLayout("insets 0, gap 0, flowy"));
add(new ScrollPane(profilesJList), "w 100%, h 100%");
}
@Override
public final void refreshStyle() {
final Color refBG = MagicStyle.getTheme().getColor(Theme.COLOR_TITLE_BACKGROUND);
final Color thisBG = MagicStyle.getTranslucentColor(refBG, 200);
setBackground(thisBG);
setBorder(FontsAndBorders.BLACK_BORDER);
}
private class ScrollPane extends JScrollPane {
public ScrollPane(final JList<? extends PlayerProfile> profilesJList) {
setViewportView(profilesJList);
setBorder(BorderFactory.createEmptyBorder());
setOpaque(false);
getViewport().setOpaque(false);
}
}
}
protected void doNextAction() {
MouseHelper.showBusyCursor();
notifyPlayerSelected(getSelectedPlayer());
ScreenController.closeActiveScreen(false);
MouseHelper.showDefaultCursor();
}
protected class DoubleClickAdapter extends MouseAdapter {
@Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
doNextAction();
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
}
}
public synchronized void addListener(IPlayerProfileListener obj) {
listeners.add(obj);
}
public synchronized void removeListener(IPlayerProfileListener obj) {
listeners.remove(obj);
}
protected synchronized void notifyPlayerUpdated(final PlayerProfile player) {
for (final IPlayerProfileListener listener : listeners) {
listener.PlayerProfileUpdated(player);
}
}
private synchronized void notifyPlayerDeleted(final PlayerProfile player) {
for (final IPlayerProfileListener listener : listeners) {
listener.PlayerProfileDeleted(player);
}
}
private synchronized void notifyPlayerSelected(final PlayerProfile player) {
for (final IPlayerProfileListener listener : listeners) {
listener.PlayerProfileSelected(player);
}
}
protected JList<? extends PlayerProfile> getJList() {
return playersJList;
}
}