/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
*    1. Redistributions of source code must retain the above copyright notice, this list of
*       conditions and the following disclaimer.
*
*    2. Redistributions in binary form must reproduce the above copyright notice, this list
*       of conditions and the following disclaimer in the documentation and/or other materials
*       provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/

/*
 * CardsList.java
 *
 * Created on Dec 18, 2009, 10:40:12 AM
 */

package mage.client.cards;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.beans.Beans;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import mage.cards.MageCard;
import mage.client.constants.Constants.DeckEditorMode;
import mage.client.constants.Constants.SortBy;
import static mage.client.constants.Constants.SortBy.CASTING_COST;
import static mage.client.constants.Constants.SortBy.COLOR;
import static mage.client.constants.Constants.SortBy.COLOR_DETAILED;
import static mage.client.constants.Constants.SortBy.RARITY;
import mage.client.deckeditor.SortSetting;
import mage.client.deckeditor.table.TableModel;
import mage.client.deckeditor.table.UpdateCountsCallback;
import mage.client.dialog.PreferencesDialog;
import mage.client.plugins.impl.Plugins;
import mage.client.util.CardViewColorComparator;
import mage.client.util.CardViewColorDetailedComparator;
import mage.client.util.CardViewCostComparator;
import mage.client.util.CardViewNameComparator;
import mage.client.util.CardViewRarityComparator;
import mage.client.util.Config;
import mage.client.util.Event;
import mage.client.util.Listener;
import mage.client.util.gui.TableSpinnerEditor;
import mage.constants.CardType;
import mage.view.CardView;
import mage.view.CardsView;
import org.mage.card.arcane.CardPanel;

/**
 *
 * @author BetaSteward_at_googlemail.com
 */
public class CardsList extends javax.swing.JPanel implements MouseListener, ICardGrid {
   
    protected CardEventSource cardEventSource = new CardEventSource();
    private Dimension cardDimension;
    private CardsView cards;
    private Map<UUID, MageCard> mageCards = new LinkedHashMap<>();
    protected BigCard bigCard;
    protected UUID gameId;
    private SortSetting sortSetting;

    private TableModel mainModel;
    private JTable mainTable;
    private ICardGrid currentView;
        
    /** Creates new form Cards */
    public CardsList() {
        initComponents();
        makeTransparent();
        initListViewComponents();
    }

    public void cleanUp() {
        this.clearCardEventListeners();
        if (cards != null) {
            cards.clear();
        }
        if (mainModel != null) {
            mainModel.removeTableModelListener(mainTable);
            mainModel.clear();
        }
        if(mainTable != null) {
            for(MouseListener ml: mainTable.getMouseListeners()) {
                mainTable.removeMouseListener(ml);
            }
        }
        if (currentView != null) {
            currentView.clearCardEventListeners();
        }
        for (Component comp :cardArea.getComponents()) {
            if (comp instanceof CardPanel) {                
                ((CardPanel)comp).cleanUp();
            }
        }
        mageCards.clear();
        cardArea.removeAll();
        this.bigCard = null;

    }

    private void makeTransparent() {
        panelCardArea.setOpaque(false);
        cardArea.setOpaque(false);
        panelCardArea.getViewport().setOpaque(false);
        panelControl.setBackground(new Color(250, 250, 250, 150));
        panelControl.setOpaque(true);
        cbSortBy.setModel(new DefaultComboBoxModel<>(SortBy.values()));
    }

