package ui.view.additional;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.Dialog.ModalityType;
import java.awt.Dimension;
import java.awt.event.ItemEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.math.RoundingMode;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.DefaultComboBoxModel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;
import javax.swing.text.NumberFormatter;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;

import classes.AbstractCanvasObject;
import classes.Constrain;
import classes.GroupNode;
import classes.Flexibility;
import classes.HolonElement;
import classes.HolonElement.Priority;
import model.Model;
import classes.HolonObject;
import ui.controller.Control;
import ui.controller.FlexManager;
import ui.controller.FlexManager.FlexState;
import ui.controller.FlexManager.FlexWrapper;
import utility.ImageImport;


public class FlexWindow extends JFrame {
	private JPanel nothingSelectedPanel;
	private JPanel selectedPanel;
	
	
	private JTabbedPane contentPanel = new JTabbedPane();
	private JScrollPane usageViewPanel;
	
	private Control controller;
	private Model model;
	
	public boolean isClosed = false;
	
	//Flexibility Intermediate
	private Flexibility intermediateFlex = new Flexibility(null);
	private boolean offered = true, onConstrain = true, offConstrain =false;
	
	
	
	//JTree
	private DefaultMutableTreeNode listOfAllSelectedHolonObjects;
	private JTree stateTree;
	private DefaultTreeModel treeModel;
	private FlexManager flexmanager;
	
	//Tabs
	String gridTabString = "Grid";
	String orderTabString = "Order";
	
	//FlexToFlexWrapper()
	
	
	
	public FlexWindow(JFrame parentFrame, ui.controller.Control  controller){
		this.intermediateFlex.name = "name";
		this.controller = controller;
		this.model = controller.getModel();
		//InitWindow
		createMenuBar();
		initWindowPanel(parentFrame);
		this.addWindowListener(new java.awt.event.WindowAdapter() {
		    @Override
		    public void windowClosing(java.awt.event.WindowEvent windowEvent) {
		    	isClosed = true;
		    }
		});
		updateSelectedPanel();
		//this.pack();
	}



	private void initWindowPanel(JFrame parentFrame) {
		this.setBounds(0, 0, 400, parentFrame.getHeight()>20?parentFrame.getHeight()- 20:parentFrame.getHeight());
		this.setIconImage(ImageImport.loadImage("/Images/Holeg.png", 30, 30));
		this.setTitle("Flexibility");
		this.setLocationRelativeTo(parentFrame);
		this.setVisible(true);
		//this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
		createNothingSelectedPanel();
		createSelectedPanel();
		createUsageViewPanel();
		contentPanel.addTab(gridTabString, nothingSelectedPanel);
		contentPanel.addTab(orderTabString, usageViewPanel);
		contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
		this.setContentPane(contentPanel);
		this.revalidate();
		
	}

