package de.tu_darmstadt.tk.SmartHomeNetworkSim.view.popups;

import javax.swing.JFrame;
import javax.swing.JPanel;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.util.LinkedList;
import java.util.Observable;
import java.util.Observer;

import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JButton;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.border.EmptyBorder;

import de.tu_darmstadt.tk.SmartHomeNetworkSim.control.Controller;
import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.Model;
import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.Port;
import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.ProbabilityDistributionHandler;

public class PortDistributionConfigurationPopUp extends JFrame implements Observer{
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	private Port port;
	
	private JSplitPane splitPane;
	
	private JScrollPane scrollPane;
	/**
	 * ComboBox for link selection
	 */
	private JComboBox<String> cmbDistribution;
	
	/**
	 * Distributions that can be selected;
	 */
	LinkedList<Class<? extends ProbabilityDistributionHandler>> availableDistributions;
	
	/**
	 * Last index which was selected in the combo box
	 */
	int lastIndex = -1;
	
	boolean mutex = false;
	
	private Controller controller;
	
	private PortDistributionConfigurationPopUp that = this;
	
	public PortDistributionConfigurationPopUp(Port port, Controller controller) {
		this.port = port;
		this.controller = controller;
		this.setSize(480, 360);
		splitPane = new JSplitPane();
		splitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
		splitPane.setBorder(new EmptyBorder(0, 0, 0, 0));
		getContentPane().add(splitPane, BorderLayout.CENTER);
		
		JPanel panel = new JPanel();
		splitPane.setLeftComponent(panel);
		panel.setLayout(null);
		
		JLabel lblDescription = new JLabel("Distribution Type:");
		lblDescription.setBounds(10, 10, 120, 20);
		panel.add(lblDescription);
		
		cmbDistribution = new JComboBox<String>();
		cmbDistribution.setBounds(120, 10, 190, 20);
		panel.add(cmbDistribution);
		
		JButton btnImport = new JButton("Import");
		btnImport.setBounds(320, 10, 100, 20);
		panel.add(btnImport);
		btnImport.addActionListener(a -> {
			ImportPopUp<ProbabilityDistributionHandler> popUp = new ImportPopUp<ProbabilityDistributionHandler>(this, ProbabilityDistributionHandler.class);
			try {
				Class<? extends ProbabilityDistributionHandler> imported = popUp.showPopUp();
				if (imported == null)
					return;
				if (controller.getImportController().addDistributionHandler(imported)) {
					update(null, null);
				} else {
					JOptionPane.showMessageDialog(that, "Import failed: Invalid Distribution Handler");
				}
			} catch (Exception e1) {
				JOptionPane.showMessageDialog(that, "Import failed: " + e1.getMessage());
			}
		});

		splitPane.setDividerLocation(40);
		
		scrollPane = new JScrollPane();
		splitPane.setRightComponent(scrollPane);
		
		update(null,null);
		
		this.addWindowListener(new WindowAdapter() {
			public void windowClosing(java.awt.event.WindowEvent e) {
				that.controller.removeObserver(that);
			}
		});
		
		cmbDistribution.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				if (mutex)
					return;

				/**
				 * New Distribution
				 */
				ProbabilityDistributionHandler newDistribution = null;
				try {
					// Create new Instance of the protocol
					newDistribution = controller.getImportController().getDistributionHandlers()
							.get(cmbDistribution.getSelectedIndex()).newInstance();
				} catch (InstantiationException | IllegalAccessException e1) {
					System.out.println("WARNING: Distribution could not be initialized");
				}
				if (newDistribution == null) {
					cmbDistribution.setSelectedIndex(lastIndex);
					System.out.println("WARNING: Invalid Distribution Selected - restore last index");
				} else {
					/**
					 * Add new Distribution
					 */
					port.setTriggerHandler(newDistribution);
					/**
					 * Update Index
					 */
					lastIndex = cmbDistribution.getSelectedIndex();
					
					update(null, null);
				}
			}
		});
		
		this.controller.addObserver(this);
	}

	@Override
	public void update(Observable o, Object arg) {
		if(port == null)return;
		ProbabilityDistributionHandler handler = port.getTriggerHandler();
		
		if(handler!=null)
			scrollPane.setViewportView(handler.getConfigurationPanel());
		else{
			scrollPane.setViewportView(null);
			return;
		}
		
		
		mutex = true;
		/**
		 *  Update Distribution function
		 */
		availableDistributions = controller.getImportController().getDistributionHandlers();
		cmbDistribution.removeAllItems();
		for (int i = 0; i < availableDistributions.size(); i++)
			try {
				cmbDistribution.addItem(availableDistributions.get(i).newInstance().getSimpleDescription());
			} catch (InstantiationException | IllegalAccessException e1) {
				System.out.println("Distribution " + i + " is invalid");
				cmbDistribution.addItem("unknown");
			}
		// Set Index to selected Protocol
		lastIndex = -1;
		for (int i = 0; i < availableDistributions.size(); i++) {
			if (handler.getClass().equals(availableDistributions.get(i))) {
				// Select the right protocol and save last index
				lastIndex = i;
			}
		}
		cmbDistribution.setSelectedIndex(lastIndex);
		
		mutex = false;
	}
	
	public static void main(String[] args) {
		PortDistributionConfigurationPopUp test = new PortDistributionConfigurationPopUp(null, new Controller(new Model()));
		test.setEnabled(true);
		test.setVisible(true);
	}
}
