package ui.view;

import DataSets.GraphDataSet;
import DataSets.PropertyDataSet;
import classes.*;
import interfaces.GraphListener;
import ui.controller.Control;
import ui.controller.SingletonControl;

import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import java.awt.*;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Random;

public class StatisticPanel extends JSplitPane implements GraphListener {
    public static final String AVG_INACTIVE_ELEMENTS_HOLON = "average of inactive elements per Holon";
    public static final String AVG_PRODUCTION_HOLON = "average production per Holon";
    // for tracked objects
    public static final String TOT_PROD_OBJ = "total production";
    public static final String TOT_CONS_OBJ = "total consumption";
    public static final String NR_ACTIVE_ELEMENTS = "active elements";
    public static final String SW_ACTIVE = "active";
    public static final String TOT_PROD_GRID = "total Grid production";
    public static final String TOT_CONS_GRID = "total Grid consumption";
    private static final String MAIN_GRID = "Main Grid";
    private static final String HOLON = "Holons";
    // Property Strings
    // for whole grid
    private static final String TOT_PROD_HOLON = "total production";
    private static final String TOT_CONS_HOLON = "total consumption";
    private static final String TOT_WASTED_HOLON = "total wasted energy";
    private static final String SUPPLIED_OBJ = "supplied objects' percentage";
    private static final String NOT_SUPPLIED_OBJ = "not supplied objects' percentage";
    private static final String PART_SUPPLIED_OBJ = "partially supplied objects' percentage";
    private static final String NR_HOLONS = "nr. of Holons";
    private static final String NR_CLOSED_SWITCHES = "nr. of closed switches";
    private static final String AVG_OBJ_IN_HOLONS = "average amount of objects";
    private static final String AVG_ELEM_IN_HOLONS = "average amount of elements";
    private static final String AVG_PRODS_IN_HOLONS = "average amount of producers";
    private static final String AVG_CONS_ENERGY_IN_HOLONS = "average consumed energy";
    private static final String AVG_WASTED_ENERGY_HOLONS = "average wasted energy";
    private static final String NR_BROKEN_EDGES = "nr. of broken edges";
    private static final String PROD_CONS_RATIO = "producer/consumer ratio";
    private static final String AVG_CLOSED_SW_HOLON = "average of closed switches per Holon";
    private static final String AVG_ACTIVE_ELEMENTS_HOLON = "average of active elements per Holon";
    private DefaultTreeModel treeModel;
    private DefaultMutableTreeNode objectsNode;
    private DefaultMutableTreeNode mainGrid;
    private DefaultMutableTreeNode holonNode;
    private DefaultMutableTreeNode switchesNode;
    private DefaultMutableTreeNode groupNode;

    private Hashtable<String, GraphDataSet> objectHashtable;
    private Hashtable<String, StatisticGraphPanel> graphHashtable;
    private Hashtable<String, PropertyDataSet> holonHashtable;
    private Hashtable<String, Integer> propValTable;

    //contains information about a selected property
    private PropertyDataSet currentProperty = new PropertyDataSet();
    private Color defaultGraphColor = Color.RED;
    private Control controller;
    private JPanel graphPanel;

    //WindowBuilder Components
    private JTree objectTree;
    private JTextField graphNrTxtField;
    private JTextField redField;
    private JTextField greenField;
    private JTextField blueField;
    private JPanel colorPanel;
    private JComboBox colorComboBox;
    private JLabel showObjectlbl;
    private JLabel showPropertylbl;
    private JButton btnAdd;