    private void initListViewComponents() {
        mainTable = new JTable();

        mainModel = new TableModel();
        mainModel.addListeners(mainTable);

        mainTable.setModel(mainModel);
        mainTable.setForeground(Color.white);
        DefaultTableCellRenderer myRenderer = (DefaultTableCellRenderer) mainTable.getDefaultRenderer(String.class);
        myRenderer.setBackground(new Color(0, 0, 0, 100));
        mainTable.getColumnModel().getColumn(0).setMaxWidth(25);
        mainTable.getColumnModel().getColumn(0).setPreferredWidth(25);
        mainTable.getColumnModel().getColumn(1).setPreferredWidth(110);
        mainTable.getColumnModel().getColumn(2).setPreferredWidth(90);
        mainTable.getColumnModel().getColumn(3).setPreferredWidth(50);
        mainTable.getColumnModel().getColumn(4).setPreferredWidth(170);
        mainTable.getColumnModel().getColumn(5).setPreferredWidth(30);
        mainTable.getColumnModel().getColumn(6).setPreferredWidth(15);
        mainTable.getColumnModel().getColumn(7).setPreferredWidth(15);

        if (PreferencesDialog.getCachedValue(PreferencesDialog.KEY_DRAFT_VIEW, "cardView").equals("listView")) {
            jToggleListView.setSelected(true);
            panelCardArea.setViewportView(mainTable);
            currentView = mainModel;
            cbSortBy.setEnabled(false);
            chkPiles.setEnabled(false);
        } else {
            jToggleCardView.setSelected(true);
            currentView = this;
            panelCardArea.setViewportView(cardArea);
            cbSortBy.setEnabled(true);
            chkPiles.setEnabled(true);
        }
        mainTable.setOpaque(false);
        mainTable.addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                if (e.getClickCount() == 2 && !e.isConsumed()) {
                    e.consume();
                    if (e.isAltDown()) {
                        handleAltDoubleClick();
                    } else {
                        handleDoubleClick();
                    }
                }
            }
        });

        mainModel.setUpdateCountsCallback(new UpdateCountsCallback(lblCount, lblCreatureCount, lblLandCount, lblSorceryCount, lblInstantCount, lblEnchantmentCount));
    }

    // if you use the deck ediot to build a free deck, numbers can be set directly in deck and sideboard
    public void setDeckEditorMode(DeckEditorMode mode) {
        if (mode.equals(DeckEditorMode.FREE_BUILDING)) {
            // activate spinner for card number change
            mainModel.setNumberEditable(true);
            TableColumnModel tcm = mainTable.getColumnModel();
            TableColumn tc = tcm.getColumn(0);            
            tc.setMaxWidth(55);
            tc.setMinWidth(55);
            tc.setPreferredWidth(55);
            tc.setCellEditor(new TableSpinnerEditor(this));            
        }
    }
    
    public void handleSetNumber(int number) {
        if (mainTable.getSelectedRowCount() == 1) {
            mainModel.setNumber(mainTable.getSelectedRow(), number);
        }        
    }
    
    public void handleDoubleClick() {
        if (mainTable.getSelectedRowCount() > 0) {
            int[] n = mainTable.getSelectedRows();
            List<Integer> indexes = asList(n);
            Collections.reverse(indexes);
            for (Integer index : indexes) {
                mainModel.doubleClick(index);
            }
        }
    }
    
    public void handleAltDoubleClick() {
        if (mainTable.getSelectedRowCount() > 0) {
            int[] n = mainTable.getSelectedRows();
            List<Integer> indexes = asList(n);
            Collections.reverse(indexes);
            for (Integer index : indexes) {
                mainModel.altDoubleClick(index);
            }
        }
    }
    
    public ICardGrid getMainModel() {
        return mainModel;
    }

    public List<Integer> asList(final int[] is) {
        List<Integer> list = new ArrayList<>();
        for (int i : is) {
            list.add(i);
        }
        return list;
    }


    public void loadCards(CardsView showCards, BigCard bigCard, UUID gameId) {
        int selectedRow = -1;
        if (currentView.equals(mainModel)) {
            selectedRow = mainTable.getSelectedRow();
        }
        this.cards = showCards;
        this.bigCard = bigCard;
        this.gameId = gameId;

        cbSortBy.setSelectedItem(sortSetting.getSortBy());
        chkPiles.setSelected(sortSetting.isPilesToggle());
        currentView.loadCards(showCards, sortSetting, bigCard, gameId);
        if (selectedRow >= 0) {
            selectedRow = Math.min(selectedRow, mainTable.getRowCount()-1);
            if (selectedRow >= 0) {
                mainTable.setRowSelectionInterval(selectedRow, selectedRow);
            }
        }
    }

    private void redrawCards() {
        if (cards == null) {
            cards = new CardsView();
        }
           currentView.loadCards(cards, sortSetting, bigCard, gameId);
    }

    @Override
    public void drawCards(SortSetting sortSetting) {
        int maxWidth = this.getParent().getWidth();
        int numColumns = maxWidth / Config.dimensions.frameWidth;
        int curColumn = 0;
        int curRow = 0;
        int maxRow = 0;
        int maxColumn = 0;
        Comparator<CardView> comparator = null;
        Map<UUID, MageCard> oldMageCards = mageCards;
        mageCards = new LinkedHashMap<>();
        
        //Find card view
        for(UUID uuid : cards.keySet()){
            if(oldMageCards.containsKey(uuid)){
                mageCards.put(uuid, oldMageCards.get(uuid));
                oldMageCards.remove(uuid);
            }
            else{
                mageCards.put(uuid, addCard(cards.get(uuid), bigCard, gameId));
            }
        }
        //Remove unused cards
        for(MageCard card : oldMageCards.values()){
            cardArea.remove(card);
        }
        
        if (cards != null && cards.size() > 0) {
            Rectangle rectangle = new Rectangle(Config.dimensions.frameWidth, Config.dimensions.frameHeight);
            List<CardView> sortedCards = new ArrayList<>(cards.values());
            switch (sortSetting.getSortBy()) {
                case NAME:
                    comparator = new CardViewNameComparator();
                    break;
                case RARITY:
                    comparator = new CardViewRarityComparator();
                    break;
                case COLOR:
                    comparator = new CardViewColorComparator();
                    break;
                case COLOR_DETAILED:
                    comparator = new CardViewColorDetailedComparator();
                    break;
                case CASTING_COST:
                    comparator = new CardViewCostComparator();
                    break;
            }
            if(comparator != null){
                Collections.sort(sortedCards, new CardViewNameComparator());
                Collections.sort(sortedCards, comparator);
            }
            CardView lastCard = null;
            for (CardView card: sortedCards) {
                if (sortSetting.isPilesToggle()) {
                    if (lastCard == null) {
                        lastCard = card;
                    }
                    if(comparator != null){
                        if(comparator.compare(card, lastCard) > 0){
                            curColumn++;
                            maxRow = Math.max(maxRow, curRow);
                            curRow = 0;
                        }
                    }
                    rectangle.setLocation(curColumn * Config.dimensions.frameWidth, curRow * 20);
                    setCardBounds(mageCards.get(card.getId()), rectangle);
                    
                    curRow++;
                    lastCard = card;
                } else {
                    rectangle.setLocation(curColumn * Config.dimensions.frameWidth, curRow * 20);
                    setCardBounds(mageCards.get(card.getId()), rectangle);
                    curColumn++;
                    if (curColumn == numColumns) {
                        maxColumn = Math.max(maxColumn, curColumn);
                        curColumn = 0;
                        curRow++;
                    }
                }
            }
        }
        maxRow = Math.max(maxRow, curRow);
        maxColumn = Math.max(maxColumn, curColumn);
        updateCounts();
        cardArea.setPreferredSize(new Dimension((maxColumn+1) * Config.dimensions.frameWidth, Config.dimensions.frameHeight + maxRow*20));
        cardArea.revalidate();
        this.revalidate();
        this.repaint();
        this.setVisible(true);
    }
    
    private void updateCounts(){
        int landCount = 0;
        int creatureCount = 0;
        int sorceryCount = 0;
        int instantCount = 0;
        int enchantmentCount = 0;
        for (CardView card: cards.values()) {
           if (card.getCardTypes().contains(CardType.LAND)) {
                landCount++;
            }
            if (card.getCardTypes().contains(CardType.CREATURE)) {
                creatureCount++;
            }
            if (card.getCardTypes().contains(CardType.SORCERY)) {
                sorceryCount++;
            }
            if (card.getCardTypes().contains(CardType.INSTANT)) {
                instantCount++;
            }
            if (card.getCardTypes().contains(CardType.ENCHANTMENT)) {
                enchantmentCount++;
            }
        }
        
        int count = cards != null ? cards.size() : 0;
        this.lblCount.setText(Integer.toString(count));
        this.lblCreatureCount.setText(Integer.toString(creatureCount));
        this.lblLandCount.setText(Integer.toString(landCount));
        this.lblSorceryCount.setText(Integer.toString(sorceryCount));
        this.lblInstantCount.setText(Integer.toString(instantCount));
        this.lblEnchantmentCount.setText(Integer.toString(enchantmentCount));
    }

    private MageCard addCard(CardView card, BigCard bigCard, UUID gameId) {
        if (cardDimension == null) {
            cardDimension = new Dimension(Config.dimensions.frameWidth, Config.dimensions.frameHeight);
        }
        MageCard cardImg = Plugins.getInstance().getMageCard(card, bigCard, cardDimension, gameId, true);
        cardArea.add(cardImg);
        cardImg.update(card);
        cardImg.addMouseListener(this);
        return cardImg;
    }
    

    private void setCardBounds(MageCard card, Rectangle rectangle) {
        card.setBounds(rectangle);
        card.setCardBounds(rectangle.x, rectangle.y, Config.dimensions.frameWidth, Config.dimensions.frameHeight);
        cardArea.moveToFront(card);
    }

    @Override
    public void addCardEventListener(Listener<Event> listener) {
        cardEventSource.addListener(listener);
        mainModel.addCardEventListener(listener);
    }

    @Override
    public void loadCards(CardsView showCards, SortSetting sortSetting, BigCard bigCard, UUID gameId) {
        this.loadCards(showCards, sortSetting, bigCard, gameId, true);
    }

    @Override
    public void loadCards(CardsView showCards, SortSetting sortSetting, BigCard bigCard, UUID gameId, boolean merge) {
        cards = showCards;
        this.bigCard = bigCard;
        this.gameId = gameId;
        drawCards(sortSetting);
    }

    @Override
    public void refresh() {
        redrawCards();
    }

    @Override
    public void clearCardEventListeners() {
        cardEventSource.clearListeners();
        mainModel.clearCardEventListeners();
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        bgView = new javax.swing.ButtonGroup();
        panelControl = new javax.swing.JPanel();
        lblCount = new javax.swing.JLabel();
        lblLandCount = new javax.swing.JLabel();
        lblCreatureCount = new javax.swing.JLabel();
        lblSorceryCount = new javax.swing.JLabel();
        lblInstantCount = new javax.swing.JLabel();
        lblEnchantmentCount = new javax.swing.JLabel();
        chkPiles = new javax.swing.JCheckBox();
        cbSortBy = new javax.swing.JComboBox<SortBy>();
        jToggleListView = new javax.swing.JToggleButton();
        jToggleCardView = new javax.swing.JToggleButton();
        panelCardArea = new javax.swing.JScrollPane();
        cardArea = new javax.swing.JLayeredPane();

        setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
        setMinimumSize(new java.awt.Dimension(30, 30));
        setPreferredSize((!Beans.isDesignTime())?
            (new Dimension(Config.dimensions.frameWidth, Config.dimensions.frameHeight))
            :(new Dimension(600, 600)));
        setRequestFocusEnabled(false);

        panelControl.setMaximumSize(new java.awt.Dimension(32767, 23));
        panelControl.setMinimumSize(new java.awt.Dimension(616, 23));
        panelControl.setName(""); // NOI18N
        panelControl.setPreferredSize(new java.awt.Dimension(616, 23));
        panelControl.setRequestFocusEnabled(false);

        lblCount.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/deck_pack.png"))); // NOI18N
        lblCount.setText("999");
        lblCount.setToolTipText("Number of all cards in this area.");
        lblCount.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
        lblCount.setFocusable(false);
        lblCount.setInheritsPopupMenu(false);
        lblCount.setRequestFocusEnabled(false);
        lblCount.setVerifyInputWhenFocusTarget(false);

        lblLandCount.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
        lblLandCount.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/type_land.png"))); // NOI18N
        lblLandCount.setText("999");
        lblLandCount.setToolTipText("Number of lands.");
        lblLandCount.setVerticalAlignment(javax.swing.SwingConstants.TOP);
        lblLandCount.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
        lblLandCount.setFocusable(false);
        lblLandCount.setInheritsPopupMenu(false);
        lblLandCount.setRequestFocusEnabled(false);
        lblLandCount.setVerifyInputWhenFocusTarget(false);

        lblCreatureCount.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
        lblCreatureCount.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/type_creatures.png"))); // NOI18N
        lblCreatureCount.setText("999");
        lblCreatureCount.setToolTipText("Number of creatures.");
        lblCreatureCount.setVerticalAlignment(javax.swing.SwingConstants.TOP);
        lblCreatureCount.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
        lblCreatureCount.setFocusable(false);
        lblCreatureCount.setInheritsPopupMenu(false);
        lblCreatureCount.setRequestFocusEnabled(false);
        lblCreatureCount.setVerifyInputWhenFocusTarget(false);

        lblSorceryCount.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
        lblSorceryCount.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/type_sorcery.png"))); // NOI18N
        lblSorceryCount.setText("999");
        lblSorceryCount.setToolTipText("Number of sorceries.");
        lblSorceryCount.setVerticalAlignment(javax.swing.SwingConstants.TOP);
        lblSorceryCount.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
        lblSorceryCount.setFocusable(false);
        lblSorceryCount.setInheritsPopupMenu(false);
        lblSorceryCount.setRequestFocusEnabled(false);
        lblSorceryCount.setVerifyInputWhenFocusTarget(false);

        lblInstantCount.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
        lblInstantCount.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/type_instant.png"))); // NOI18N
        lblInstantCount.setText("999");
        lblInstantCount.setToolTipText("Number of instants.");
        lblInstantCount.setVerticalAlignment(javax.swing.SwingConstants.TOP);
        lblInstantCount.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
        lblInstantCount.setFocusable(false);
        lblInstantCount.setInheritsPopupMenu(false);
        lblInstantCount.setRequestFocusEnabled(false);
        lblInstantCount.setVerifyInputWhenFocusTarget(false);

        lblEnchantmentCount.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
        lblEnchantmentCount.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/type_enchantment.png"))); // NOI18N
        lblEnchantmentCount.setText("999");
        lblEnchantmentCount.setToolTipText("Number of enchantments.");
        lblEnchantmentCount.setVerticalAlignment(javax.swing.SwingConstants.TOP);
        lblEnchantmentCount.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
        lblEnchantmentCount.setFocusable(false);
        lblEnchantmentCount.setInheritsPopupMenu(false);
        lblEnchantmentCount.setRequestFocusEnabled(false);
        lblEnchantmentCount.setVerifyInputWhenFocusTarget(false);

        chkPiles.setText("Piles");
        chkPiles.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
        chkPiles.setMargin(new java.awt.Insets(3, 2, 2, 2));
        chkPiles.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                chkPilesActionPerformed(evt);
            }
        });

        cbSortBy.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "SortBy" }));
        cbSortBy.setToolTipText("Sort the cards if card view is active.");
        cbSortBy.setMaximumSize(new java.awt.Dimension(120, 20));
        cbSortBy.setMinimumSize(new java.awt.Dimension(120, 20));
        cbSortBy.setName("SortBy"); // NOI18N
        cbSortBy.setOpaque(false);
        cbSortBy.setPreferredSize(new java.awt.Dimension(120, 20));
        cbSortBy.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cbSortByActionPerformed(evt);
            }
        });

        bgView.add(jToggleListView);
        jToggleListView.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/list_panel.png"))); // NOI18N
        jToggleListView.setToolTipText("Shows the cards as a list.");
        jToggleListView.setBorder(null);
        jToggleListView.setHorizontalTextPosition(javax.swing.SwingConstants.LEADING);
        jToggleListView.setMargin(new java.awt.Insets(2, 6, 2, 6));
        jToggleListView.setMaximumSize(new java.awt.Dimension(37, 25));
        jToggleListView.setMinimumSize(new java.awt.Dimension(37, 25));
        jToggleListView.setPreferredSize(new java.awt.Dimension(44, 22));
        jToggleListView.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jToggleListViewActionPerformed(evt);
            }
        });

        bgView.add(jToggleCardView);
        jToggleCardView.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/card_panel.png"))); // NOI18N
        jToggleCardView.setToolTipText("Shows the card as images.");
        jToggleCardView.setHorizontalTextPosition(javax.swing.SwingConstants.LEADING);
        jToggleCardView.setMargin(new java.awt.Insets(2, 6, 2, 6));
        jToggleCardView.setPreferredSize(new java.awt.Dimension(40, 22));
        jToggleCardView.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jToggleCardViewActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout panelControlLayout = new javax.swing.GroupLayout(panelControl);
        panelControl.setLayout(panelControlLayout);
        panelControlLayout.setHorizontalGroup(
            panelControlLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(panelControlLayout.createSequentialGroup()
                .addComponent(lblCount)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(lblLandCount)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(lblCreatureCount)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(lblSorceryCount)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(lblInstantCount)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(lblEnchantmentCount)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(chkPiles)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(cbSortBy, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(jToggleListView, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jToggleCardView, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(0, 55, Short.MAX_VALUE))
        );
        panelControlLayout.setVerticalGroup(
            panelControlLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(panelControlLayout.createSequentialGroup()
                .addGroup(panelControlLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(panelControlLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                        .addComponent(lblCount)
                        .addComponent(lblLandCount)
                        .addComponent(lblCreatureCount)
                        .addComponent(lblSorceryCount)
                        .addComponent(lblInstantCount)
                        .addComponent(lblEnchantmentCount)
                        .addComponent(chkPiles))
                    .addComponent(cbSortBy, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jToggleListView, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jToggleCardView, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(0, 0, 0))
        );

        jToggleListView.getAccessibleContext().setAccessibleDescription("Switch between image and table view.");

        panelCardArea.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.LOWERED));
        panelCardArea.setViewportView(cardArea);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(1, 1, 1)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(panelControl, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(panelCardArea)))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(panelControl, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(0, 0, 0)
                .addComponent(panelCardArea, javax.swing.GroupLayout.DEFAULT_SIZE, 266, Short.MAX_VALUE))
        );
    }// </editor-fold>//GEN-END:initComponents

    private void jToggleListViewActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jToggleListViewActionPerformed
        currentView = mainModel;
        panelCardArea.setViewportView(mainTable);
        cbSortBy.setEnabled(false);
        chkPiles.setEnabled(false); 
        PreferencesDialog.saveValue(PreferencesDialog.KEY_DRAFT_VIEW, "listView");
        redrawCards();        
    }//GEN-LAST:event_jToggleListViewActionPerformed

    private void cbSortByActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbSortByActionPerformed
        sortSetting.setSortBy((SortBy) cbSortBy.getSelectedItem());
        drawCards(sortSetting);
    }//GEN-LAST:event_cbSortByActionPerformed

    private void chkPilesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_chkPilesActionPerformed
        sortSetting.setPilesToggle(chkPiles.isSelected());
        drawCards(sortSetting);
    }//GEN-LAST:event_chkPilesActionPerformed

    private void jToggleCardViewActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jToggleCardViewActionPerformed
        currentView = this;
        panelCardArea.setViewportView(cardArea);
        cbSortBy.setEnabled(true);
        chkPiles.setEnabled(true);
        PreferencesDialog.saveValue(PreferencesDialog.KEY_DRAFT_VIEW, "cardView");  
        redrawCards();    
    }//GEN-LAST:event_jToggleCardViewActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.ButtonGroup bgView;
    private javax.swing.JLayeredPane cardArea;
    private javax.swing.JComboBox<SortBy> cbSortBy;
    private javax.swing.JCheckBox chkPiles;
    private javax.swing.JToggleButton jToggleCardView;
    private javax.swing.JToggleButton jToggleListView;
    private javax.swing.JLabel lblCount;
    private javax.swing.JLabel lblCreatureCount;
    private javax.swing.JLabel lblEnchantmentCount;
    private javax.swing.JLabel lblInstantCount;
    private javax.swing.JLabel lblLandCount;
    private javax.swing.JLabel lblSorceryCount;
    private javax.swing.JScrollPane panelCardArea;
    private javax.swing.JPanel panelControl;
    // End of variables declaration//GEN-END:variables

    @Override
    public void mouseClicked(MouseEvent e) {
    }

    @Override
    public void mousePressed(MouseEvent e) {
        if (e.getClickCount() == 2 && !e.isConsumed()) {
            e.consume();
            Object obj = e.getSource();
            if (obj instanceof Card) {
                if (e.isAltDown()) {
                    cardEventSource.altDoubleClick(((Card)obj).getOriginal(), "alt-double-click");
                }
                else {
                    cardEventSource.doubleClick(((Card)obj).getOriginal(), "double-click");
                }
            } else if (obj instanceof MageCard) {
                if (e.isAltDown()) {
                    cardEventSource.altDoubleClick(((MageCard)obj).getOriginal(), "alt-double-click");
                }
                else {
                    cardEventSource.doubleClick(((MageCard)obj).getOriginal(), "double-click");
                }
            }
        }
    }

    @Override
    public void mouseReleased(MouseEvent e) {
    }

    @Override
    public void mouseEntered(MouseEvent e) {
    }

    @Override
    public void mouseExited(MouseEvent e) {
    }

    public void setDisplayNoCopies(boolean value) {
        mainModel.setDisplayNoCopies(value);
    }

    @Override
    public int cardsSize() {
        return cards.size();
    }

    public void setSortBy(SortBy sortBy) {
        if (sortBy != null) {
            cbSortBy.setSelectedIndex(sortBy.ordinal());
        }
    }

    public void setSortSetting(SortSetting sortSetting) {
        this.sortSetting = sortSetting;
    }

}
