// PathVisio,
// a tool for data visualization and analysis using Biological Pathways
// Copyright 2006-2011 BiGCaT Bioinformatics
//
// Licensed 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.
//
package org.pathvisio.gui.dialogs;

import java.awt.Component;
import java.awt.Frame;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.SwingWorker;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;

import org.bridgedb.AttributeMapper;
import org.bridgedb.DataSource;
import org.bridgedb.IDMapperException;
import org.bridgedb.IDMapperStack;
import org.bridgedb.Xref;
import org.pathvisio.core.data.XrefWithSymbol;
import org.pathvisio.core.debug.Logger;
import org.pathvisio.core.model.LineType;
import org.pathvisio.core.model.PathwayElement;
import org.pathvisio.core.util.ProgressKeeper;
import org.pathvisio.gui.DataSourceModel;
import org.pathvisio.gui.ProgressDialog;
import org.pathvisio.gui.SwingEngine;
import org.pathvisio.gui.completer.CompleterQueryTextField;
import org.pathvisio.gui.completer.OptionProvider;
import org.pathvisio.gui.util.PermissiveComboBox;

public class LineDialog extends PathwayElementDialog implements ItemListener {

	/**
	 * Dialog for editing Reactions/ Interactions. In addition to the 
	 * standard comments and literature tabs, this has a tab for looking 
	 * up accession numbers of reactions/interactions.
	 */
	private static final long serialVersionUID = 1L;
	

	protected LineDialog(final SwingEngine swingEngine, final PathwayElement e, final boolean readonly, final Frame frame, final Component locationComp) {
		super(swingEngine, e, readonly, frame, "Interaction properties", locationComp);
		getRootPane().setDefaultButton(null);
		setButton.requestFocus();
	}
	CompleterQueryTextField idText;
	private PermissiveComboBox dbCombo;
	private PermissiveComboBox typeCombo;
	private DataSourceModel dsm;
	XrefWithSymbol ref;
	String id;

	public final void refresh() {
		super.refresh();
		idText.setText(getInput().getElementID());
		dsm.setSelectedItem(input.getDataSource());
		String lType = getInput().getEndLineType().toString();
		typeCombo.setSelectedItem(LineType.fromName(lType));
		dsm.setInteractionFilter(true);
		pack();
	}

	private void applyAutoFill(final XrefWithSymbol ref)
	{
		String sym = ref.getSymbol();
		if (sym == null || sym.equals ("")) {
			sym = ref.getId();
		}
		idText.setText(ref.getId());
		String type = ref.getDataSource().getType();
		if (!type.equals(null)) {
			typeCombo.setSelectedItem(LineType.LINE);
		}
		dsm.setSelectedItem(ref.getDataSource());
		}

//	/**
//	 * Search for symbols or ids in the synonym databases that match
//	 * the given text
//	 */
//	private void search(final String aText)
//	{
//		if(aText == null || "".equals(aText.trim())) {
//			JOptionPane.showMessageDialog(this, "No search term specified, " +
//			"please type something in the 'Search' field");
//			return;
//		}
//		final String text = aText.trim();
//
//		final ProgressKeeper progress = new ProgressKeeper();
//		ProgressDialog dialog = new ProgressDialog(null, "Searching", progress, true, true);
//		dialog.setLocationRelativeTo(this);
//
//		SwingWorker<List<XrefWithSymbol>, Void> sw = new SwingWorker<List<XrefWithSymbol>, Void>() {
//			private static final int QUERY_LIMIT = 200;
//
//			protected List<XrefWithSymbol> doInBackground() throws IDMapperException
//			{
//				IDMapperStack gdb = swingEngine.getGdbManager().getCurrentGdb();
//
//			    //The result set
//				List<XrefWithSymbol> result = new ArrayList<XrefWithSymbol>();
//
//		    	for (Map.Entry<Xref, String> i :
//		    		gdb.freeAttributeSearch( text, AttributeMapper.MATCH_ID, QUERY_LIMIT).entrySet())
//		    	{
//		    		result.add (new XrefWithSymbol (i.getKey(), i.getValue()));
//		    	}
//		    	for (Map.Entry<Xref, String> i :
//		    		gdb.freeAttributeSearch( text, "Symbol", QUERY_LIMIT).entrySet())
//		    	{
//		    		result.add (new XrefWithSymbol (i.getKey(), i.getValue()));
//		    	}
//				return result;
//			}
//
//			@Override
//			public void done()
//			{
//				progress.finished();
//				if (!progress.isCancelled())
//				{
//					List<XrefWithSymbol> results = null;
//					try
//					{
//						results = get();
//						//Show results to user
//						if(results != null && results.size() > 0) {
//							DatabaseSearchDialog resultDialog = new DatabaseSearchDialog("Results", results);
//							resultDialog.setVisible(true);
//							XrefWithSymbol selected = resultDialog.getSelected();
//							if(selected != null) {
//								applyAutoFill(selected);
//							}
//						} else {
//							JOptionPane.showMessageDialog(LineDialog.this,
//									"No results for '" + text + "'");
//						}
//					} catch (InterruptedException e) {
//						//Ignore, thread interrupted. Same as cancel.
//					}
//					catch (ExecutionException e) {
//						JOptionPane.showMessageDialog(LineDialog.this,
//								"Exception occurred while searching,\n" +
//								"see error log for details.", "Error",
//								JOptionPane.ERROR_MESSAGE);
//						Logger.log.error("Error while searching", e);
//					}
//				}
//			}
//		};
//		sw.execute();
//		dialog.setVisible(true);
//	}