	private void createMenuBar(){
		JMenuBar menuBar = new JMenuBar();
		JMenu canvas = new JMenu("Canvas");
		menuBar.add(canvas);
		JMenuItem updateMenuItem = new JMenuItem("Update");
		updateMenuItem.addActionListener(clicked -> updateSelectedPanel());
		canvas.add(updateMenuItem);
		JMenu flex = new JMenu("Flex");
		menuBar.add(flex);
		JMenuItem addMenuItem = new JMenuItem("Add Flexibility");
		addMenuItem.addActionListener(clicked -> createAddDialog(null));
		flex.add(addMenuItem);
		JMenuItem deleteMenuItem = new JMenuItem("Delete Flexibility");
		deleteMenuItem.addActionListener(clicked -> createDeleteDialog());
		flex.add(deleteMenuItem);
		
		this.setJMenuBar(menuBar);
	}
	
	

	
	private void createUsageViewPanel() {
		flexmanager = controller.getSimManager().getActualFlexManager();
		//GridBagApprouch
		JPanel gridbagPanel =  new JPanel(new GridBagLayout());
		usageViewPanel = new JScrollPane(gridbagPanel);
		gridbagPanel.setBackground(Color.white);
		//5breit
		FlexState[] titles = FlexState.values();
		
		
		
		for(int i = 0; i<5; i++){
			
			
			
			
			List<FlexWrapper> listOfFlexWithState = flexmanager.getAllFlexWrapperWithState(titles[i]);
			JLabel label = new JLabel(titles[i].toString() + "[" + listOfFlexWithState.size()+ "]");									
			GridBagConstraints labelC = new GridBagConstraints();
			labelC.gridx = 1;
			labelC.gridy = i*2;
			labelC.anchor = GridBagConstraints.LINE_START;
			labelC.fill = GridBagConstraints.HORIZONTAL;
			labelC.weightx = 0.5;
			labelC.weighty = 0.0;
			gridbagPanel.add(label, labelC);
			
			JPanel listPanel = new JPanel(new GridBagLayout());
			createFlexPanel(listPanel, listOfFlexWithState);
			GridBagConstraints panelC = new GridBagConstraints();
			panelC.gridx = 0;
			panelC.gridwidth = 2;
			panelC.gridy = i*2 +1;
			panelC.fill = GridBagConstraints.BOTH;
			gridbagPanel.add(listPanel, panelC);

			
			
			JButton expandButton = new JButton("-");
			GridBagConstraints buttonC = new GridBagConstraints();
			buttonC.gridx = 0;
			buttonC.gridy = i*2;
			gridbagPanel.add(expandButton, buttonC);
			expandButton.addActionListener(clicked -> {
				listPanel.setVisible(!listPanel.isVisible());
				expandButton.setText(listPanel.isVisible()?"-":"+");
			});
			
		}
		//Add Spacer
		JLabel spacer = new JLabel();
		GridBagConstraints c = new GridBagConstraints();
		c.gridx = 0;
		c.gridy = 5*2;
		c.fill = GridBagConstraints.VERTICAL;
		c.weightx = 0.0;
		c.weighty = 1;
		gridbagPanel.add(spacer, c);
		
		
		
		
		
		
		
		
		
		
		
	
		
		

	}

	


	private void createFlexPanel(JPanel listPanel, List<FlexWrapper> flexWrapperList) {
		listPanel.setBackground(Color.white);
		
		Insets insets = new Insets(2,2,2,2);
		
		//String[] flexesString = flexWrapperList.stream().map(flexWrapper -> flexWrapper.getFlex().name).toArray(String[]::new);
		for(int i = 0; i < flexWrapperList.size(); i++) {
			FlexWrapper actual = flexWrapperList.get(i);
			GridBagConstraints c = new GridBagConstraints();
			c.gridx = Math.floorMod(i, 5);
			c.weightx = 0.0;	
			c.insets = insets;
			JButton labelButton = new JButton(actual.getFlex().name);
			labelButton.setPreferredSize(new Dimension(70,70));
			labelButton.setBorder(BorderFactory.createLineBorder(Color.black));
			listPanel.add(labelButton, c);
			labelButton.addActionListener(clicked ->{
				actual.order();
				controller.calculateStateAndVisualForCurrentTimeStep();
				controller.updateCanvas();
			});
			labelButton.setToolTipText(createToolTipp(actual));
		}
		//AddSpacer
		JLabel spacer = new JLabel();
		GridBagConstraints c = new GridBagConstraints();
		c.gridx = 5;
		c.gridy = 0;
		c.fill = GridBagConstraints.VERTICAL;
		c.weightx = 1;
		c.weighty = 0;
	
		listPanel.add(spacer, c);
		
	}


	private String createToolTipp(FlexWrapper actual) {
		String tooltipString = "<html>" +
	"<b>" + actual.getFlex().name + "( </b>" + actual.getFlex().getElement().getEleName() + "<b> )</b><br>"
	+ ((actual.remainingDuration() != 0)?"<i>Remaining Duration:"+ actual.remainingDuration()+"</i><br>":"") 
	+ ((actual.remainingTimeTillActivation() != 0)?"<i>Remaining TimeTillActivation:"+ actual.remainingTimeTillActivation()+"</i><br>":"")
	+ "Duration: " + actual.getFlex().getDuration()  + "<br>"
	+ "Cooldown: " + actual.getFlex().getCooldown() + "<br>"
	//+ "Speed: " + actual.getFlex().speed + "<br>"
	+ "Cost: " + actual.getFlex().cost + "<br>"
	+ "BrigtMir: " + actual.getFlex().bringtmir() + "<br>"
	+ "Constrains: " + actual.getFlex().constrainList.stream().map(constrain -> constrain.getName()).collect(Collectors.joining( "," )) + "<br>"
	+ "</html>";
		
		return tooltipString;
	}