    public StatisticPanel(Control cont) {
        setBorder(null);
        setMaximumSize(new Dimension(0, 0));
        setPreferredSize(new Dimension(0, 0));
        setMinimumSize(new Dimension(0, 0));
        this.setDividerLocation(180);
        setContinuousLayout(true);
        this.controller = cont;
        objectHashtable = new Hashtable<>();
        graphHashtable = new Hashtable<>();
        controller.setGraphTable(graphHashtable);

        holonHashtable = new Hashtable<>();
        holonHashtable.put(TOT_PROD_HOLON, new PropertyDataSet("", defaultGraphColor));
        holonHashtable.put(TOT_CONS_HOLON, new PropertyDataSet("", defaultGraphColor));
        holonHashtable.put(TOT_WASTED_HOLON, new PropertyDataSet("", defaultGraphColor));
        holonHashtable.put(SUPPLIED_OBJ, new PropertyDataSet("", defaultGraphColor));
        holonHashtable.put(NOT_SUPPLIED_OBJ, new PropertyDataSet("", defaultGraphColor));
        holonHashtable.put(PART_SUPPLIED_OBJ, new PropertyDataSet("", defaultGraphColor));
        holonHashtable.put(NR_HOLONS, new PropertyDataSet("", defaultGraphColor));
        holonHashtable.put(NR_CLOSED_SWITCHES, new PropertyDataSet("", defaultGraphColor));
        holonHashtable.put(AVG_OBJ_IN_HOLONS, new PropertyDataSet("", defaultGraphColor));
        holonHashtable.put(AVG_ELEM_IN_HOLONS, new PropertyDataSet("", defaultGraphColor));
        holonHashtable.put(AVG_PRODS_IN_HOLONS, new PropertyDataSet("", defaultGraphColor));
        holonHashtable.put(AVG_CONS_ENERGY_IN_HOLONS, new PropertyDataSet("", defaultGraphColor));
        holonHashtable.put(AVG_WASTED_ENERGY_HOLONS, new PropertyDataSet("", defaultGraphColor));
        holonHashtable.put(NR_BROKEN_EDGES, new PropertyDataSet("", defaultGraphColor));
        holonHashtable.put(PROD_CONS_RATIO, new PropertyDataSet("", defaultGraphColor));
        holonHashtable.put(AVG_CLOSED_SW_HOLON, new PropertyDataSet("", defaultGraphColor));
        holonHashtable.put(AVG_ACTIVE_ELEMENTS_HOLON, new PropertyDataSet("", defaultGraphColor));
        holonHashtable.put(AVG_INACTIVE_ELEMENTS_HOLON, new PropertyDataSet("", defaultGraphColor));
        holonHashtable.put(AVG_PRODUCTION_HOLON, new PropertyDataSet("", defaultGraphColor));


        //propValTable associates the Strings to the numbers
        propValTable = new Hashtable<>();
        propValTable.put(TOT_PROD_OBJ, TrackedDataSet.PRODUCTION);
        propValTable.put(TOT_CONS_OBJ, TrackedDataSet.CONSUMPTION);
        propValTable.put(TOT_WASTED_HOLON, TrackedDataSet.WASTED_ENERGY);
        propValTable.put(NR_ACTIVE_ELEMENTS, TrackedDataSet.ACTIVATED_ELEMENTS);
        propValTable.put(SW_ACTIVE, TrackedDataSet.ON_OFF);
        propValTable.put(TOT_PROD_HOLON, TrackedDataSet.TOTAL_PRODUCTION);
        propValTable.put(TOT_CONS_HOLON, TrackedDataSet.TOTAL_CONSUMPTION);
        propValTable.put(SUPPLIED_OBJ, TrackedDataSet.PERCENT_SUPPLIED);
        propValTable.put(NOT_SUPPLIED_OBJ, TrackedDataSet.PERCENT_NOT_SUPPLIED);
        propValTable.put(PART_SUPPLIED_OBJ, TrackedDataSet.PERCENT_PARTIAL_SUPPLIED);
        propValTable.put(TOT_PROD_GRID, TrackedDataSet.GROUP_PRODUCTION);
        propValTable.put(TOT_CONS_GRID, TrackedDataSet.GROUP_CONSUMPTION);
        propValTable.put(NR_HOLONS, TrackedDataSet.AMOUNT_HOLONS);
        propValTable.put(NR_CLOSED_SWITCHES, TrackedDataSet.AMOUNT_CLOSED_SWITCHES);
        propValTable.put(AVG_OBJ_IN_HOLONS, TrackedDataSet.AVG_AMOUNT_OBJECTS_IN_HOLONS);
        propValTable.put(AVG_ELEM_IN_HOLONS, TrackedDataSet.AVG_AMOUNT_ELEMENTS_IN_HOLONS);
        propValTable.put(AVG_PRODS_IN_HOLONS, TrackedDataSet.AVG_AMOUNT_PRODUCERS_IN_HOLONS);
        propValTable.put(AVG_CONS_ENERGY_IN_HOLONS, TrackedDataSet.AVG_CONSUMED_ENERGY_IN_HOLONS);
        propValTable.put(AVG_WASTED_ENERGY_HOLONS, TrackedDataSet.AVG_WASTED_ENERGY_IN_HOLONS);
        propValTable.put(NR_BROKEN_EDGES, TrackedDataSet.AMOUNT_BROKEN_EDGES);
        propValTable.put(PROD_CONS_RATIO, TrackedDataSet.RATIO_PRODUCERS_CONSUMERS);
        propValTable.put(AVG_CLOSED_SW_HOLON, TrackedDataSet.AVG_AMOUNT_CLOSED_SWITCHES_IN_HOLONS);
        propValTable.put(AVG_ACTIVE_ELEMENTS_HOLON, TrackedDataSet.AVG_AMOUNT_ACTIVE_ELEMENTS_IN_HOLONS);
        propValTable.put(AVG_INACTIVE_ELEMENTS_HOLON, TrackedDataSet.AVG_AMOUNT_INACTIVE_ELEMENTS_IN_HOLONS);
        propValTable.put(AVG_PRODUCTION_HOLON, TrackedDataSet.AVG_PRODUCED_ENERGY_IN_HOLONS);


        JScrollPane graphScrollPane = new JScrollPane();
        graphScrollPane.setBorder(null);
        setRightComponent(graphScrollPane);

        graphPanel = new JPanel();
        graphPanel.setLayout(new BoxLayout(graphPanel, BoxLayout.Y_AXIS));
        graphPanel.revalidate();
        graphPanel.updateUI();
        graphScrollPane.setViewportView(graphPanel);

        JSplitPane splitPane = new JSplitPane();
        splitPane.setResizeWeight(0.5);
        splitPane.setBorder(null);
        splitPane.setPreferredSize(new Dimension(0, 0));
        splitPane.setMinimumSize(new Dimension(0, 0));
        splitPane.setMaximumSize(new Dimension(0, 0));
        splitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
        setLeftComponent(splitPane);

        //========================== TREE STRUCTURE ===============================//
        JScrollPane treeScrollPane = new JScrollPane();
        treeScrollPane.setBorder(null);
        objectTree = new JTree();
        objectTree.setBorder(new EmptyBorder(0, 0, 0, 0));
        treeModel = (DefaultTreeModel) objectTree.getModel();
        DefaultMutableTreeNode root = new DefaultMutableTreeNode("Statistics");
        mainGrid = new DefaultMutableTreeNode(MAIN_GRID);
        mainGrid.add(new DefaultMutableTreeNode(TOT_PROD_HOLON));
        mainGrid.add(new DefaultMutableTreeNode(TOT_CONS_HOLON));
        mainGrid.add(new DefaultMutableTreeNode(TOT_WASTED_HOLON));
        mainGrid.add(new DefaultMutableTreeNode(SUPPLIED_OBJ));
        mainGrid.add(new DefaultMutableTreeNode(NOT_SUPPLIED_OBJ));
        mainGrid.add(new DefaultMutableTreeNode(PART_SUPPLIED_OBJ));
        mainGrid.add(new DefaultMutableTreeNode(PROD_CONS_RATIO));
        mainGrid.add(new DefaultMutableTreeNode(NR_BROKEN_EDGES));
        mainGrid.add(new DefaultMutableTreeNode(NR_CLOSED_SWITCHES));

        holonNode = new DefaultMutableTreeNode(HOLON);
        holonNode.add(new DefaultMutableTreeNode(NR_HOLONS));
        holonNode.add(new DefaultMutableTreeNode(AVG_OBJ_IN_HOLONS));
        holonNode.add(new DefaultMutableTreeNode(AVG_ELEM_IN_HOLONS));
        holonNode.add(new DefaultMutableTreeNode(AVG_WASTED_ENERGY_HOLONS));
        holonNode.add(new DefaultMutableTreeNode(AVG_CONS_ENERGY_IN_HOLONS));
        holonNode.add(new DefaultMutableTreeNode(AVG_PRODS_IN_HOLONS));
        holonNode.add(new DefaultMutableTreeNode(AVG_CLOSED_SW_HOLON));
        holonNode.add(new DefaultMutableTreeNode(AVG_ACTIVE_ELEMENTS_HOLON));
        holonNode.add(new DefaultMutableTreeNode(AVG_INACTIVE_ELEMENTS_HOLON));
        holonNode.add(new DefaultMutableTreeNode(AVG_PRODUCTION_HOLON));


        objectsNode = new DefaultMutableTreeNode("Objects");
        objectsNode.add(new DefaultMutableTreeNode("empty"));

        switchesNode = new DefaultMutableTreeNode("Switches");
        switchesNode.add(new DefaultMutableTreeNode("empty"));

        groupNode = new DefaultMutableTreeNode("Groups");
        groupNode.add(new DefaultMutableTreeNode("empty"));

        treeModel.setRoot(root);
        root.add(mainGrid);
        root.add(holonNode);
        root.add(objectsNode);
        root.add(switchesNode);
        root.add(groupNode);
        objectTree.setModel(treeModel);

        treeScrollPane.setViewportView(objectTree);

        JPopupMenu popupMenu = new JPopupMenu();
        addPopup(objectTree, popupMenu);

        JMenuItem mntmUntrack = new JMenuItem("Untrack");
        mntmUntrack.addActionListener(actionEvent -> {
            DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) objectTree
                    .getLastSelectedPathComponent();
            if (selectedNode.getLevel() == 2 && !selectedNode.getParent().toString().equals("whole Holon")) {
                String object = selectedNode.toString();
                controller.removeTrackingObj(objectHashtable.get(object).getObject());
            }
        });
        popupMenu.add(mntmUntrack);

