shuffle.fwk.service.teams.EditTeamService.java Source code

Java tutorial

Introduction

Here is the source code for shuffle.fwk.service.teams.EditTeamService.java

Source

/*  ShuffleMove - A program for identifying and simulating ideal moves in the game
 *  called Pokemon Shuffle.
 *  
 *  Copyright (C) 2015  Andrew Meyers
 *  
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *  This program 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
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package shuffle.fwk.service.teams;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.logging.Logger;

import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.JTextField;
import javax.swing.ScrollPaneConstants;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingConstants;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;

import org.apache.commons.lang3.text.WordUtils;

import shuffle.fwk.config.ConfigManager;
import shuffle.fwk.config.EntryType;
import shuffle.fwk.config.manager.ImageManager;
import shuffle.fwk.config.manager.RosterManager;
import shuffle.fwk.config.manager.SpeciesManager;
import shuffle.fwk.config.manager.StageManager;
import shuffle.fwk.config.manager.TeamManager;
import shuffle.fwk.data.Effect;
import shuffle.fwk.data.PkmType;
import shuffle.fwk.data.Species;
import shuffle.fwk.data.SpeciesPaint;
import shuffle.fwk.data.Stage;
import shuffle.fwk.data.Team;
import shuffle.fwk.data.TeamImpl;
import shuffle.fwk.gui.EffectChooser;
import shuffle.fwk.gui.Indicator;
import shuffle.fwk.gui.MultiListener;
import shuffle.fwk.gui.PressOrClickMouseAdapter;
import shuffle.fwk.gui.PressToggleMouseAdapter;
import shuffle.fwk.gui.StageChooser;
import shuffle.fwk.gui.TypeChooser;
import shuffle.fwk.gui.WrapLayout;
import shuffle.fwk.gui.user.MultiListenerUser;
import shuffle.fwk.gui.user.StageIndicatorUser;
import shuffle.fwk.i18n.I18nUser;
import shuffle.fwk.service.BaseService;
import shuffle.fwk.service.DisposeAction;
import shuffle.fwk.service.roster.EditRosterService;

/**
 * @author Andrew Meyers
 *         
 */
