package Connection;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.BindException;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.text.NumberFormatter;

import api.AddOn;
import classes.AbstractCanvasObject;
import classes.GroupNode;
import classes.HolonObject;
import Connection.ConnectPhysical.HolonObjectStatus;
import Connection.ConnectPhysical.PhysicalLinkWrapper;
import Connection.socket.Server;
import ui.controller.Control;
import ui.view.Console;

public class ConnectHandheld implements AddOn{
	
	//Holeg
	Control control;
	private HolonObject observed;
	
	//Gui
	private JPanel content = new JPanel();
	private JTextArea textArea;
	

	//TCP
	int port = 4242;
	Server server;
	
	private Console console;
	private boolean holonObjectConnected;
	private JLabel houseLabel;
	




	public static void main(String[] args)
	{
	      JFrame newFrame = new JFrame("exampleWindow");
	      ConnectHandheld instance = new ConnectHandheld();
	      newFrame.setContentPane(instance.getPanel());
	      newFrame.pack();
	      newFrame.setVisible(true);
	      newFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}

	
	
	
	
	public ConnectHandheld() {
		content.setLayout(new BorderLayout());
		
		textArea = new JTextArea();
		textArea.setEditable(false);
		console = new Console();
		JScrollPane scrollPane = new JScrollPane(console);
		JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
				createSettingsPanel() , scrollPane);
		splitPane.setResizeWeight(0.0);
		content.add(splitPane, BorderLayout.CENTER);
		content.setPreferredSize(new Dimension(400,600));	
	}


	
	private JPanel createSettingsPanel() {
		JPanel settingsPanel = new JPanel(null);
		settingsPanel.setPreferredSize(new Dimension(400, 400));
		settingsPanel.setMinimumSize(new Dimension(400, 225));
		
		NumberFormat format = NumberFormat.getIntegerInstance();
		format.setGroupingUsed(false);
		format.setParseIntegerOnly(true);
		NumberFormatter integerFormatter = new NumberFormatter(format);
		integerFormatter.setMinimum(0);
		integerFormatter.setMaximum(65535);
		integerFormatter.setCommitsOnValidEdit(true);
		
		
		
		JLabel portLabel = new JLabel("Port:");
		portLabel.setBounds(10, 20, 35, 30);
		settingsPanel.add(portLabel);
		JFormattedTextField portTF = new JFormattedTextField(integerFormatter);
		portTF.setText(""+port);
		portTF.setBounds(55 ,20, 80, 30);
		portTF.addPropertyChangeListener(propertyChange ->{
			String text = portTF.getValue().toString();
			text = text.replaceAll("\\s", "");
			port = Integer.parseInt((text));
		});
		settingsPanel.add(portTF);
		
		
		houseLabel = new JLabel("House Status: " + (holonObjectConnected?"Connected":"Not selected"));
		houseLabel.setBounds(10, 90, 220, 30);
		settingsPanel.add(houseLabel);
		
		JButton selectRoom1Button = new JButton("Select");
		selectRoom1Button.setBounds(230,95, 90, 20);
		selectRoom1Button.addActionListener(actionEvent -> this.selectHolonObject());
		settingsPanel.add(selectRoom1Button);
		
		
		JButton connectButton = new JButton("Start Server");
		connectButton.setBounds(100 ,175, 200, 50);
		connectButton.addActionListener(actionEvent -> connect());
		settingsPanel.add(connectButton);

		return settingsPanel;
	}











	private void connect() {
		if(!holonObjectConnected) {
			console.println("Select a HolonObject");
			return;
		}
		try {
			if(server != null) {
				server.stopServer();
			}
			console.println("Start Server on Port:" + port);
			server = new Server(port, console, observed, control);
		}catch(BindException e){
			console.println(e.getMessage());
		}
		catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	

	@Override
	public JPanel getPanel() {
		return content;
	}

	@Override
	public void setController(Control control) {
		this.control = control;
	}

	
		private void selectHolonObject() {
			List<HolonObject> holonObjectList = new ArrayList<HolonObject>();
			addObjectToList(control.getModel().getObjectsOnCanvas(),holonObjectList);
			Object[] possibilities = holonObjectList.stream().map(aCps -> new Handle<HolonObject>(aCps)).toArray();
			@SuppressWarnings("unchecked")
			Handle<HolonObject> selected = (Handle<HolonObject>) JOptionPane.showInputDialog(content, "Select HolonObject:", "HolonObject?",  JOptionPane.OK_OPTION,new ImageIcon(new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB)) , possibilities, "");
			if(selected != null) {
				console.println("Selected: " + selected);
				observed = selected.object;
				holonObjectConnected = true;
				if(server != null) {
					server.setObserved(selected.object);
				}
				updateSelectionLabel();
			}
		}
		
		private void updateSelectionLabel() {
			houseLabel.setText("House Status: " + (holonObjectConnected?"Connected":"Not selected"));
		}





		private void addObjectToList(List<AbstractCanvasObject> listToSearch, List<HolonObject> listToAdd){
			for (AbstractCanvasObject aCps : listToSearch) {
				if (aCps instanceof HolonObject) listToAdd.add((HolonObject) aCps);
				else if(aCps instanceof GroupNode) {
					addObjectToList(((GroupNode)aCps).getNodes(),listToAdd);
				}
			}
		}
		
		
		private   class  Handle<T>{
			public T object;
			Handle(T object){
				this.object = object;
			}
			public String toString() {
				return object.toString();
			}
		}
	
}