        objectTree.addTreeSelectionListener(treeSelectionEvent -> {
            resetFields();
            showObjectlbl.setText("...");
            //showPropertylbl.setText("...");
            DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) objectTree
                    .getLastSelectedPathComponent();
            if (selectedNode == null) {
                return;
            } else {
                if (selectedNode.getLevel() == 0) {
                    disableFields();
                }
                if (selectedNode.getLevel() == 1) {
                    disableFields();
                    currentProperty = null;
                    graphNrTxtField.setText("");
                    showObjectlbl.setText(selectedNode.toString());
                }
                if (selectedNode.getLevel() == 2) {
                    if (selectedNode.getParent().toString().equals(MAIN_GRID)
                            || selectedNode.getParent().toString().equals(HOLON)) {
                        enableFields();
                        String object = selectedNode.getParent().toString();
                        String property = selectedNode.toString();
                        currentProperty = holonHashtable.get(property);
                        Color color = currentProperty.getColor();

                        redField.setText(Integer.toString(color.getRed()));
                        greenField.setText(Integer.toString(color.getGreen()));
                        blueField.setText(Integer.toString(color.getBlue()));

                        showPropertylbl.setText(property);
                        showObjectlbl.setText(object);
                        graphNrTxtField.setText(currentProperty.getAssignedGraph());
                        colorPanel.setBackground(color);
                    } else {
                        disableFields();
                        currentProperty = null;
                        graphNrTxtField.setText("");
                        showObjectlbl.setText(selectedNode.toString());
                    }
                }
                if (selectedNode.getLevel() == 3) {
                    enableFields();
                    String object = selectedNode.getParent().toString();
                    String property = selectedNode.toString();
                    currentProperty = objectHashtable.get(object).getPropertytTable().get(property);
                    Color color = currentProperty.getColor();
                    redField.setText(Integer.toString(color.getRed()));
                    greenField.setText(Integer.toString(color.getGreen()));
                    blueField.setText(Integer.toString(color.getBlue()));

                    showObjectlbl.setText(object);
                    showPropertylbl.setText(property);
                    graphNrTxtField.setText(currentProperty.getAssignedGraph());
                    colorPanel.setBackground(color);
                }
            }
        });

        splitPane.setLeftComponent(treeScrollPane);
        repaintTree();
        //=========================== TREE STRUCTURE END ==========================//

        //================= COLOR COMBOBOX ===========================//

        colorComboBox = new JComboBox();
        colorComboBox.addItem("Red");
        colorComboBox.addItem("Blue");
        colorComboBox.addItem("Green");
        colorComboBox.addItem("Yellow");
        colorComboBox.addItem("Orange");
        colorComboBox.addItem("Cyan");
        colorComboBox.addItem("Magenta");
        colorComboBox.addItem("Pink");
        colorComboBox.addItem("Gray");
        colorComboBox.addItem("Random");
        colorComboBox.addItemListener(itemEvent -> {
            String colorName = (String) colorComboBox.getSelectedItem();
            Color tmpColor = defaultGraphColor;
            switch (colorName) {
                case "Red":
                    colorChanged(tmpColor);
                    break;
                case "Blue":
                    tmpColor = Color.BLUE;
                    colorChanged(tmpColor);
                    break;
                case "Green":
                    tmpColor = Color.GREEN;
                    colorChanged(tmpColor);
                    break;
                case "Yellow":
                    tmpColor = Color.YELLOW;
                    colorChanged(tmpColor);
                    break;
                case "Orange":
                    tmpColor = Color.ORANGE;
                    colorChanged(tmpColor);
                    break;
                case "Cyan":
                    tmpColor = Color.CYAN;
                    colorChanged(tmpColor);
                    break;
                case "Magenta":
                    tmpColor = Color.MAGENTA;
                    colorChanged(tmpColor);
                    break;
                case "Pink":
                    tmpColor = Color.PINK;
                    colorChanged(tmpColor);
                    break;
                case "Gray":
                    tmpColor = Color.GRAY;
                    colorChanged(tmpColor);
                    break;
                case "Random":
                    Random rdm = new Random();
                    tmpColor = new Color(rdm.nextInt(255), rdm.nextInt(255), rdm.nextInt(255));
            }
            redField.setText(Integer.toString(tmpColor.getRed()));
            greenField.setText(Integer.toString(tmpColor.getGreen()));
            blueField.setText(Integer.toString(tmpColor.getBlue()));
        });

        // ==================== COLORBOX END ==========================//

        // ====================RED TEXTFIELD===========================//
        redField = new JTextField();
        redField.setColumns(10);
        redField.getDocument().addDocumentListener(new DocumentListener() {
            /*
             * if textField for Red changes, changes will applied in the
             * DataStructure "currentProperty" if Value is legit
             */
            @Override
            public void insertUpdate(DocumentEvent e) {
                int tmp = -1;
                try {
                    tmp = Integer.parseInt(redField.getText());
                } catch (NumberFormatException e1) {

                }
                if (tmp > -1 && tmp <= 255) {
                    if (currentProperty != null) {
                        Color oldColor = currentProperty.getColor();
                        Color color = new Color(tmp, oldColor.getGreen(), oldColor.getBlue());
                        currentProperty.setColor(color);
                        colorChanged(color);
                    }
                }
            }

            @Override
            public void removeUpdate(DocumentEvent e) {
                int tmp = -1;
                try {
                    tmp = Integer.parseInt(redField.getText());
                } catch (NumberFormatException e1) {

                }
                if (tmp > -1 && tmp <= 255) {
                    if (currentProperty != null) {
                        Color oldColor = currentProperty.getColor();
                        Color color = new Color(tmp, oldColor.getGreen(), oldColor.getBlue());
                        currentProperty.setColor(color);
                        colorChanged(color);
                    }
                }
            }

            @Override
            public void changedUpdate(DocumentEvent e) {

            }
        });
        // ======================RED TEXTFIELD END==========================//

        // ======================GREEN TEXTFIELD============================//
        greenField = new JTextField();
        greenField.setColumns(10);
        greenField.getDocument().addDocumentListener(new DocumentListener() {
            /*
             * if textField for Red changes, changes will applied in the
             * DataStructure "currentProperty" if Value is legit
             */
            @Override
            public void insertUpdate(DocumentEvent e) {
                int tmp = -1;
                try {
                    tmp = Integer.parseInt(greenField.getText());
                } catch (NumberFormatException e1) {

                }
                if (tmp > -1 && tmp <= 255) {
                    if (currentProperty != null) {
                        Color oldColor = currentProperty.getColor();
                        Color color = new Color(oldColor.getRed(), tmp, oldColor.getBlue());
                        currentProperty.setColor(color);
                        colorChanged(color);
                    }
                }
            }

            @Override
            public void removeUpdate(DocumentEvent e) {
                int tmp = -1;
                try {
                    tmp = Integer.parseInt(greenField.getText());
                } catch (NumberFormatException e1) {

                }
                if (tmp > -1 && tmp <= 255) {
                    if (currentProperty != null) {
                        Color oldColor = currentProperty.getColor();
                        Color color = new Color(oldColor.getRed(), tmp, oldColor.getBlue());
                        currentProperty.setColor(color);
                        colorChanged(color);
                    }
                }
            }

            @Override
            public void changedUpdate(DocumentEvent e) {

            }
        });
        // ======================GREEN TEXTFIELD END========================//

        // ======================BLUE TEXTFIELD=============================//
        blueField = new JTextField();
        blueField.setColumns(10);
        blueField.getDocument().addDocumentListener(new DocumentListener() {
            /*
             * if textField for Red changes, changes will applied in the
             * DataStructure "currentProperty" if Value is legit
             */
            @Override
            public void insertUpdate(DocumentEvent e) {
                int tmp = -1;
                try {
                    tmp = Integer.parseInt(blueField.getText());
                } catch (NumberFormatException e1) {

                }
                if (tmp > -1 && tmp <= 255) {
                    if (currentProperty != null) {
                        Color oldColor = currentProperty.getColor();
                        Color color = new Color(oldColor.getRed(), oldColor.getGreen(), tmp);
                        currentProperty.setColor(color);
                        colorChanged(color);
                    }
                }
            }

            @Override
            public void removeUpdate(DocumentEvent e) {
                int tmp = -1;
                try {
                    tmp = Integer.parseInt(blueField.getText());
                } catch (NumberFormatException e1) {

                }
                if (tmp > -1 && tmp <= 255) {
                    if (currentProperty != null) {
                        Color oldColor = currentProperty.getColor();
                        Color color = new Color(oldColor.getRed(), oldColor.getGreen(), tmp);
                        currentProperty.setColor(color);
                        colorChanged(color);
                    }
                }
            }

            @Override
            public void changedUpdate(DocumentEvent e) {

            }
        });
        // ======================BLUE TEXTFIELD END=========================//

        // ======================GRAPH NR TEXTFIELD=========================//
        graphNrTxtField = new JTextField();
        graphNrTxtField.setColumns(10);
        graphNrTxtField.getDocument().addDocumentListener(new DocumentListener() {
            /*
             * if textField for Red changes, changes will applied in the
             * DataStructure "currentProperty" if Value is legit
             */
            @Override
            public void insertUpdate(DocumentEvent e) {
                if (currentProperty != null) {
                    currentProperty.setGraph(graphNrTxtField.getText());
                }
            }

            @Override
            public void removeUpdate(DocumentEvent e) {
                if (currentProperty != null) {
                    currentProperty.setGraph(graphNrTxtField.getText());
                }
            }

            @Override
            public void changedUpdate(DocumentEvent e) {

            }
        });

        // ======================= GRAPH NR TEXTFIELD END==================//

        //======================== ADD BUTTON =============================//

        JButton btnAdd = new JButton("Add");
        btnAdd.addActionListener(actionEvent -> {
            DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) objectTree
                    .getLastSelectedPathComponent();
            if (selectedNode != null) {
                int nodeLevel = selectedNode.getLevel();
                String parentString = selectedNode.getParent().toString();
                if (nodeLevel == 3 ||
                        (nodeLevel == 2 && (parentString.equals(HOLON) || parentString.equals(MAIN_GRID)))) {
                    StatisticGraphPanel tmp;
                    if (graphNrTxtField.getText().length() > 0) {
                        if (!graphHashtable.containsKey(graphNrTxtField.getText())
                                && graphNrTxtField.getText().length() > 0) {
                            tmp = new StatisticGraphPanel(controller.getModel(), controller,
                                    graphNrTxtField.getText(), graphHashtable);
                            graphPanel.add(tmp);
                            graphPanel.add(Box.createRigidArea(new Dimension(50, 50)));
                            graphPanel.revalidate();
                            graphPanel.updateUI();
                            graphHashtable.put(graphNrTxtField.getText(), tmp);
                        }
                        String object = selectedNode.getParent().toString();
                        String property = selectedNode.toString();
                        AbstractCpsObject absCps = null;
                        if (!object.equals(MAIN_GRID) && !object.equals(HOLON)) {
                            GraphDataSet dataSet = objectHashtable.get(object);
                            absCps = dataSet.getObject();
                        }
                        TrackedDataSet tds = new TrackedDataSet(absCps, propValTable.get(property),
                                currentProperty.getColor(),cont.getModel().getIterations());
                        graphHashtable.get(graphNrTxtField.getText()).addObject(tds);
                    }
                }
            }
        });

        //============================== ADD BUTTON END ==============================//

        //=========================== WINDOWBUILDER COMPONENTS ====================//
        JScrollPane scrollPane = new JScrollPane();
        scrollPane.setBorder(null);
        splitPane.setRightComponent(scrollPane);

        JPanel editPanel = new JPanel();
        //editPanel.setBounds(0,0,600,600);
        editPanel.setPreferredSize(new Dimension(170, 240));
        //scrollPane.setBounds(0,0,600,600);
        scrollPane.setViewportView(editPanel);
        editPanel.setLayout(null);

        JLabel lblObject = new JLabel("Object(s):");
        lblObject.setBounds(10, 11, 59, 20);
        editPanel.add(lblObject);

        showObjectlbl = new JLabel("...");
        showObjectlbl.setBounds(69, 11, 101, 20);
        editPanel.add(showObjectlbl);

        JLabel lblProperty = new JLabel("Property:");
        lblProperty.setBounds(10, 36, 59, 20);
        editPanel.add(lblProperty);

        showPropertylbl = new JLabel("...");
        showPropertylbl.setBounds(69, 36, 101, 20);
        editPanel.add(showPropertylbl);

        JLabel lblGraph = new JLabel("Graph:");
        lblGraph.setBounds(10, 61, 49, 23);
        editPanel.add(lblGraph);

        graphNrTxtField.setColumns(10);
        graphNrTxtField.setBounds(69, 61, 101, 23);
        editPanel.add(graphNrTxtField);

        JLabel lblColor = new JLabel("Color:");
        lblColor.setBounds(10, 95, 49, 23);
        editPanel.add(lblColor);

        colorComboBox.setBounds(69, 95, 101, 23);
        editPanel.add(colorComboBox);

        JLabel lblR = new JLabel("R");
        lblR.setBounds(10, 139, 11, 14);
        editPanel.add(lblR);

        redField.setColumns(10);
        redField.setBounds(22, 136, 37, 20);
        editPanel.add(redField);

        JLabel lblG = new JLabel("G");
        lblG.setBounds(68, 139, 11, 14);
        editPanel.add(lblG);

        greenField.setColumns(10);
        greenField.setBounds(79, 136, 37, 20);
        editPanel.add(greenField);

        JLabel lblB = new JLabel("B");
        lblB.setBounds(126, 139, 10, 14);
        editPanel.add(lblB);

        blueField.setColumns(10);
        blueField.setBounds(133, 136, 37, 20);
        editPanel.add(blueField);

        colorPanel = new JPanel();
        colorPanel.setBorder(new LineBorder(new Color(0, 0, 0)));
        colorPanel.setBackground(defaultGraphColor);
        colorPanel.setBounds(10, 164, 59, 38);
        editPanel.add(colorPanel);


        btnAdd.setBounds(10, 213, 59, 23);
        editPanel.add(btnAdd);

        //============================= WINDOWBUILDER COMPONENTS END =================//

    }

    //=============================== END CONSTRUCTOR ==============================//

    private static void addPopup(Component component, final JPopupMenu popup) {
    }

    //=============================== METHODS ======================================//
    @Override
    public void repaintTree() {
        treeModel.reload();
    }

    @Override
    public void addTrackedObject(ArrayList<AbstractCpsObject> hlList) {
        objectsNode.removeAllChildren();
        switchesNode.removeAllChildren();
        groupNode.removeAllChildren();
        objectHashtable.clear();
        if (hlList.size() > 0 && hlList != null) {
            for (AbstractCpsObject abs : hlList) {
                String name = abs.getName() + " " + abs.getId();
                DefaultMutableTreeNode tmp = new DefaultMutableTreeNode(name);
                Hashtable<String, PropertyDataSet> tmpHash = new Hashtable<>();

                //HolonObjects
                if (abs instanceof HolonObject) {
                    tmp.add(new DefaultMutableTreeNode(TOT_PROD_OBJ));
                    tmp.add(new DefaultMutableTreeNode(TOT_CONS_OBJ));
                    tmp.add(new DefaultMutableTreeNode(NR_ACTIVE_ELEMENTS));
                    tmpHash.put(TOT_PROD_OBJ, new PropertyDataSet());
                    tmpHash.put(TOT_CONS_OBJ, new PropertyDataSet());
                    tmpHash.put(NR_ACTIVE_ELEMENTS, new PropertyDataSet());
                    objectsNode.add(tmp);
                }

                //HolonSwitches
                if (abs instanceof HolonSwitch) {
                    tmp.add(new DefaultMutableTreeNode(SW_ACTIVE));
                    tmpHash.put(SW_ACTIVE, new PropertyDataSet());
                    switchesNode.add(tmp);
                }

                //NodesOfNodes
                if (abs instanceof CpsUpperNode) {
                    tmp.add(new DefaultMutableTreeNode(TOT_PROD_GRID));
                    tmp.add(new DefaultMutableTreeNode(TOT_CONS_GRID));
                    tmpHash.put(TOT_PROD_GRID, new PropertyDataSet());
                    tmpHash.put(TOT_CONS_GRID, new PropertyDataSet());
                    groupNode.add(tmp);
                }

                GraphDataSet gS = new GraphDataSet(abs, tmpHash);
                objectHashtable.put(name, gS);
            }
        }
        if (objectsNode.getChildCount() == 0) {
            objectsNode.add(new DefaultMutableTreeNode("empty"));
        }
        if (switchesNode.getChildCount() == 0) {
            switchesNode.add(new DefaultMutableTreeNode("empty"));
        }
        if (groupNode.getChildCount() == 0) {
            groupNode.add(new DefaultMutableTreeNode("empty"));
        }

    }

    private void colorChanged(Color color) {
        colorPanel.setBackground(color);
    }

    private void resetFields() {
        colorPanel.setBackground(defaultGraphColor);
        redField.setText("");
        greenField.setText("");
        blueField.setText("");
        colorComboBox.setSelectedIndex(0);
    }

    private void disableFields() {
        redField.setEnabled(false);
        greenField.setEnabled(false);
        blueField.setEnabled(false);
        graphNrTxtField.setEnabled(false);
        colorComboBox.setEnabled(false);
        colorPanel.setBackground(Color.LIGHT_GRAY);
    }

    private void enableFields() {
        redField.setEnabled(true);
        greenField.setEnabled(true);
        blueField.setEnabled(true);
        graphNrTxtField.setEnabled(true);
        colorComboBox.setEnabled(true);
        colorPanel.setBackground(defaultGraphColor);
    }

    void repaintGraphs() {
        for (StatisticGraphPanel sg : graphHashtable.values()) {
            sg.calcMaximum();
            sg.addValues();
            sg.repaint();
        }
    }

    JPanel getGraphPanel() {
        return graphPanel;
    }

	public void updateIterations() {
		for(Enumeration<StatisticGraphPanel> dataEnum=graphHashtable.elements();dataEnum.hasMoreElements();){
			dataEnum.nextElement().getStatGraph().updateIterations();
		}
	}
}