public class EditTeamService extends BaseService<EditTeamServiceUser>
        implements StageIndicatorUser, I18nUser, MultiListenerUser {
    private static final Logger LOG = Logger.getLogger(EditTeamService.class.getName());

    // Config keys
    private static final String KEY_ROSTER_CELL_OUTLINE_THICK = EditRosterService.KEY_ROSTER_CELL_OUTLINE_THICK;
    private static final String KEY_ROSTER_CELL_BORDER_THICK = EditRosterService.KEY_ROSTER_CELL_BORDER_THICK;
    private static final String KEY_ROSTER_CELL_MARGIN_THICK = EditRosterService.KEY_ROSTER_CELL_MARGIN_THICK;
    private static final String KEY_EDIT_TEAM_WIDTH = "EDIT_TEAM_WIDTH";
    private static final String KEY_EDIT_TEAM_HEIGHT = "EDIT_TEAM_HEIGHT";

    // i18n keys
    private static final String KEY_NO_BINDINGS = "error.nobindings";
    private static final String KEY_NONE_SELECTED = "text.noneselected";
    private static final String KEY_SELECTED = "text.selected";
    private static final String KEY_SURVIVAL = "text.survival";
    private static final String KEY_OK = "button.ok";
    private static final String KEY_APPLY = "button.apply";
    private static final String KEY_CANCEL = "button.cancel";
    private static final String KEY_NONE = "text.none";
    private static final String KEY_ACTIVE = "text.active";
    private static final String KEY_MAKE_DEFAULT = "button.makedefault";
    private static final String KEY_MEGA_LABEL = "text.megalabel";
    private static final String KEY_MEGA_FILTER = "text.megafilter";
    private static final String KEY_CLEAR_TEAM = "button.clearteam";
    private static final String KEY_WOOD = "text.wood";
    private static final String KEY_METAL = "text.metal";
    private static final String KEY_COIN = "text.coin";
    private static final String KEY_FREEZE = "text.freeze";
    private static final String KEY_REMOVE = "button.remove";
    private static final String KEY_ADD = "button.add";
    private static final String KEY_TITLE = "text.title";
    private static final String KEY_LEVEL = "text.level";
    private static final String KEY_NAME = "text.name";
    private static final String KEY_TYPE = "text.type";
    private static final String KEY_TYPE_TOOLTIP = "tooltip.type";
    private static final String KEY_LEVEL_TOOLTIP = "tooltip.level";
    private static final String KEY_NAME_TOOLTIP = "tooltip.name";
    private static final String KEY_MEGA_FILTER_TOOLTIP = "tooltip.megafilter";
    private static final String KEY_EFFECT_FILTER_TOOLTIP = "tooltip.effectfilter";
    private static final String KEY_MAKE_DEFAULT_TOOLTIP = "tooltip.makedefault";
    private static final String KEY_MEGA_TOOLTIP = "tooltip.mega";
    private static final String KEY_ACTIVE_TOOLTIP = "tooltip.active";
    private static final String KEY_MEGA_PROGRESS_TOOLTIP = "tooltip.megaprogress";
    private static final String KEY_CLEAR_TEAM_TOOLTIP = "tooltip.clearteam";
    private static final String KEY_WOOD_TOOLTIP = "tooltip.wood";
    private static final String KEY_METAL_TOOLTIP = "tooltip.metal";
    private static final String KEY_COIN_TOOLTIP = "tooltip.coin";
    private static final String KEY_FREEZE_TOOLTIP = "tooltip.freeze";
    private static final String KEY_REMOVE_TOOLTIP = "tooltip.remove";
    private static final String KEY_KEYBINDS_TOOLTIP = "tooltip.keybinds";
    private static final String KEY_ADD_TOOLTIP = "tooltip.add";
    private static final String KEY_SELECTED_TOOLTIP = "tooltip.selected";
    private static final String KEY_SURVIVAL_TOOLTIP = "tooltip.survival";
    private static final String KEY_OK_TOOLTIP = "tooltip.ok";
    private static final String KEY_APPLY_TOOLTIP = "tooltip.apply";
    private static final String KEY_CANCEL_TOOLTIP = "tooltip.cancel";

    // Defaults
    private static final int DEFAULT_BORDER_WIDTH = EditRosterService.DEFAULT_BORDER_WIDTH;
    private static final int DEFAULT_BORDER_OUTLINE = EditRosterService.DEFAULT_BORDER_OUTLINE;
    private static final int DEFAULT_BORDER_MARGIN = EditRosterService.DEFAULT_BORDER_MARGIN;

    // components and data
    private TypeChooser typeChooser = null;
    private JLabel selectedDisplayLabel = null;
    private JPanel rosterPanel = null;
    private JPanel teamPanel = null;
    private JSpinner levelSpinner = null;
    private JTextField textField = null;
    private JCheckBox megaFilter = null;
    private EffectChooser effectFilter = null;
    private JDialog d = null;
    private TeamManager myData = null;
    private Map<String, ItemListener> nameToItemListenerMap = new HashMap<String, ItemListener>();
    private Map<String, JComboBox<Character>> nameToKeybindComboboxMap = new HashMap<String, JComboBox<Character>>();
    private Stage curStage = StageManager.DEFAULT_STAGE;
    private Team prevTeam = null;
    private JComboBox<String> megaChooser;
    private JCheckBox megaActive;
    private boolean wasMegaActive = false;
    private JComboBox<Integer> megaProgressChooser;
    private int megaProgress = 0;
    private int megaThreshold = 0;
    private JCheckBox woodCheckBox;
    private JCheckBox metalCheckBox;
    private JCheckBox coinCheckBox;
    private JCheckBox freezeCheckBox;
    private StageChooser stageChooser;
    private JScrollPane rosterScrollPane;
    private Supplier<Dimension> getMinUpperPanel = null;
    private JCheckBox survivalMode;

    private JPanel selectedComponent = null;
    private Species selectedSpecies = null;

    private ItemListener optionListener = null;

    /*
     * (non-Javadoc)
     * @see shuffle.fwk.service.BaseService#getUserClass()
     */
    @Override
    protected Class<EditTeamServiceUser> getUserClass() {
        return EditTeamServiceUser.class;
    }

    /*
     * (non-Javadoc)
     * @see shuffle.fwk.service.BaseService#setupGUI()
     */
    @Override
    public void onSetupGUI() {
        d = new JDialog(getOwner(), getString(KEY_TITLE));
        d.setLayout(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();
        c.fill = GridBagConstraints.HORIZONTAL;
        c.weightx = 1.0;
        c.weighty = 0.0;
        c.gridx = 1;
        c.gridy = 1;
        c.gridwidth = 2;
        c.gridheight = 1;
        d.add(makeUpperPanel(), c);

        c.gridy += 1;
        c.fill = GridBagConstraints.BOTH;
        c.weighty = 1.0;
        c.gridwidth = 1;
        d.add(makeRosterPanel(), c);

        c.gridx += 1;
        c.weightx = 0.0;
        d.add(makeTeamPanel(), c);
        c.weightx = 1.0;

        c.gridx = 1;
        c.gridy += 1;
        c.gridwidth = 2;
        c.fill = GridBagConstraints.HORIZONTAL;
        c.weighty = 0.0;
        d.add(makeBottomPanel(), c);

        ConfigManager preferencesManager = getUser().getPreferencesManager();
        int defaultWidth = preferencesManager.getIntegerValue(KEY_POPUP_WIDTH, DEFAULT_POPUP_WIDTH);
        int defaultHeight = preferencesManager.getIntegerValue(KEY_POPUP_HEIGHT, DEFAULT_POPUP_HEIGHT);
        int width = preferencesManager.getIntegerValue(KEY_EDIT_TEAM_WIDTH, defaultWidth);
        int height = preferencesManager.getIntegerValue(KEY_EDIT_TEAM_HEIGHT, defaultHeight);
        d.repaint();
        d.pack();
        d.setMinimumSize(new Dimension(getMinimumWidth(), DEFAULT_POPUP_HEIGHT));
        d.setSize(new Dimension(width, height));
        d.setLocationRelativeTo(null);
        d.setResizable(true);
        addActionListeners();

        setDialog(d);
    }

    private int getMinimumWidth() {
        int ret = 0;
        if (getMinUpperPanel != null) {
            ret += Math.max(0, getMinUpperPanel.get().width);
        }
        return Math.max(ret, DEFAULT_POPUP_WIDTH);
    }

    @Override
    protected void onLaunch() {
        d.addComponentListener(new ComponentAdapter() {
            @Override
            public void componentResized(ComponentEvent ev) {
                ConfigManager preferencesManager = getUser().getPreferencesManager();
                Dimension dim = d.getSize();
                preferencesManager.setEntry(EntryType.INTEGER, KEY_EDIT_TEAM_WIDTH, dim.width);
                preferencesManager.setEntry(EntryType.INTEGER, KEY_EDIT_TEAM_HEIGHT, dim.height);
            }
        });
    }

    private void addActionListeners() {
        MultiListener listener = new MultiListener(this);
        typeChooser.addItemListener(listener);
        textField.getDocument().addDocumentListener(listener);
        levelSpinner.getModel().addChangeListener(listener);
        megaFilter.addItemListener(listener);
        effectFilter.addItemListener(listener);
        survivalMode.addItemListener(new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent e) {
                updateTeamPanel();
            }
        });
    }

    private Component makeUpperPanel() {
        JPanel ret = new JPanel(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();
        c.fill = GridBagConstraints.HORIZONTAL;
        c.weightx = 1.0;
        c.weighty = 0.0;
        c.gridx = 1;
        c.gridy = 1;
        c.gridwidth = 1;
        c.gridheight = 1;

        c.gridx += 1;
        c.weightx = 0.0;
        JPanel typePanel = new JPanel();
        typePanel.add(new JLabel(getString(KEY_TYPE)));
        typeChooser = new TypeChooser(true);
        typePanel.add(typeChooser);
        typePanel.setToolTipText(getString(KEY_TYPE_TOOLTIP));
        typeChooser.setToolTipText(getString(KEY_TYPE_TOOLTIP));
        ret.add(typePanel, c);

        c.gridx += 1;
        c.weightx = 0.0;
        JPanel levelPanel = new JPanel();
        levelPanel.add(new JLabel(getString(KEY_LEVEL)));
        SpinnerNumberModel snm = new SpinnerNumberModel(0, 0, Species.MAX_LEVEL, 1);
        levelSpinner = new JSpinner(snm);
        levelPanel.add(levelSpinner);
        levelPanel.setToolTipText(getString(KEY_LEVEL_TOOLTIP));
        levelSpinner.setToolTipText(getString(KEY_LEVEL_TOOLTIP));
        ret.add(levelPanel, c);

        c.gridx += 1;
        c.weightx = 1.0;
        JPanel stringPanel = new JPanel(new GridBagLayout());
        GridBagConstraints sc = new GridBagConstraints();
        sc.fill = GridBagConstraints.HORIZONTAL;
        sc.gridx = 1;
        stringPanel.add(new JLabel(getString(KEY_NAME)), sc);
        textField = new JTextField();
        sc.gridx += 1;
        sc.weightx = 1.0;
        sc.insets = new Insets(0, 5, 0, 5);
        stringPanel.add(textField, sc);
        stringPanel.setToolTipText(getString(KEY_NAME_TOOLTIP));
        textField.setToolTipText(getString(KEY_NAME_TOOLTIP));
        ret.add(stringPanel, c);

        c.gridx += 1;
        c.weightx = 0.0;
        megaFilter = new JCheckBox(getString(KEY_MEGA_FILTER));
        megaFilter.setToolTipText(getString(KEY_MEGA_FILTER_TOOLTIP));
        ;
        ret.add(megaFilter, c);

        c.gridx += 1;
        c.weightx = 0.0;
        effectFilter = new EffectChooser(false, EffectChooser.DefaultEntry.NO_FILTER);
        effectFilter.setToolTipText(getString(KEY_EFFECT_FILTER_TOOLTIP));
        ret.add(effectFilter, c);

        c.gridx += 1;
        c.weightx = 0.0;
        @SuppressWarnings("serial")
        JButton copyToLauncher = new JButton(new AbstractAction(getString(KEY_MAKE_DEFAULT)) {
            @Override
            public void actionPerformed(ActionEvent e) {
                makeTeamDefault();
            }
        });
        copyToLauncher.setToolTipText(getString(KEY_MAKE_DEFAULT_TOOLTIP));
        ret.add(copyToLauncher, c);

        getMinUpperPanel = new Supplier<Dimension>() {

            @Override
            public Dimension get() {
                Dimension ret = new Dimension(10 + 50, 0);
                for (Component c : new Component[] { typePanel, levelPanel, stringPanel, megaFilter, effectFilter,
                        copyToLauncher }) {
                    Dimension temp = c.getPreferredSize();
                    int width = temp.width + ret.width;
                    int height = Math.max(temp.height, ret.height);
                    ret.setSize(width, height);
                }
                return ret;
            }
        };

        return ret;
    }

    /**
     * 
     */
    protected void makeTeamDefault() {
        PkmType t = getCurrentStage().getType();
        Stage fallbackStage = new Stage(t);
        myData.setTeamForStage(getCurrentTeamImpl(), fallbackStage);
        updateTeamPanel();
    }

    @SuppressWarnings("serial")
    private Component makeRosterPanel() {
        rosterPanel = new JPanel(new WrapLayout()) {
            // Fix to make it play nice with the scroll bar.
            @Override
            public Dimension getPreferredSize() {
                Dimension d = super.getPreferredSize();
                d.width = (int) (d.getWidth() - 20);
                return d;
            }
        };
        rosterScrollPane = new JScrollPane(rosterPanel, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
                ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        rosterScrollPane.addComponentListener(new ComponentAdapter() {
            @Override
            public void componentResized(ComponentEvent e) {
                rosterScrollPane.revalidate();
            }
        });
        rosterScrollPane.getVerticalScrollBar().setUnitIncrement(27);
        return rosterScrollPane;
    }

    @SuppressWarnings("serial")
    private Component makeTeamPanel() {

        JPanel firstOptionRow = new JPanel(new GridBagLayout());
        GridBagConstraints rowc = new GridBagConstraints();
        rowc.fill = GridBagConstraints.HORIZONTAL;
        rowc.weightx = 0.0;
        rowc.weighty = 0.0;

        rowc.weightx = 1.0;
        rowc.gridx = 1;
        stageChooser = new StageChooser(this);
        firstOptionRow.add(stageChooser, rowc);
        rowc.weightx = 0.0;

        JPanel secondOptionRow = new JPanel(new GridBagLayout());

        rowc.gridx = 1;
        JLabel megaLabel = new JLabel(getString(KEY_MEGA_LABEL));
        megaLabel.setToolTipText(getString(KEY_MEGA_TOOLTIP));
        secondOptionRow.add(megaLabel, rowc);

        rowc.gridx = 2;
        megaChooser = new JComboBox<String>();
        megaChooser.setToolTipText(getString(KEY_MEGA_TOOLTIP));
        secondOptionRow.add(megaChooser, rowc);

        rowc.gridx = 3;
        JPanel progressPanel = new JPanel(new BorderLayout());
        megaActive = new JCheckBox(getString(KEY_ACTIVE));
        megaActive.setSelected(false);
        megaActive.setToolTipText(getString(KEY_ACTIVE_TOOLTIP));
        progressPanel.add(megaActive, BorderLayout.WEST);
        megaProgressChooser = new JComboBox<Integer>();
        progressPanel.add(megaProgressChooser, BorderLayout.EAST);
        megaProgressChooser.setToolTipText(getString(KEY_MEGA_PROGRESS_TOOLTIP));
        secondOptionRow.add(progressPanel, rowc);

        JPanel thirdOptionRow = new JPanel(new GridBagLayout());

        rowc.gridx = 1;
        JButton clearTeamButton = new JButton(getString(KEY_CLEAR_TEAM));
        clearTeamButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                clearTeam();
            }
        });
        clearTeamButton.setToolTipText(getString(KEY_CLEAR_TEAM_TOOLTIP));
        thirdOptionRow.add(clearTeamButton, rowc);

        rowc.gridx = 2;
        woodCheckBox = new JCheckBox(getString(KEY_WOOD));
        woodCheckBox.setToolTipText(getString(KEY_WOOD_TOOLTIP));
        thirdOptionRow.add(woodCheckBox, rowc);

        rowc.gridx = 3;
        metalCheckBox = new JCheckBox(getString(KEY_METAL));
        metalCheckBox.setToolTipText(getString(KEY_METAL_TOOLTIP));
        thirdOptionRow.add(metalCheckBox, rowc);

        rowc.gridx = 4;
        coinCheckBox = new JCheckBox(getString(KEY_COIN));
        coinCheckBox.setToolTipText(getString(KEY_COIN_TOOLTIP));
        thirdOptionRow.add(coinCheckBox, rowc);

        rowc.gridx = 5;
        freezeCheckBox = new JCheckBox(getString(KEY_FREEZE));
        freezeCheckBox.setToolTipText(getString(KEY_FREEZE_TOOLTIP));
        thirdOptionRow.add(freezeCheckBox, rowc);

        JPanel topPart = new JPanel(new GridBagLayout());
        GridBagConstraints topC = new GridBagConstraints();
        topC.fill = GridBagConstraints.HORIZONTAL;
        topC.weightx = 0.0;
        topC.weighty = 0.0;
        topC.gridx = 1;
        topC.gridy = 1;
        topC.gridwidth = 1;
        topC.gridheight = 1;
        topC.anchor = GridBagConstraints.CENTER;

        topC.gridy = 1;
        topPart.add(firstOptionRow, topC);
        topC.gridy = 2;
        topPart.add(secondOptionRow, topC);
        topC.gridy = 3;
        topPart.add(thirdOptionRow, topC);

        addOptionListeners();

        teamPanel = new JPanel(new WrapLayout()) {
            // Fix to make it play nice with the scroll bar.
            @Override
            public Dimension getPreferredSize() {
                Dimension d = super.getPreferredSize();
                d.width = (int) (d.getWidth() - 20);
                return d;
            }
        };
        final JScrollPane scrollPane = new JScrollPane(teamPanel, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
                ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER) {
            @Override
            public Dimension getMinimumSize() {
                Dimension d = super.getMinimumSize();
                d.width = topPart.getMinimumSize().width;
                d.height = rosterScrollPane.getPreferredSize().height - topPart.getPreferredSize().height;
                return d;
            }

            @Override
            public Dimension getPreferredSize() {
                Dimension d = super.getPreferredSize();
                d.width = topPart.getMinimumSize().width;
                d.height = rosterScrollPane.getPreferredSize().height - topPart.getPreferredSize().height;
                return d;
            }
        };
        scrollPane.addComponentListener(new ComponentAdapter() {
            @Override
            public void componentResized(ComponentEvent e) {
                scrollPane.revalidate();
            }
        });
        scrollPane.getVerticalScrollBar().setUnitIncrement(27);

        JPanel ret = new JPanel(new GridBagLayout());
        GridBagConstraints rc = new GridBagConstraints();
        rc.fill = GridBagConstraints.VERTICAL;
        rc.weightx = 0.0;
        rc.weighty = 0.0;
        rc.gridx = 1;
        rc.gridy = 1;
        rc.insets = new Insets(5, 5, 5, 5);
        ret.add(topPart, rc);
        rc.gridy += 1;
        rc.weightx = 0.0;
        rc.weighty = 1.0;
        rc.insets = new Insets(0, 0, 0, 0);
        ret.add(scrollPane, rc);
        return ret;
    }

    private Component makeBottomPanel() {
        JPanel ret = new JPanel(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();
        c.fill = GridBagConstraints.NONE;
        c.weightx = 1.0;
        c.weighty = 0.0;
        c.gridx = 1;
        c.gridy = 1;
        c.gridwidth = 1;
        c.gridheight = 1;

        c.anchor = GridBagConstraints.LINE_START;
        c.weightx = 0.0;
        c.gridx += 1;
        c.insets = new Insets(0, 10, 0, 10);
        selectedDisplayLabel = new JLabel(getString(KEY_NONE_SELECTED));
        selectedDisplayLabel.setToolTipText(getString(KEY_SELECTED_TOOLTIP));
        ret.add(selectedDisplayLabel, c);

        c.anchor = GridBagConstraints.LINE_END;
        c.weightx = 1.0;
        c.gridx++;
        survivalMode = new JCheckBox(getString(KEY_SURVIVAL));
        JPanel survivalModePanel = new JPanel(new BorderLayout());
        survivalModePanel.add(survivalMode, BorderLayout.WEST);
        survivalMode.setToolTipText(getString(KEY_SURVIVAL_TOOLTIP));
        ret.add(survivalModePanel, c);

        c.anchor = GridBagConstraints.LINE_END;
        c.weightx = 0.0;
        c.gridx += 1;
        JButton okButton = new JButton(getString(KEY_OK));
        okButton.setToolTipText(getString(KEY_OK_TOOLTIP));
        ret.add(okButton, c);
        setDefaultButton(okButton);

        c.anchor = GridBagConstraints.CENTER;
        c.weightx = 0.0;
        c.gridx += 1;
        JButton applyButton = new JButton(getString(KEY_APPLY));
        applyButton.setToolTipText(getString(KEY_APPLY_TOOLTIP));
        ret.add(applyButton, c);

        c.anchor = GridBagConstraints.LINE_START;
        c.weightx = 0.0;
        c.gridx += 1;
        JButton cancelButton = new JButton(new DisposeAction(getString(KEY_CANCEL), this));
        cancelButton.setToolTipText(getString(KEY_CANCEL_TOOLTIP));
        ret.add(cancelButton, c);

        okButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                onOK();
            }
        });
        applyButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                onApply();
            }
        });
        return ret;
    }

    private void onOK() {
        onApply();
        dispose();
    }

    private void onApply() {
        getUser().setSurvival(survivalMode.isSelected());
        getUser().setCurrentStage(getCurrentStage());
        getUser().loadFromTeamManager(myData);
        getUser().setMegaProgress(megaProgress);
    }

    @Override
    protected void onHide() {
        // Do Nothing
    }

    @Override
    protected void onDispose() {
        onHide();
    }

    /*
     * (non-Javadoc)
     * @see shuffle.fwk.service.BaseService#updateGUIFrom(java.lang.Object)
     */
    @Override
    protected void updateGUIFrom(EditTeamServiceUser user) {
        myData = new TeamManager(user.getTeamManager());
        survivalMode.setSelected(user.isSurvival());
        curStage = user.getCurrentStage();
        megaProgress = user.getMegaProgress();
        megaThreshold = getCurrentTeam().getMegaThreshold(user.getSpeciesManager(), user.getRosterManager(),
                user.getEffectManager());
        updateRosterPanel();
        updateTeamPanel();
    }

    @Override
    public void update() {
        updateRosterPanel();
    }

    private void updateRosterPanel() {
        rosterPanel.removeAll();

        Species newSpecies = null;
        JPanel newComponent = null;
        SpeciesManager speciesManager = getUser().getSpeciesManager();
        List<Predicate<Species>> filters = getCurrentFilters(false);
        Collection<Species> speciesValues = speciesManager.getSpeciesByFilters(filters);
        for (Species s : speciesValues) {
            JPanel component = createRosterComponent(s);
            if (s.equals(selectedSpecies)) {
                newSpecies = s;
                newComponent = component;
                setBorderFor(component, true, true);
            } else {
                setBorderFor(component, false, true);
            }
            rosterPanel.add(component);
        }
        setSelected(newSpecies, newComponent);
        rosterPanel.revalidate();
        d.repaint();
    }

    private JPanel createRosterComponent(Species s) {
        JPanel ret = new JPanel(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();
        c.fill = GridBagConstraints.HORIZONTAL;
        c.gridx = 1;
        c.gridy = 1;
        c.anchor = GridBagConstraints.CENTER;

        MouseAdapter ma = new PressOrClickMouseAdapter() {

            @Override
            protected void onRight(MouseEvent e) {
                onLeft(e);
            }

            @Override
            protected void onLeft(MouseEvent e) {
                setSelected(s, ret);
                selectedDisplayLabel.repaint();
            }

            @Override
            protected void onEnter() {
                // Do nothing
            }
        };
        SpeciesPaint sp = new SpeciesPaint(s, false, getMegaFilter());
        ImageIcon icon = getUser().getImageManager().getImageFor(sp);
        JLabel iconLabel = new JLabel(icon);
        iconLabel.addMouseListener(ma);
        ret.add(iconLabel, c);
        c.gridy += 1;
        JLabel jLabel = new JLabel(s.getLocalizedName(getMegaFilter()));
        jLabel.setHorizontalTextPosition(SwingConstants.CENTER);
        jLabel.setHorizontalAlignment(SwingConstants.CENTER);
        jLabel.addMouseListener(ma);
        ret.add(jLabel, c);

        JButton addToTeam = new JButton(getString(KEY_ADD));
        addToTeam.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                addSpeciesToTeam(s);
                updateTeamPanel();
            }
        });
        addToTeam.setToolTipText(getString(KEY_ADD_TOOLTIP));
        c.gridy += 1;
        ret.add(addToTeam, c);

        return ret;
    }

    private void setSelected(Species s, JPanel newComponent) {
        selectedSpecies = s;
        if (selectedComponent != null) {
            setBorderFor(selectedComponent, false, true);
        }
        selectedComponent = newComponent;
        setBorderFor(selectedComponent, true, true);
        rebuildSelectedLabel();
    }

    private void rebuildSelectedLabel() {
        String textToUse = getString(KEY_NONE_SELECTED);
        if (selectedSpecies != null) {
            String name = selectedSpecies.getLocalizedName();
            RosterManager rosterManager = getUser().getRosterManager();
            Integer thisLevel = rosterManager.getLevelForSpecies(selectedSpecies);
            int attack = selectedSpecies.getAttack(thisLevel);
            PkmType type = megaFilter.isSelected() ? selectedSpecies.getMegaType() : selectedSpecies.getType();
            String typeNice = WordUtils.capitalizeFully(type.toString());
            Effect effect = selectedSpecies.getEffect(getUser().getRosterManager());
            String effectNice = EffectChooser.convertToBox(effect.toString());
            textToUse = getString(KEY_SELECTED, name, attack, typeNice, effectNice);
        }
        selectedDisplayLabel.setText(textToUse);
    }

    private void setBorderFor(JComponent c, boolean isSelected, boolean haveSelect) {
        if (c != null) {
            ConfigManager manager = getUser().getPreferencesManager();
            int borderThick = manager.getIntegerValue(KEY_ROSTER_CELL_BORDER_THICK, DEFAULT_BORDER_WIDTH);
            borderThick = getUser().scaleBorderThickness(borderThick);
            int outlineThick = manager.getIntegerValue(KEY_ROSTER_CELL_OUTLINE_THICK, DEFAULT_BORDER_OUTLINE);
            outlineThick = getUser().scaleBorderThickness(outlineThick);
            int marginThick = manager.getIntegerValue(KEY_ROSTER_CELL_MARGIN_THICK, DEFAULT_BORDER_MARGIN);
            marginThick = getUser().scaleBorderThickness(marginThick);
            Border margin = new EmptyBorder(marginThick, marginThick, marginThick, marginThick);
            Border greyOutline = new LineBorder(Color.gray, outlineThick);
            Border innerChunk = BorderFactory.createCompoundBorder(greyOutline, margin);
            Border toSet;
            if (haveSelect) {
                Border main;
                if (isSelected) {
                    main = new LineBorder(Color.BLACK, borderThick);
                } else {
                    main = new EmptyBorder(borderThick, borderThick, borderThick, borderThick);
                }
                Border outerChunk = BorderFactory.createCompoundBorder(main, margin);
                Border finalBorder = BorderFactory.createCompoundBorder(outerChunk, innerChunk);
                toSet = finalBorder;
            } else {
                toSet = innerChunk;
            }
            c.setBorder(toSet);
        }
    }

    private void updateTeamPanel() {
        stageChooser.updateStage();
        Team curTeam = getCurrentTeam();
        if (prevTeam != null && !prevTeam.getNames().isEmpty()
                && (curTeam == null || curTeam.getNames().isEmpty())) {
            curTeam = new TeamImpl(prevTeam);
            setTeamForCurrentStage(curTeam);
        }
        prevTeam = null;

        teamPanel.removeAll();
        nameToKeybindComboboxMap.clear();
        nameToItemListenerMap.clear();
        List<String> teamNames = curTeam.getNames();
        Set<String> names = new HashSet<String>(teamNames);
        SpeciesManager speciesManager = getUser().getSpeciesManager();
        for (String name : teamNames) {
            Species species = speciesManager.getSpeciesByName(name);
            if (species != null) {
                teamPanel.add(createTeamComponent(species));
            }
        }
        teamPanel.repaint();

        removeOptionListeners();

        // update the special species checkboxes
        boolean hasWood = curTeam.getNames().contains(Species.WOOD.getName());
        boolean hasMetal = curTeam.getNames().contains(Species.METAL.getName());
        boolean hasCoin = curTeam.getNames().contains(Species.COIN.getName());
        boolean hasFreeze = curTeam.getNames().contains(Species.FREEZE.getName());
        woodCheckBox.setSelected(hasWood);
        metalCheckBox.setSelected(hasMetal);
        coinCheckBox.setSelected(hasCoin);
        freezeCheckBox.setSelected(hasFreeze);

        megaChooser.removeAllItems();
        megaChooser.addItem(getString(KEY_NONE));
        for (String name : names) {
            Species species = speciesManager.getSpeciesByName(name);
            if (species.getMegaName() != null && !curTeam.isNonSupport(species)) {
                megaChooser.addItem(species.getLocalizedName(true));
            }
        }
        String megaSlotName = curTeam.getMegaSlotName();
        Species megaSpecies = megaSlotName == null ? null : speciesManager.getSpeciesValue(megaSlotName);
        // Mega chooser (which species is the mega slot) settings...
        if (megaSpecies == null || megaSpecies.getMegaName() == null) {
            megaChooser.setSelectedItem(getString(KEY_NONE));
        } else {
            megaChooser.setSelectedItem(megaSpecies.getLocalizedName(true));
        }
        int newThreshold = curTeam.getMegaThreshold(speciesManager, getUser().getRosterManager(),
                getUser().getEffectManager());
        if (megaSpecies == null || megaSpecies.getMegaName() == null || newThreshold == Integer.MAX_VALUE) {
            // remove their states
            megaProgressChooser.removeAllItems();
            megaActive.setSelected(false);
            // disable both the progress and the activate button
            megaProgressChooser.setEnabled(false);
            megaActive.setEnabled(false);
            megaProgress = 0;
            megaThreshold = Integer.MAX_VALUE;
        } else {
            // If we were at the max, we remain at the max
            // Otherwise, we cap out at the lesser of our previous progress and the new threshold
            if (megaProgress == megaThreshold) {
                megaProgress = newThreshold;
            } else {
                megaProgress = Math.min(megaProgress, newThreshold);
            }
            // update threshold
            megaThreshold = newThreshold;
            // refresh the progress dropdown menu
            megaProgressChooser.removeAllItems();
            int threshold = megaThreshold == Integer.MAX_VALUE ? 0 : megaThreshold;
            for (int i = 0; i <= threshold; i++) {
                megaProgressChooser.addItem(i);
            }
            // update their states appropriately
            megaProgressChooser.setSelectedItem(megaProgress);
            megaActive.setSelected(megaThreshold == megaProgress);
            // maintain the look-behind
            wasMegaActive = megaThreshold == megaProgress;
            // ensure they are editable
            megaProgressChooser.setEnabled(true);
            megaActive.setEnabled(true);
        }
        addOptionListeners();
    }

    private Component createTeamComponent(Species s) {
        Team curTeam = getCurrentTeam();
        JPanel ret = new JPanel(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();
        c.gridx = 1;
        c.gridy = 1;
        c.gridwidth = 2;
        Indicator<SpeciesPaint> ind = new Indicator<SpeciesPaint>(this);
        boolean isMega = megaProgress >= megaThreshold && s.getName().equals(curTeam.getMegaSlotName());
        SpeciesPaint paint = new SpeciesPaint(s, s.equals(Species.FREEZE), isMega);
        ind.setVisualized(paint);
        ret.add(ind, c);
        c.gridy += 1;
        c.gridwidth = 1;
        JButton removeButton = new JButton(getString(KEY_REMOVE));
        removeButton.setToolTipText(getString(KEY_REMOVE_TOOLTIP));
        removeButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent arg0) {
                removeSpeciesFromTeam(s.getName());
                updateTeamPanel();
            }
        });
        removeButton.setEnabled(
                s.getEffect(getUser().getRosterManager()).isPickable() && !s.getType().equals(PkmType.NONE));
        ret.add(removeButton, c);

        c.gridx += 1;
        JComboBox<Character> keybindsComboBox = new JComboBox<Character>();
        Character curBinding = curTeam.getBinding(s);
        LinkedHashSet<Character> allBindingsFor = new LinkedHashSet<Character>(Arrays.asList(curBinding));
        LinkedHashSet<Character> availableBindings = myData.getAllAvailableBindingsFor(s.getName(), curTeam);
        allBindingsFor.addAll(availableBindings);
        for (Character ch : allBindingsFor) {
            keybindsComboBox.addItem(ch);
        }
        keybindsComboBox.setSelectedItem(curBinding);
        final ItemListener bindingListener = new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent e) {
                JComboBox<?> source = (JComboBox<?>) e.getSource();
                int selectedIndex = source.getSelectedIndex();
                Character selected = (Character) source.getItemAt(selectedIndex);
                setBinding(s, selected);
                updateKeybindComboBoxes();
            }
        };
        nameToKeybindComboboxMap.put(s.getName(), keybindsComboBox);
        nameToItemListenerMap.put(s.getName(), bindingListener);
        keybindsComboBox.addItemListener(bindingListener);
        keybindsComboBox.setToolTipText(getString(KEY_KEYBINDS_TOOLTIP));
        ret.add(keybindsComboBox, c);

        MouseAdapter ma = new PressToggleMouseAdapter() {

            @Override
            protected void onRight(MouseEvent e) {
                doToggle();
            }

            @Override
            protected void onLeft(MouseEvent e) {
                doToggle();
            }

            private void doToggle() {
                toggleSupport(s);
                updateTeamPanel();
            }
        };
        ret.addMouseListener(ma);

        setBorderFor(ret, false, false);
        if (!Species.FIXED_SPECIES.contains(s)) {
            boolean isSupport = !curTeam.isNonSupport(s);
            Color indColor = isSupport ? Color.GREEN : Color.RED;
            ret.setBackground(indColor);
            ret.setOpaque(true);
        }
        return ret;
    }

    /**
     * @param name
     */
    protected void toggleSupport(Species species) {
        TeamImpl curTeam = getCurrentTeamImpl();
        boolean previous = curTeam.isNonSupport(species.getName());
        curTeam.setNonSupport(species, !previous);
        if (curTeam.getMegaSlotName() == null && species.getMegaName() != null && !curTeam.isNonSupport(species)) {
            curTeam.setMegaSlot(species.getName());
        }
        if (curTeam.getMegaSlotName() != null) {
            megaThreshold = curTeam.getMegaThreshold(getUser().getSpeciesManager(), getUser().getRosterManager(),
                    getUser().getEffectManager());
            megaProgress = Math.min(megaProgress, megaThreshold);
        }
        setTeamForCurrentStage(curTeam);
    }

    private void setBinding(Species species, Character newBinding) {
        TeamImpl newTeam = getCurrentTeamImpl();
        newTeam.setBinding(species, newBinding);
        setTeamForCurrentStage(newTeam);
    }

    private void updateKeybindComboBoxes() {
        Team curTeam = getCurrentTeam();
        for (String name : curTeam.getNames()) {
            ItemListener itemListener = nameToItemListenerMap.get(name);
            JComboBox<Character> box = nameToKeybindComboboxMap.get(name);
            box.removeItemListener(itemListener);
            Character prevSelected = box.getItemAt(box.getSelectedIndex());
            box.removeAllItems();
            Character curBinding = curTeam.getBinding(name);
            LinkedHashSet<Character> availableBindings = new LinkedHashSet<Character>(Arrays.asList(curBinding));
            availableBindings.addAll(myData.getAllAvailableBindingsFor(name, curTeam));
            for (Character ch : availableBindings) {
                if (ch != null) {
                    box.addItem(ch);
                }
            }
            box.setSelectedItem(prevSelected);
            if (box.getSelectedIndex() < 0) {
                LOG.warning(getString(KEY_NO_BINDINGS));
            }
            box.addItemListener(itemListener);
        }
    }

    private void removeOptionListeners() {
        if (optionListener != null) {
            megaChooser.removeItemListener(optionListener);
            megaProgressChooser.removeItemListener(optionListener);
            megaActive.removeItemListener(optionListener);
            woodCheckBox.removeItemListener(optionListener);
            metalCheckBox.removeItemListener(optionListener);
            coinCheckBox.removeItemListener(optionListener);
            freezeCheckBox.removeItemListener(optionListener);
        }
    }

    private void addOptionListeners() {
        if (optionListener == null) {
            optionListener = new ItemListener() {
                @Override
                public void itemStateChanged(ItemEvent e) {
                    updateFromOptions();
                    updateTeamPanel();
                }
            };
        }
        megaChooser.addItemListener(optionListener);
        megaProgressChooser.addItemListener(optionListener);
        megaActive.addItemListener(optionListener);
        woodCheckBox.addItemListener(optionListener);
        metalCheckBox.addItemListener(optionListener);
        coinCheckBox.addItemListener(optionListener);
        freezeCheckBox.addItemListener(optionListener);
    }

    private void updateFromOptions() {
        TeamImpl curTeam = getCurrentTeamImpl();
        String megaSlotDisplayed = getMegaSlot();
        String megaSlot = null;
        if (megaSlotDisplayed != null) {
            SpeciesManager sm = getUser().getSpeciesManager();
            for (Species s : curTeam.getSpecies(sm)) {
                if (s.getMegaName() != null && megaSlotDisplayed.equals(s.getLocalizedName(true))
                        && !curTeam.isNonSupport(s)) {
                    megaSlot = s.getName();
                    break;
                }
            }
        }
        curTeam.setMegaSlot(megaSlot);
        String woodName = Species.WOOD.getName();
        boolean hasWood = curTeam.getNames().contains(woodName);
        String metalName = Species.METAL.getName();
        boolean hasMetal = curTeam.getNames().contains(metalName);
        String coinName = Species.COIN.getName();
        boolean hasCoin = curTeam.getNames().contains(coinName);
        String freezeName = Species.FREEZE.getName();
        boolean hasFreeze = curTeam.getNames().contains(freezeName);

        if (hasWood && !woodCheckBox.isSelected()) {
            curTeam.removeName(woodName);
        } else if (!hasWood && woodCheckBox.isSelected()) {
            curTeam.addName(woodName, getNextBindingFor(woodName, curTeam));
        }
        boolean metalSelected = metalCheckBox.isSelected();
        if (hasMetal != metalSelected) {
            boolean extendedMetalEnabled = getUser().isExtendedMetalEnabled();
            getUser().getTeamManager().setMetalInTeam(curTeam, metalSelected, extendedMetalEnabled);
        }
        if (hasCoin && !coinCheckBox.isSelected()) {
            curTeam.removeName(coinName);
        } else if (!hasCoin && coinCheckBox.isSelected()) {
            curTeam.addName(coinName, getNextBindingFor(coinName, curTeam));
        }
        if (hasFreeze && !freezeCheckBox.isSelected()) {
            curTeam.removeName(freezeName);
        } else if (!hasFreeze && freezeCheckBox.isSelected()) {
            curTeam.addName(freezeName, getNextBindingFor(freezeName, curTeam));
        }

        Integer selectedMegaProgress = megaProgressChooser.getItemAt(megaProgressChooser.getSelectedIndex());
        if (selectedMegaProgress != null) {
            if (selectedMegaProgress == megaProgress && wasMegaActive != megaActive.isSelected()) {
                megaProgress = megaActive.isSelected() ? megaThreshold : 0;
            } else {
                megaProgress = selectedMegaProgress;
            }
            wasMegaActive = megaActive.isSelected();
        }
        setTeamForCurrentStage(curTeam);
    }

    private char getNextBindingFor(String name, Team team) {
        return myData.getAllAvailableBindingsFor(name, team).iterator().next();
    }

    private Team getCurrentTeam() {
        return getCurrentTeamImpl();
    }

    private TeamImpl getCurrentTeamImpl() {
        Stage currentStage = getCurrentStage();
        if (survivalMode.isSelected()) {
            currentStage = StageManager.SURVIVAL;
        }
        return new TeamImpl(myData.getTeamForStage(currentStage));
    }

    private void setTeamForCurrentStage(Team team) {
        Stage currentStage = getCurrentStage();
        if (survivalMode.isSelected()) {
            currentStage = StageManager.SURVIVAL;
        }
        myData.setTeamForStage(team, currentStage);
    }

    private void addSpeciesToTeam(Species species) {
        TeamImpl curTeam = getCurrentTeamImpl();
        curTeam.addName(species.getName(), getNextBindingFor(species.getName(), curTeam));
        if (curTeam.getMegaSlotName() == null && species.getMegaName() != null && !curTeam.isNonSupport(species)) {
            curTeam.setMegaSlot(species.getName());
        }
        if (curTeam.getMegaSlotName() != null) {
            megaThreshold = curTeam.getMegaThreshold(getUser().getSpeciesManager(), getUser().getRosterManager(),
                    getUser().getEffectManager());
            megaProgress = Math.min(megaProgress, megaThreshold);
        }
        setTeamForCurrentStage(curTeam);
    }

    private void removeSpeciesFromTeam(String name) {
        TeamImpl curTeam = new TeamImpl(getCurrentTeam());
        curTeam.removeName(name);
        setTeamForCurrentStage(curTeam);
    }

    private void clearTeam() {
        Stage currentStage = getCurrentStage();
        if (survivalMode.isSelected()) {
            currentStage = StageManager.SURVIVAL;
        }
        Team curTeam = myData.getTeamForStage(currentStage, false);
        Team newTeam = null;
        if (curTeam == null || !curTeam.getNames().isEmpty()) {
            // make it be empty if it didn't exist or if it had entries.
            newTeam = new TeamImpl();
        }
        setTeamForCurrentStage(newTeam);
        updateTeamPanel();
    }

    private String getMegaSlot() {
        String chosen = megaChooser.getItemAt(megaChooser.getSelectedIndex());
        return chosen == null || chosen.equals(getString(KEY_NONE)) ? null : chosen;
    }

    private Effect getEffect() {
        return effectFilter.getSelectedEffect();
    }

    private boolean getMegaFilter() {
        return megaFilter.isSelected();
    }

    private Function<PkmType, Boolean> getTypeFilter(PkmType stageType) {
        return typeChooser.getCurrentFilter(stageType);
    }

    private String getContainsString() {
        return textField.getText();
    }

    private Integer getLevel() {
        return (Integer) levelSpinner.getValue();
    }

    @Override
    public String getTextFor(Object o) {
        return getUser().getTextFor(o);
    }

    @Override
    public ImageManager getImageManager() {
        return getUser().getImageManager();
    }

    @Override
    public Stage getCurrentStage() {
        return curStage;
    }

    @Override
    public Collection<Stage> getAllStages() {
        return getUser().getAllStages();
    }

    @Override
    public void setCurrentStage(Stage stage) {
        prevTeam = getCurrentTeam();
        curStage = stage;
        updateTeamPanel();
        updateRosterPanel();
    }

    /**
     * @return
     */
    private List<Predicate<Species>> getCurrentFilters(boolean ignoreLevel) {
        List<Predicate<Species>> filters = getBasicFilters();
        Function<PkmType, Boolean> typeFilter = getTypeFilter(getCurrentStage().getType());
        filters.add(
                species -> typeFilter.apply(megaFilter.isSelected() ? species.getMegaType() : species.getType()));
        if (!ignoreLevel) {
            Integer curLevelFilter = getLevel();
            int minLevel = curLevelFilter != null ? curLevelFilter : 0;
            RosterManager rosterManager = getUser().getRosterManager();
            filters.add(species -> rosterManager.getLevelForSpecies(species.getName()) >= minLevel);
        }
        String str = getContainsString().toUpperCase();
        if (str != null && !str.isEmpty()) {
            filters.add(species -> species.getLocalizedName().toUpperCase().contains(str));
        }
        Effect effect = getEffect();
        if (effect != null) {
            filters.add(species -> species.getEffect(getUser().getRosterManager()).equals(effect));
        }
        if (getMegaFilter()) {
            filters.add(species -> species.getMegaName() != null && !species.getMegaName().isEmpty());
        }
        return filters;
    }

    /**
     * @return
     */
    private List<Predicate<Species>> getBasicFilters() {
        List<Predicate<Species>> filters = new ArrayList<Predicate<Species>>();
        filters.add(species -> species.getEffect(getUser().getRosterManager()).canLevel());
        return filters;
    }

    /*
     * (non-Javadoc)
     * @see shuffle.fwk.config.provider.PreferencesManagerProvider#getPreferencesManager()
     */
    @Override
    public ConfigManager getPreferencesManager() {
        return getUser().getPreferencesManager();
    }

    /*
     * (non-Javadoc)
     * @see shuffle.fwk.gui.user.StageIndicatorUser#setEscalationLevel(java.lang.Integer)
     */
    @Override
    public void setEscalationLevel(Integer level) {
        getUser().setEscalationLevel(level);
    }

    /*
     * (non-Javadoc)
     * @see shuffle.fwk.gui.user.StageIndicatorUser#getEscalationLevel()
     */
    @Override
    public Integer getEscalationLevel() {
        return getUser().getEscalationLevel();
    }

    /*
     * (non-Javadoc)
     * @see shuffle.fwk.gui.user.StageIndicatorUser#canLevelEscalation()
     */
    @Override
    public boolean canLevelEscalation() {
        return false;
    }

    /*
     * (non-Javadoc)
     * @see shuffle.fwk.gui.user.IndicatorUser#scaleFont(java.awt.Font)
     */
    @Override
    public Font scaleFont(Font fontToUse) {
        return getUser() == null ? fontToUse : getUser().scaleFont(fontToUse);
    }

    /*
     * (non-Javadoc)
     * @see shuffle.fwk.config.provider.ImageManagerProvider#getScaledBorderThickness(int)
     */
    @Override
    public Integer scaleBorderThickness(int given) {
        return getUser() == null ? given : getUser().scaleBorderThickness(given);
    }

}