	protected final void addCustomTabs(final JTabbedPane parent) {
		JPanel panel = new JPanel();
		panel.setLayout(new GridBagLayout());

		JPanel searchPanel = new JPanel();
		JPanel fieldPanel = new JPanel();
//		searchPanel.setBorder(BorderFactory.createTitledBorder("Search"));
		fieldPanel.setBorder(BorderFactory.createTitledBorder("Manual entry"));
		GridBagConstraints panelConstraints = new GridBagConstraints();
		panelConstraints.fill = GridBagConstraints.BOTH;
		panelConstraints.gridx = 0;
		panelConstraints.weightx = 1;
		panelConstraints.weighty = 1;
		panelConstraints.insets = new Insets(2, 2, 2, 2);
		panelConstraints.gridy = GridBagConstraints.RELATIVE;

		panel.add(searchPanel, panelConstraints);
		panel.add(fieldPanel, panelConstraints);

		//Search panel elements
		searchPanel.setLayout(new GridBagLayout());
//Commenting out search for now due to lack of interaction annotation database
//		final JTextField searchText = new JTextField();
//		final JButton searchButton = new JButton("Search");

		//Key listener to search when user presses Enter
//		searchText.addKeyListener(new KeyAdapter() {
//			public void keyReleased(final KeyEvent e) {
//				if (e.getKeyCode() == KeyEvent.VK_ENTER) {
//					searchButton.requestFocus();
//					search(searchText.getText());
//				}
//			}
//		});

//		searchButton.addActionListener(new ActionListener() {
//			public void actionPerformed(final ActionEvent e) {
//				search(searchText.getText());
//			}
//		});
//		searchButton.setToolTipText("Search the synonym database for references, based on the text label");

		GridBagConstraints searchConstraints = new GridBagConstraints();
		searchConstraints.gridx = GridBagConstraints.RELATIVE;
		searchConstraints.fill = GridBagConstraints.HORIZONTAL;
		searchConstraints.weightx = 1;
//		searchPanel.add(searchText, searchConstraints);

		searchConstraints.weightx = 0;
//		searchPanel.add(searchButton, searchConstraints);

		//Manual entry panel elements
		fieldPanel.setLayout(new GridBagLayout());
		
		JLabel typeLabel = new JLabel("Biological Type");
		JLabel idLabel = new JLabel("Identifier");
		JLabel dbLabel = new JLabel("Database");
		
		idText = new CompleterQueryTextField(new OptionProvider() {
			public List<String> provideOptions(final String text) {
				if(text == null) {
					return Collections.emptyList();
				}

				IDMapperStack gdb = swingEngine.getGdbManager().getCurrentGdb();
				Set<Xref> refs = new HashSet<Xref>();
				try
				{
					refs = gdb.freeSearch(text, 100);
				}
				catch (IDMapperException ignore) {}

				//Only take identifiers
				List<String> ids = new ArrayList<String>();
				for (Xref ref : refs) ids.add(ref.getId());
				return ids;
			}
		}, true);
		
		idText.setCorrectCase(false);

		dsm = new DataSourceModel();
		dsm.setPrimaryFilter(true);
		dsm.setSpeciesFilter(swingEngine.getCurrentOrganism());
		dbCombo = new PermissiveComboBox(dsm);
		typeCombo = new PermissiveComboBox(LineType.getValues());
		
		GridBagConstraints c = new GridBagConstraints();
		c.ipadx = c.ipady = 5;
		c.anchor = GridBagConstraints.FIRST_LINE_START;
		c.weightx = 0;
		c.gridx = 0;
		c.gridy = GridBagConstraints.RELATIVE;
		fieldPanel.add(typeLabel, c);
		fieldPanel.add(idLabel, c);
		fieldPanel.add(dbLabel, c);
		c.gridx = 1;
		c.fill = GridBagConstraints.HORIZONTAL;
		c.weightx = 1;
		
		fieldPanel.add(typeCombo, c);
		fieldPanel.add(idText, c);
		fieldPanel.add(dbCombo, c);

		idText.getDocument().addDocumentListener(new DocumentListener() {
			public void changedUpdate(final DocumentEvent e) { setText();	}
			public void insertUpdate(final DocumentEvent e) {	setText(); }
			public void removeUpdate(final DocumentEvent e) { setText(); }
			private void setText() {
				getInput().setElementID(idText.getText());
			}
		});

		dsm.addListDataListener(new ListDataListener()
		{

			public void contentsChanged(final ListDataEvent arg0)
			{
				getInput().setDataSource((DataSource)dsm.getSelectedItem());

			}

			public void intervalAdded(final ListDataEvent arg0) {	}

			public void intervalRemoved(final ListDataEvent arg0) { }
		});

		typeCombo.addActionListener(new ActionListener() {
			public void actionPerformed(final ActionEvent e) {
				LineType item = (LineType)typeCombo.getSelectedItem();
				getInput().setEndLineType(item);
				refresh();
			}
		});

		idText.setEnabled(!readonly);
		dbCombo.setEnabled(!readonly);
		typeCombo.setEnabled(!readonly);

		parent.add("Annotation", panel);
		parent.setSelectedComponent(panel);
	}

	@Override
	public void itemStateChanged(final ItemEvent arg0) {
		// TODO Auto-generated method stub
		}
}