package at.oefai.aaa.gui;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.File;

import javax.swing.AbstractListModel;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.ImageIcon;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTree;
import javax.swing.ListModel;
import javax.swing.SwingConstants;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreeSelectionModel;

/**
 * panel that displays details about an agent.
 * @author Stefan Rank
 */
public class AgentPanel extends JPanel implements ItemListener {
    private static final int WORKAROUND_FIXED_CELL_WIDTH = 100;
    private static final int WORKAROUND_FIXED_CELL_HEIGHT = 15;
    private static final ListModel EMPTY_LIST_MODEL = new AbstractListModel() {
        public int getSize() { return 0; }
        public Object getElementAt(final int i) { return "No Data Model"; }
    };

    private final JList factList = new JList(EMPTY_LIST_MODEL);
    private final JTree intentTree = new JTree((TreeModel) null);
    private final JCheckBox chkBox = new JCheckBox();

    private final ListModel factModel;
    private final TreeModel intentsModel;
    private final TreeSelectionModel intentSelectionModel;

    public AgentPanel(final String agentName, final File agentPNGfile, final ListModel facts,
                      final TreeModel intents, final TreeSelectionModel tsm) {
        this.factModel = facts;
        this.intentsModel = intents;
        this.intentSelectionModel = tsm;

        // set up gui components:
        JLabel label = new JLabel(new ImageIcon(agentPNGfile.getAbsolutePath(), agentName), SwingConstants.CENTER);
        label.setAlignmentX(0.5f);
        label.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
        JLabel nameLabel = new JLabel(agentName, SwingConstants.CENTER);
        nameLabel.setAlignmentX(0.5f);

        // the following is necessary to avoid automatic computation of the lists
        // preferred size (which uses non thread save code:
        // javax.swing.plaf.basic.BasicListUI.updateLayout...
        // calls getSize of the listmodel, creates an array of this size and
        // calls getsize again before the iteration (change in between possible)
        this.factList.setFixedCellHeight(WORKAROUND_FIXED_CELL_HEIGHT);
        this.factList.setFixedCellWidth(WORKAROUND_FIXED_CELL_WIDTH);
        JScrollPane factsp = new JScrollPane(this.factList);
        factsp.setPreferredSize(new Dimension(250, 200));
        factsp.setMinimumSize(new Dimension(150, 50));
        factsp.setBorder(null);

        this.intentTree.setEditable(false);
        this.intentTree.setRootVisible(false);
        this.intentTree.setShowsRootHandles(true);
        this.intentTree.setExpandsSelectedPaths(true);
        JScrollPane intentsp = new JScrollPane(this.intentTree);
        intentsp.setPreferredSize(new Dimension(200, 200));
        intentsp.setMinimumSize(new Dimension(200, 50));
        intentsp.setBorder(null);

        // the checkbox for activating and deactivating the display
        this.chkBox.setAlignmentX(0.5f);
        this.chkBox.setSelected(true);
        this.chkBox.addItemListener(this);

        Box leftBox = Box.createVerticalBox();
        leftBox.add(Box.createVerticalGlue());
        leftBox.add(label);
        leftBox.add(nameLabel);
        leftBox.add(this.chkBox);
        leftBox.add(Box.createVerticalGlue());
        leftBox.add(Box.createHorizontalStrut(40));

        JSplitPane sp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, factsp, intentsp);

        this.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
        this.setLayout(new BorderLayout());
        this.add(leftBox, BorderLayout.WEST);
        this.add(sp);

        this.setModels(true);
    }

    private void setModels(final boolean flag) {
        if (flag) {
            this.factList.setModel(this.factModel);
            this.intentTree.setModel(this.intentsModel);
            this.intentTree.setSelectionModel(this.intentSelectionModel);
            this.setPreferredSize(new Dimension(450, 200));
        } else {
            this.factList.setModel(EMPTY_LIST_MODEL);
            this.intentTree.setModel(null);
            this.intentTree.setSelectionModel(null);
            this.setPreferredSize(new Dimension(350, 55));
        }
        if (this.getParent() != null) {
            this.getParent().validate();
        }
    }

    public final void setChildrenEnabled(final boolean b) {
        this.factList.setEnabled(b);
        this.intentTree.setEnabled(b);
        this.chkBox.setEnabled(b);
    }

    /**
     * itemlistener method to react to the checkbox, unchecked means no models displayed.
     */
    public final void itemStateChanged(final ItemEvent e) {
        this.setModels(e.getStateChange() == ItemEvent.SELECTED);
    }

}
