/**
 *
 */
package org.apache.taverna.activities.externaltool.manager;
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.swing.AbstractAction;
import javax.swing.DefaultListCellRenderer;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;
import org.apache.taverna.activities.externaltool.manager.InvocationGroup;
import org.apache.taverna.activities.externaltool.manager.InvocationManagerEvent;
import org.apache.taverna.activities.externaltool.manager.InvocationMechanism;
import org.apache.taverna.activities.externaltool.manager.MechanismCreator;

import org.apache.taverna.activities.externaltool.manager.impl.InvocationGroupManagerImpl;
import org.apache.taverna.lang.observer.Observable;
import org.apache.taverna.lang.observer.Observer;
import org.apache.taverna.lang.ui.DeselectingButton;
import org.apache.taverna.lang.ui.ValidatingUserInputDialog;
import org.apache.taverna.workbench.helper.Helper;

/**
 * @author alanrw
 *
 */
public class ToolInvocationConfigurationPanel extends JPanel implements
		Observer<InvocationManagerEvent> {

	public static final String HEADER_TEXT = "A tool can be set to run at an explicit location (e.g. on a specificic machine or one of a set of machines). Alternatively, it can be set to run at a symbolic location, which means the tool will then be run at the explicit location pointed to by the symbolic location.";

	private final InvocationGroupManager manager;

	private final List<InvocationMechanismEditor<?>> invocationMechanismEditors;

	private final JTextArea headerText;

	private static String EXPLICIT_LOCATIONS = "explicit locations";
	private static String SYMBOLIC_LOCATIONS = "symbolic locations";

	private final List<MechanismCreator> mechanismCreators;

	JList locationList = new JList();

	DefaultListModel groupListModel = new DefaultListModel();
	DefaultListModel mechanismListModel = new DefaultListModel();
	JComboBox locationTypeCombo = new JComboBox(new String[] { EXPLICIT_LOCATIONS,
			SYMBOLIC_LOCATIONS });

	public ToolInvocationConfigurationPanel(List<MechanismCreator> mechanismCreators,
			List<InvocationMechanismEditor<?>> invocationMechanismEditors, InvocationGroupManager manager) {
		super();
		this.mechanismCreators = mechanismCreators;
		this.invocationMechanismEditors = invocationMechanismEditors;
		this.manager = manager;
		manager.addObserver(this);

		this.setLayout(new GridBagLayout());
		GridBagConstraints gbc = new GridBagConstraints();

		headerText = new JTextArea(HEADER_TEXT);
		headerText.setLineWrap(true);
		headerText.setWrapStyleWord(true);
		headerText.setEditable(false);
		headerText.setFocusable(false);
		headerText.setBorder(new EmptyBorder(10, 10, 10, 10));

		gbc.anchor = GridBagConstraints.WEST;
		gbc.insets = new Insets(0, 0, 10, 0);
		gbc.gridx = 0;
		gbc.gridy = 0;
		gbc.gridwidth = 1;
		gbc.weightx = 1.0;
		gbc.weighty = 0.0;
		gbc.fill = GridBagConstraints.HORIZONTAL;
		add(headerText, gbc);

		JPanel locationPanel = new JPanel(new BorderLayout());
		JPanel subPanel = new JPanel(new FlowLayout());
		JLabel modify = new JLabel("Modify:");

		locationTypeCombo.setSelectedItem(EXPLICIT_LOCATIONS);
		locationTypeCombo.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				switchList();
			}
		});
		subPanel.add(modify);
		subPanel.add(locationTypeCombo);

		populateLists();
		switchList();
		locationList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		locationList.setCellRenderer(new DefaultListCellRenderer() {
			public Component getListCellRendererComponent(JList list, Object value, int index,
					boolean isSelected, boolean cellHasFocus) {
				Object toShow = value;
				if (value instanceof InvocationGroup) {
					InvocationGroup invocationGroup = (InvocationGroup) value;
					toShow = invocationGroup.getName() + "  -->  "
							+ invocationGroup.getMechanismName();
				}
				return super.getListCellRendererComponent(list, toShow, index, isSelected,
						cellHasFocus);
			}
		});
		locationPanel.add(new JScrollPane(locationList), BorderLayout.CENTER);
		locationPanel.add(subPanel, BorderLayout.NORTH);

		JPanel buttonPanel = new JPanel(new FlowLayout());
		JButton helpButton = new DeselectingButton("Help", new AbstractAction() {

			public void actionPerformed(ActionEvent e) {
				Helper.showHelp(ToolInvocationConfigurationPanel.this);
			}
		});

		buttonPanel.add(helpButton);

		buttonPanel.add(addLocationButton());
		buttonPanel.add(removeLocationButton());
		buttonPanel.add(editLocationButton());
		locationPanel.add(buttonPanel, BorderLayout.SOUTH);

		gbc.gridy++;
		gbc.weighty = 1;

		gbc.fill = GridBagConstraints.BOTH;
		gbc.anchor = GridBagConstraints.SOUTH;
		gbc.insets = new Insets(10, 0, 0, 0);
		this.add(locationPanel, gbc);
	}

	private void switchList() {
		if (isShowingGroups()) {
			locationList.setModel(groupListModel);
		} else {
			locationList.setModel(mechanismListModel);
		}
	}

	private void populateLists() {
		poopulateGroupList();
		populateMechanismList();
	}

	private void populateMechanismList() {
		Object currentSelection = locationList.getSelectedValue();
		ArrayList<InvocationMechanism> mechanisms = new ArrayList<InvocationMechanism>();
		mechanisms.addAll(manager.getMechanisms());
		Collections.sort(mechanisms, new Comparator<InvocationMechanism>() {

			@Override
			public int compare(InvocationMechanism o1, InvocationMechanism o2) {
				return o1.getName().compareTo(o2.getName());
			}
		});
		mechanismListModel.clear();
		for (InvocationMechanism m : mechanisms) {
			mechanismListModel.addElement(m);
		}
		if ((currentSelection != null) && !isShowingGroups()) {
			locationList.setSelectedValue(currentSelection, true);
		}
	}

	private void poopulateGroupList() {
		Object currentSelection = locationList.getSelectedValue();
		ArrayList<InvocationGroup> groups = new ArrayList<InvocationGroup>();
		groups.addAll(manager.getInvocationGroups());
		Collections.sort(groups, new Comparator<InvocationGroup>() {

			@Override
			public int compare(InvocationGroup o1, InvocationGroup o2) {
				return o1.getName().compareTo(o2.getName());
			}
		});
		groupListModel.clear();
		for (InvocationGroup g : groups) {
			groupListModel.addElement(g);
		}
		if ((currentSelection != null) && isShowingGroups()) {
			locationList.setSelectedValue(currentSelection, true);
		}
	}

	private boolean isShowingGroups() {
		return (locationTypeCombo.getSelectedItem().equals(SYMBOLIC_LOCATIONS));
	}

	private JButton addLocationButton() {
		final JButton result = new DeselectingButton("Add", new AbstractAction() {

			@Override
			public void actionPerformed(ActionEvent e) {
				if (isShowingGroups()) {
					Set<String> usedGroupNames = new HashSet<String>();
					for (InvocationGroup g : manager.getInvocationGroups()) {
						usedGroupNames.add(g.getName());
					}

					GroupPanel inputPanel = new GroupPanel(mechanismListModel.toArray(), manager);

					ValidatingUserInputDialog vuid = new ValidatingUserInputDialog(
							"Add symbolic location", inputPanel);
					vuid.addTextComponentValidation(inputPanel.getGroupNameField(),
							"Set the symbolic location name.", usedGroupNames,
							"Duplicate symbolic location name.", "[\\p{L}\\p{Digit}_.]+",
							"Invalid symbolic location name.");
					vuid.setSize(new Dimension(400, 250));

					if (vuid.show(ToolInvocationConfigurationPanel.this)) {
						String groupName = inputPanel.getGroupName();
						InvocationGroup newGroup = new InvocationGroup(mechanismCreators);
						newGroup.setName(groupName);
						newGroup.setMechanism(inputPanel.getSelectedMechanism());
						manager.addInvocationGroup(newGroup);
						locationList.setSelectedValue(newGroup, true);
					}
				} else {
					Set<String> usedNames = new HashSet<String>();
					for (InvocationMechanism m : manager.getMechanisms()) {
						usedNames.add(m.getName());
					}

					MechanismPanel inputPanel = new MechanismPanel(invocationMechanismEditors);

					ValidatingUserInputDialog vuid = new ValidatingUserInputDialog(
							"Add explicit location", inputPanel);
					vuid.addTextComponentValidation(inputPanel.getMechanismNameField(),
							"Set the explicit location name.", usedNames,
							"Duplicate explicit location name.", "[\\p{L}\\p{Digit}_.]+",
							"Invalid explicit location name.");
					vuid.addMessageComponent(inputPanel.getMechanismTypeSelector(),
							"Set the location name and type.");
					vuid.setSize(new Dimension(400, 250));

					if (vuid.show(ToolInvocationConfigurationPanel.this)) {
						String mechanismName = inputPanel.getMechanismName();
						String mechanismTypeName = inputPanel.getMechanismTypeName();
						InvocationMechanismEditor ime = findEditor(mechanismTypeName);
						InvocationMechanism newMechanism = ime.createMechanism(mechanismName);
						manager.addMechanism(newMechanism);
						ime.show(newMechanism);
						ime.setPreferredSize(new Dimension(550, 500));
						int answer = JOptionPane.showConfirmDialog(
								ToolInvocationConfigurationPanel.this, ime,
								"New explicit location", JOptionPane.OK_CANCEL_OPTION,
								JOptionPane.PLAIN_MESSAGE, null);
						if (answer == JOptionPane.OK_OPTION) {
							ime.updateInvocationMechanism();
							manager.mechanismChanged(newMechanism);
						}
						locationList.setSelectedValue(newMechanism, true);
					}
				}
			}
		});
		return result;
	}

	private JButton removeLocationButton() {
		JButton result = new DeselectingButton("Remove", new AbstractAction() {

			@Override
			public void actionPerformed(ActionEvent e) {
				if (isShowingGroups()) {
					InvocationGroup toRemove = (InvocationGroup) locationList.getSelectedValue();
					if ((toRemove != null) && !toRemove.equals(manager.getDefaultGroup())) {
						manager.removeInvocationGroup(toRemove);
					}
					locationList.setSelectedValue(manager.getDefaultGroup(), true);
				} else {
					InvocationMechanism toRemove = (InvocationMechanism) locationList
							.getSelectedValue();
					if ((toRemove != null) && !toRemove.equals(manager.getDefaultMechanism())) {
						manager.removeMechanism(toRemove);
						locationList.setSelectedValue(manager.getDefaultMechanism(), true);
					}
				}
			}
		});
		return result;
	}

	private JButton editLocationButton() {
		final JButton result = new DeselectingButton("Edit", new AbstractAction() {

			@Override
			public void actionPerformed(ActionEvent e) {
				if (isShowingGroups()) {
					InvocationGroup toEdit = (InvocationGroup) locationList.getSelectedValue();
					if (toEdit != null) {
						InvocationMechanism chosenMechanism = (InvocationMechanism) JOptionPane
								.showInputDialog(ToolInvocationConfigurationPanel.this,
										"Select an explicit location", "Edit symbolic location",
										JOptionPane.PLAIN_MESSAGE, null,
										mechanismListModel.toArray(), toEdit.getMechanism());
						if (chosenMechanism != null) {
							toEdit.setMechanism(chosenMechanism);
							manager.groupChanged(toEdit);
						}
					}
				} else {
					InvocationMechanism toEdit = (InvocationMechanism) locationList
							.getSelectedValue();
					if (toEdit != null) {
						InvocationMechanismEditor ime = findEditor(toEdit.getClass());
						ime.show(toEdit);
						ime.setPreferredSize(new Dimension(550, 500));
						int answer = JOptionPane.showConfirmDialog(
								ToolInvocationConfigurationPanel.this, ime,
								"Edit explicit location", JOptionPane.OK_CANCEL_OPTION,
								JOptionPane.PLAIN_MESSAGE, null);
						if (answer == JOptionPane.OK_OPTION) {
							ime.updateInvocationMechanism();
							manager.mechanismChanged(toEdit);
						}
					}
				}
			}
		});
		return result;
	}

	protected InvocationMechanismEditor findEditor(String name) {
		for (InvocationMechanismEditor ime : invocationMechanismEditors) {
			if (ime.getName().equalsIgnoreCase(name)) {
				return ime;
			}
		}
		return null;
	}

	protected InvocationMechanismEditor findEditor(Class c) {
		for (InvocationMechanismEditor ime : invocationMechanismEditors) {
			if (ime.canShow(c)) {
				return ime;
			}
		}
		return null;
	}

	@Override
	public void notify(Observable<InvocationManagerEvent> arg0, InvocationManagerEvent arg1)
			throws Exception {
		if (SwingUtilities.isEventDispatchThread()) {
			populateLists();
		} else {
			SwingUtilities.invokeLater(new Runnable() {
				public void run() {
					populateLists();
				}
			});
		}
	}
}
