package at.oefai.aaa.gui;

import java.awt.BorderLayout;
import java.awt.Dimension;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
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;

import at.oefai.aaa.IDetailSink;
import java.io.File;
import javax.swing.JCheckBox;
import java.awt.event.ItemListener;
import java.awt.event.ItemEvent;
import javax.swing.AbstractListModel;


/**
 * The DetailPanel is displaying info about the agents and the environment.
 * @author Stefan Rank
 */
public class DetailPanel extends JPanel implements IDetailSink, ItemListener  {
    private static final int WORKAROUND_FIXED_CELL_WIDTH = 100;
    private static final int WORKAROUND_FIXED_CELL_HEIGHT = 15;
    private static final int DEFAULT_HEIGHT = 200;
    private static final int DEFAULT_WIDTH = 600;
    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 environmentList = new JList();
    private final JPanel agentPane = new JPanel();
    private final JTree intentTree = new JTree((TreeModel) null);
    private final JCheckBox chkBox = new JCheckBox("Environment");

    private ListModel factModel = EMPTY_LIST_MODEL;
    private TreeModel intentsModel = null;
    private TreeSelectionModel intentSelectionModel = null;


    public DetailPanel() {
        setLayout(new BorderLayout());
        setMinimumSize(new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT));
        setPreferredSize(new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT));
        setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));

        //environmentList.setEnabled(false);
        this.environmentList.setFixedCellHeight(WORKAROUND_FIXED_CELL_HEIGHT);
        this.environmentList.setFixedCellWidth(WORKAROUND_FIXED_CELL_WIDTH);

        JScrollPane envScrollPane = new JScrollPane(this.environmentList);
        envScrollPane.setMinimumSize(new Dimension(150, 150));
        envScrollPane.setBorder(null);

        this.intentTree.setEditable(false);
        this.intentTree.setRootVisible(false);
        this.intentTree.setShowsRootHandles(true);
        this.intentTree.setExpandsSelectedPaths(false);
        JScrollPane intentsp = new JScrollPane(this.intentTree);
        intentsp.setPreferredSize(new Dimension(100, 100));
        intentsp.setMinimumSize(new Dimension(50, 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);

        JSplitPane sp = new JSplitPane(JSplitPane.VERTICAL_SPLIT, envScrollPane, intentsp);
        JPanel leftPane = new JPanel(new BorderLayout());
        leftPane.add(this.chkBox, BorderLayout.NORTH);
        leftPane.add(sp);

        this.agentPane.setMinimumSize(new Dimension(350, 150));
        this.agentPane.setLayout(new BoxLayout(this.agentPane, BoxLayout.Y_AXIS));

        JSplitPane splitpane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPane, this.agentPane);
        splitpane.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));

        JLabel infoLabel = new JLabel("bottom left :  Environment status (world facts) and current actions"
                               + "  ---  bottom right :  Actors beliefs (excl. perceptions) and their intentions",
                               SwingConstants.CENTER);
        this.add(infoLabel, BorderLayout.NORTH);
        this.add(splitpane);
    }

    public final void setEnvironmentModels(final ListModel lm, final TreeModel intents,
                                           final TreeSelectionModel tsm) {
        this.factModel = lm;
        this.intentsModel = intents;
        this.intentSelectionModel = tsm;
        this.chkBox.setSelected(true);
        this.setModels(true);
    }

    public final void addAgentModels(final String agentName, final File agentPNGfile, final ListModel facts,
                                     final TreeModel intents, final TreeSelectionModel tsm) {
        this.agentPane.add(new AgentPanel(agentName, agentPNGfile, facts, intents, tsm));
    }

    public final void clearModels() {
        this.agentPane.removeAll();
        this.setModels(false);
    }

    private void setModels(final boolean flag) {
        if (flag) {
            this.environmentList.setModel(this.factModel);
            this.intentTree.setModel(this.intentsModel);
            this.intentTree.setSelectionModel(this.intentSelectionModel);
        } else {
            this.environmentList.setModel(EMPTY_LIST_MODEL);
            this.intentTree.setSelectionModel(null);
            this.intentTree.setModel(null);
        }
    }

    public final void setChildrenEnabled(final boolean b) {
        this.environmentList.setEnabled(b);
        this.intentTree.setEnabled(b);
        this.chkBox.setEnabled(b);
        for (int i = 0; i < this.agentPane.getComponentCount(); ++i) {
            ((AgentPanel) this.agentPane.getComponent(i)).setChildrenEnabled(b);
        }
    }

    public final void itemStateChanged(final ItemEvent e) {
        this.setModels(e.getStateChange() == ItemEvent.SELECTED);
    }

}