	public void update() {
		updateSelectedPanel();
		createUsageViewPanel();
		contentPanel.setComponentAt(contentPanel.indexOfTab(orderTabString), usageViewPanel);
		contentPanel.revalidate();
	}

	
	
	
	private void createSelectedPanel() {
		//Liste aller Flexibilities
		listOfAllSelectedHolonObjects = new DefaultMutableTreeNode("HolonObjects");
		treeModel = new DefaultTreeModel(listOfAllSelectedHolonObjects);
		stateTree = new JTree(treeModel);
		stateTree.addMouseListener ( new MouseAdapter ()
		    {
		        public void mousePressed ( MouseEvent e )
		        {
		            if ( SwingUtilities.isRightMouseButton ( e ) )
		            {
		            	
		            	
		                TreePath pathUnderCursor = stateTree.getPathForLocation ( e.getX (), e.getY () );
		                Rectangle pathBounds = stateTree.getUI ().getPathBounds ( stateTree, pathUnderCursor );
		                if ( pathBounds != null && pathBounds.contains ( e.getX (), e.getY () ) )
		                {
		                	TreePath[] selectedPaths = stateTree.getSelectionPaths();
			   	        	if(selectedPaths == null) {
			   	        		stateTree.addSelectionPath(pathUnderCursor);
			   	        	}else {
			   	        		boolean isInselectedPaths = false;
			   	        		for (TreePath path : stateTree.getSelectionPaths()) {
			   	        			if(path.equals(pathUnderCursor)) {
			   	        				isInselectedPaths = true;
			   	        			}
			   	        		}
			   	        		if(!isInselectedPaths) {
			   	        			stateTree.clearSelection();
			   	        			stateTree.addSelectionPath(pathUnderCursor);
			   	        		}
			   	        	}
		                    JPopupMenu menu = new JPopupMenu ();
		                    JMenuItem priorityItem = new JMenuItem("EditPriorities");
			         	    JMenuItem flexItem = new JMenuItem("AddFlex");
			         	    
							priorityItem.addActionListener(clicked -> {
								Priority prio = null;
								if (stateTree.getSelectionPaths() != null)
									for (TreePath path : stateTree.getSelectionPaths()) {
										Object treeNodeUserObject = ((DefaultMutableTreeNode) path.getLastPathComponent())
												.getUserObject();
										if (treeNodeUserObject instanceof ElementInfo) {
											if (prio == null)
												prio = (Priority) JOptionPane.showInputDialog(stateTree,
														"Select the Priority:", "Priority?", JOptionPane.OK_OPTION,
														new ImageIcon(new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB)),
														Priority.values(), "");
											if (prio == null)
												break;
											ElementInfo eleInfo = (ElementInfo) treeNodeUserObject;
											eleInfo.ele.setPriority(prio);
											treeModel.reload((DefaultMutableTreeNode) path.getLastPathComponent());
										}
									}
							});
							flexItem.addActionListener(clicked -> {
								TreePath path = stateTree.getSelectionPath();
								if (path == null)
									return;
								Object treeNodeUserObject = ((DefaultMutableTreeNode) path.getLastPathComponent())
										.getUserObject();
								if (!(treeNodeUserObject instanceof ElementInfo))
									return;
								createAddDialog(((ElementInfo) treeNodeUserObject).ele);
			   	        });
			         	    
		                    menu.add ( priorityItem );
		                    menu.add ( flexItem );
		                    menu.show ( stateTree, pathBounds.x, pathBounds.y + pathBounds.height );
		                }else {
		                	JPopupMenu menu = new JPopupMenu ();
		                    menu.add ( new JMenuItem ( "Other Test" ) );
		                    menu.show ( stateTree, e.getX(), e.getY() );
		                }
		            }
		        }
		    } );
		selectedPanel = new JPanel(new BorderLayout());
		selectedPanel.add(new JScrollPane(stateTree));
	}


	private void createNothingSelectedPanel() {
		nothingSelectedPanel = new JPanel();
		nothingSelectedPanel.setLayout(new BoxLayout(nothingSelectedPanel, BoxLayout.PAGE_AXIS));
		JLabel nothingSelectedTextLabel = new JLabel("No HolonObject exist.");
		nothingSelectedTextLabel.setForeground(Color.gray);
		nothingSelectedTextLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
		nothingSelectedPanel.add(Box.createVerticalGlue());
		nothingSelectedPanel.add(nothingSelectedTextLabel);
		nothingSelectedPanel.add(Box.createVerticalGlue());
	}
	
	public void updateSelectedPanel() {
		//UpdateFlexManager
		flexmanager = controller.getSimManager().getActualFlexManager();
		
		listOfAllSelectedHolonObjects.removeAllChildren();
		//Init with HolonObjects
		for(AbstractCanvasObject aCps: model.getObjectsOnCanvas()) {
			DefaultMutableTreeNode newObjectChild = new DefaultMutableTreeNode(aCps.getName() + " ID:" + aCps.getId());
			if(aCps instanceof HolonObject) expandTreeHolonObject((HolonObject)aCps, newObjectChild);
			if(aCps instanceof GroupNode)expandTreeUpperNode((GroupNode)aCps, newObjectChild);
			listOfAllSelectedHolonObjects.add(newObjectChild);
		}
		treeModel.nodeStructureChanged(listOfAllSelectedHolonObjects);
	
		stateTree.revalidate();
		expandAll(stateTree);
		selectedPanel.revalidate();
		contentPanel.setComponentAt(contentPanel.indexOfTab(gridTabString), selectedPanel);
		contentPanel.revalidate();
		this.revalidate();
	}



	private void expandAll(JTree tree) {
		for(int i = 0; i< tree.getRowCount() ; i++) {
			tree.expandRow(i);
		}
		
	}



	private void expandTreeUpperNode(GroupNode groupNode, DefaultMutableTreeNode root) {
		for(AbstractCanvasObject aCps: groupNode.getNodes()) {
			DefaultMutableTreeNode newObjectChild = new DefaultMutableTreeNode(aCps.getName() + " ID:" + aCps.getId());
			if(aCps instanceof HolonObject) expandTreeHolonObject((HolonObject)aCps, newObjectChild);
			if(aCps instanceof GroupNode)expandTreeUpperNode((GroupNode)aCps, newObjectChild);
			root.add(newObjectChild);
		}
		
	}



	private void expandTreeHolonObject(HolonObject hObject, DefaultMutableTreeNode root) {
		for(HolonElement hElement: hObject.getElements()) {
			DefaultMutableTreeNode newChild = new DefaultMutableTreeNode(new ElementInfo(hElement));
			expandTreeFlex(hElement, newChild);
			root.add(newChild);
		}
	}
	private void expandTreeFlex(HolonElement hElement, DefaultMutableTreeNode root) {
		for(Flexibility flex: hElement.flexList) {
			FlexWrapper flexWrapper = this.flexmanager.getFlexWrapperFromFlexibility(flex);
			String flexState = "";
			if(flexWrapper != null) {
				Color color = this.FlexStateToColor(flexWrapper.getState());
				flexState = "<font bgcolor='#" + Integer.toHexString(color.getRGB()).substring(2) + "'>" + flexWrapper.getState().name() + "</font>";
			}
			DefaultMutableTreeNode newChild = new DefaultMutableTreeNode("<html>"+ flexState + " <b>" + flex.name+ "</b>" + "</html>");
			root.add(newChild);
		}
	}
	
	
	private void createDeleteDialog() {
		
		List<HolonObject> list= createListOfHolonObjects(model.getObjectsOnCanvas());
		
		//String test = list.stream().map(Object::toString).collect(Collectors.joining(","));
		Object[] allFlexes = list.stream().flatMap(hObject -> hObject.getElements().stream()).flatMap(hElement -> hElement.flexList.stream()).toArray(size -> new Flexibility[size]);
		if(allFlexes.length == 0) {
			JOptionPane.showMessageDialog(this,
					"No Flexibility exist.",
					"Warning",
					JOptionPane.WARNING_MESSAGE);
			return;
		}
		
		
		
		Flexibility toDeleteFlex =(Flexibility) JOptionPane.showInputDialog(this, "Select to Delete Flexibility:", "Flexibility?",  JOptionPane.OK_OPTION,new ImageIcon(new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB)) , allFlexes, "");
		if(toDeleteFlex != null) {
			toDeleteFlex.getElement().flexList.remove(toDeleteFlex);
			controller.getSimManager().calculateStateForTimeStep(model.getCurIteration(), true);
			updateSelectedPanel();
		}
	}
	
	
	
	private List<HolonObject> createListOfHolonObjects(List<AbstractCanvasObject> objectsOnCanvas) {
		List<HolonObject> list = new ArrayList<HolonObject>();
		for(AbstractCanvasObject aCps :  objectsOnCanvas) {
			if(aCps instanceof HolonObject) list.add((HolonObject) aCps);
			else if (aCps instanceof GroupNode) list.addAll(createListOfHolonObjects(((GroupNode)aCps).getNodes()));
		}
		return list;
	}



	//Add Element
	private void createAddDialog(HolonElement element){
		if(model.getObjectsOnCanvas().isEmpty()) {
			JOptionPane.showMessageDialog(this,
					"No HolonObject exist.",
					"Warning",
					JOptionPane.WARNING_MESSAGE);
			return;
		}
		JDialog addDialog = new JDialog();
		addDialog.setTitle("Create Flexibility");
		addDialog.setBounds(0, 0, 820, 400);	
		addDialog.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
		JPanel dialogPanel = new JPanel(new BorderLayout());
		addDialog.setContentPane(dialogPanel);
		JPanel selectionPanel = new JPanel(null);
		dialogPanel.add(selectionPanel, BorderLayout.CENTER);
		JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
		dialogPanel.add(buttonPanel, BorderLayout.PAGE_END);
		
		
		
		
		addDialog.setModalityType(ModalityType.APPLICATION_MODAL);
		
		

		//Erstelle HolonObject AuswahlBox
		HolonObject[] holonObjects = createListOfHolonObjects(model.getObjectsOnCanvas()).stream().toArray(HolonObject[]::new);

		DefaultComboBoxModel<HolonObject> comboBoxModel = new DefaultComboBoxModel<HolonObject>( holonObjects );


		JComboBox<HolonObject> holonObjectSelector = new JComboBox<HolonObject>(comboBoxModel);
		holonObjectSelector.setBounds(10,30, 800, 30);
		
		DefaultComboBoxModel<HolonElement> comboBoxModelElements = new DefaultComboBoxModel<HolonElement>( holonObjects[0].getElements().stream().toArray(size -> new HolonElement[size]));
		JComboBox<HolonElement> holonElementSelector  = new JComboBox<HolonElement>(comboBoxModelElements);
		holonElementSelector.setBounds(10,80, 800, 30);
		
		
		holonObjectSelector.addItemListener(aListener -> {
			if(aListener.getStateChange() == ItemEvent.SELECTED) {
				DefaultComboBoxModel<HolonElement> newComboBoxModelElements = new DefaultComboBoxModel<HolonElement>( ((HolonObject) aListener.getItem()).getElements().stream().toArray(size -> new HolonElement[size]));
				holonElementSelector.setModel(newComboBoxModelElements);
			}
		});
			
		if(element == null) {
			selectionPanel.add(holonObjectSelector);
			selectionPanel.add(holonElementSelector);
			JLabel selectObjectLabel = new JLabel("Select HolonObject:");
			selectObjectLabel.setBounds(10, 10, 200, 20);
			selectionPanel.add(selectObjectLabel);
			JLabel selectElementLabel = new JLabel("Select HolonElement:");
			selectElementLabel.setBounds(10, 60, 200, 20);
			selectionPanel.add(selectElementLabel);
		}
		else {
			JLabel selectElementLabel = new JLabel("Selected: " +element.toString());
			selectElementLabel.setBounds(10, 60, 2000, 20);
			selectionPanel.add(selectElementLabel);
		}
		
		
		
		
		
		
		JPanel flexAttributesBorderPanel = new  JPanel(null);
		flexAttributesBorderPanel.setBounds(10, 120, 800, 200);
		flexAttributesBorderPanel.setBorder(BorderFactory.createTitledBorder("Flexibility Attributes"));
		selectionPanel.add(flexAttributesBorderPanel);	
		JLabel flexNameLabel = new JLabel("Name:");
		flexNameLabel.setBounds(10,20, 50, 20);
		flexAttributesBorderPanel.add(flexNameLabel);
		JFormattedTextField nameTextField = new JFormattedTextField(intermediateFlex.name);
		nameTextField.addPropertyChangeListener(changed -> intermediateFlex.name = nameTextField.getText());
		nameTextField.setBounds(80, 15, 200, 30);
		flexAttributesBorderPanel.add(nameTextField);
		JLabel flexSpeedLabel = new JLabel("Speed:");
		flexSpeedLabel.setBounds(10,55, 50, 20);
		flexAttributesBorderPanel.add(flexSpeedLabel);
		//Integer formatter
		NumberFormat format = NumberFormat.getIntegerInstance();
		format.setGroupingUsed(false);
		format.setParseIntegerOnly(true);
		NumberFormatter integerFormatter = new NumberFormatter(format);
		integerFormatter.setMinimum(0);
		integerFormatter.setCommitsOnValidEdit(true);
		
		
		JFormattedTextField speedTextField = new  JFormattedTextField(integerFormatter);
		speedTextField.setValue(intermediateFlex.speed);
		speedTextField.setToolTipText("Only positive Integer.");
		speedTextField.addPropertyChangeListener(actionEvent -> intermediateFlex.speed = Integer.parseInt(speedTextField.getValue().toString()));
		speedTextField.setBounds(80, 50, 200, 30);
		flexAttributesBorderPanel.add(speedTextField);
		speedTextField.setEnabled(false);
		
		JLabel flexDurationLabel = new JLabel("Duration:");
		flexDurationLabel.setBounds(10,90, 70, 20);
		flexAttributesBorderPanel.add(flexDurationLabel);
		
		
		NumberFormatter moreThenZeroIntegerFormater = new NumberFormatter(format);
		moreThenZeroIntegerFormater.setMinimum(1);
		moreThenZeroIntegerFormater.setCommitsOnValidEdit(true);
		
		JFormattedTextField durationTextField = new  JFormattedTextField(moreThenZeroIntegerFormater);
		durationTextField.setValue(intermediateFlex.getDuration());
		durationTextField.setToolTipText("Only positive Integer bigger then 0.");
		durationTextField.addPropertyChangeListener(actionEvent -> intermediateFlex.setDuration(Integer.parseInt(durationTextField.getValue().toString())));
		durationTextField.setBounds(80, 85, 200, 30);
		flexAttributesBorderPanel.add(durationTextField);
		
		JLabel flexCostsLabel = new JLabel("Costs:");
		flexCostsLabel.setBounds(10,125, 70, 20);
		flexAttributesBorderPanel.add(flexCostsLabel);
		
		//Double Format:
		NumberFormat doubleFormat = NumberFormat.getNumberInstance(Locale.US);
		doubleFormat.setMinimumFractionDigits(1);
		doubleFormat.setMaximumFractionDigits(2);
		doubleFormat.setRoundingMode(RoundingMode.HALF_UP);

		//CostFormatter:
		NumberFormatter costsFormatter = new NumberFormatter(doubleFormat);
		costsFormatter.setMinimum(0.0);
		
		JFormattedTextField costTextField = new JFormattedTextField(costsFormatter);
		costTextField.setValue(intermediateFlex.cost);
		costTextField.setToolTipText("Only non negative Double with DecimalSeperator Point('.').");
		costTextField.addPropertyChangeListener(propertyChange -> intermediateFlex.cost = Float.parseFloat(costTextField.getValue().toString()));
		costTextField.setBounds(80, 120, 200, 30);
		flexAttributesBorderPanel.add(costTextField);
		
		
		
		JLabel flexCooldownLabel = new JLabel("Cooldown:");
		flexCooldownLabel.setBounds(310,20, 70, 20);
		flexAttributesBorderPanel.add(flexCooldownLabel);
		
		
		JFormattedTextField cooldownTextField = new  JFormattedTextField(moreThenZeroIntegerFormater);
		cooldownTextField.setValue(intermediateFlex.getCooldown());
		cooldownTextField.setToolTipText("Only positive Integer.");
		cooldownTextField.addPropertyChangeListener(actionEvent -> intermediateFlex.setCooldown(Integer.parseInt(cooldownTextField.getValue().toString())));
		cooldownTextField.setBounds(380, 15, 200, 30);
		flexAttributesBorderPanel.add(cooldownTextField);
		
		JCheckBox offeredCheckBox = new JCheckBox("Offered");
		offeredCheckBox.setSelected(this.offered);
		offeredCheckBox.setBounds(310, 55, 200, 20);
		flexAttributesBorderPanel.add(offeredCheckBox);
		
		JCheckBox onConstrainCheckBox = new JCheckBox("On_Constrain");
		onConstrainCheckBox.setSelected(this.onConstrain);
		onConstrainCheckBox.setBounds(310, 80, 200, 20);
		flexAttributesBorderPanel.add(onConstrainCheckBox);
		
		JCheckBox offConstrainCheckBox = new JCheckBox("Off_Constrain");
		offConstrainCheckBox.setSelected(this.offConstrain);
		offConstrainCheckBox.setBounds(310, 105, 200, 20);
		flexAttributesBorderPanel.add(offConstrainCheckBox);
		
		
		
		
		//Both cant be true....
		onConstrainCheckBox.addActionListener(clicked -> {
			if(onConstrainCheckBox.isSelected()) offConstrainCheckBox.setSelected(false);
			});
		offConstrainCheckBox.addActionListener(clicked -> {
			if(offConstrainCheckBox.isSelected()) onConstrainCheckBox.setSelected(false);
			});
		
		JButton createFlexButton = new JButton("Create");
		createFlexButton.addActionListener(clicked -> {
			//createFlexButton.requestFocus();
			//createFlexButton.grabFocus();
			HolonElement ele;
			if(element ==null) {				
				ele = (HolonElement) holonElementSelector.getSelectedItem();
			}else {
				ele =  element;
			}
			Flexibility toCreateFlex = new Flexibility(ele);
			toCreateFlex.name = intermediateFlex.name;
			toCreateFlex.speed = intermediateFlex.speed;
			toCreateFlex.setDuration(intermediateFlex.getDuration());
			toCreateFlex.cost = intermediateFlex.cost;
			toCreateFlex.setCooldown(intermediateFlex.getCooldown());
			toCreateFlex.offered=offeredCheckBox.isSelected();
			if(onConstrainCheckBox.isSelected())toCreateFlex.constrainList.add(Constrain.createOnConstrain());
			if(offConstrainCheckBox.isSelected())toCreateFlex.constrainList.add(Constrain.createOffConstrain());
			
			ele.flexList.add(toCreateFlex);
			//save checkboxes
			this.offered=offeredCheckBox.isSelected();
			this.onConstrain = onConstrainCheckBox.isSelected();
			this.offConstrain = offConstrainCheckBox.isSelected();
			
			
			//if(!model.getSelectedCpsObjects().contains(holonObjectSelector.getSelectedItem()))model.getSelectedCpsObjects().add((AbstractCpsObject)holonObjectSelector.getSelectedItem());
			controller.getSimManager().calculateStateForTimeStep(model.getCurIteration(), true);
			
			update();
			addDialog.dispose();
		});
		buttonPanel.add(createFlexButton);
		JButton cancelButton = new JButton("Cancel");
		cancelButton.addActionListener(clicked -> {
			addDialog.dispose();
		});
		buttonPanel.add(cancelButton);
		
		
		
		//last 
		addDialog.setLocationRelativeTo(this);
		addDialog.setVisible(true);
	}
	
	
	class ElementInfo {
		HolonElement ele;
		public ElementInfo(HolonElement ele) {
			this.ele = ele;
		}
		@Override
		public String toString() {
			return ele.getEleName() + " Priority:" + ele.getPriority();
		}
	}
	
	public Color FlexStateToColor(FlexState state) {
		switch(state) {
		case IN_USE:
			return new Color(173,247,182);
		case NOT_OFFERED:
			return new Color(252,245,199);
		case OFFERED:
			return new Color(160,206,217);
		case ON_COOLDOWN:
			return new Color(255,238,147);
		case UNAVAILABLE:
		default:
			return new Color(255,192,159);
		}
	}
	
}
