/*
 * This file is a part of EpnTAPClient.
 * This program aims to provide EPN-TAP support for software clients, like CASSIS spectrum analyzer.
 * See draft specifications: https://voparis-confluence.obspm.fr/pages/viewpage.action?pageId=559861
 * Copyright (C) 2016 Institut de Recherche en Astrophysique et Planétologie.
 *
 * This program is free software: you can
 * redistribute it and/or modify it under the terms of the GNU General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or (at your option) any later
 * version. This program is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 * PURPOSE. See the GNU General Public License for more details. You should have received a copy of
 * the GNU General Public License along with this program. If not, see
 * <http://www.gnu.org/licenses/>.
 */

package eu.omp.irap.vespa.epntapclient.gui.requestpanel.paramfield;

import java.awt.Dimension;
import java.io.File;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.JComboBox;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

import eu.omp.irap.vespa.epntapclient.epntap.request.RequestCtrl;
import eu.omp.irap.vespa.epntapclient.gui.requestpanel.RequestPanelListener;
import eu.omp.irap.vespa.votable.utils.CantSendQueryException;

/**
 * The target name field is used only for the `target_name` parameter. It is a ComboBox which is
 * automatically filled with actual target names which begins by the entered characters, by asking
 * to an online resolver (RESOLVER_URL). The parameter is sent to the controller each time it is
 * updated, so it is possible to enter a parameter that the resolver do not know.
 *
 * @author N. Jourdane
 */
public class TargetNameField extends ParamField implements TextFieldListener {

	/** The logger for the class TargetNameField. */
	private static final Logger LOGGER = Logger.getLogger(TargetNameField.class.getName());

	/** The serial version UID. */
	private static final long serialVersionUID = 1L;

	/** The comboBox to enter the target_name and display target name propositions. */
	private JComboBox<String> comboBox;

	/** The JTextField related to the ComboBox, allowing to listen for text content update. */
	private JTextField field;

	/**
	 * The content of the last entered value. It is used to avoid recursions, because each time an
	 * update event is detected, the resolver is called and the ComboBox is filled with new values,
	 * which trigger a new event.
	 */
	private String lastContent;


	/**
	 * Method constructor
	 *
	 * @param requestPanelListener The listener of the request panel.
	 * @param paramName The name of the parameter.
	 */
	public TargetNameField(RequestPanelListener requestPanelListener, String paramName) {
		super(requestPanelListener, paramName);
		comboBox = new JComboBox<>();
		comboBox.setPreferredSize(new Dimension(MIN_FIELD_WIDTH, FIELD_HEIGHT));
		comboBox.setEditable(true);
		field = (JTextField) comboBox.getEditor().getEditorComponent();
		addChangeListener(this, field);
		this.add(comboBox);
	}

	/**
	 * Constructor of TargetNameField without listener, in order to use only GUI elements.
	 *
	 * @param paraName The name of the parameter.
	 */
	public TargetNameField(String paraName) {
		this(new RequestPanelListener() {

			@Override
			public void onParameterRemoved(String paramName) {
				/** No ParameterRemoved event, we just want the field itself. */
			}

			@Override
			public void onParameterUpdated(String paramName, Object paramValue) {
				/** No ParameterChanged event, we just want the field itself. */
			}

			@Override
			public void onSaveButtonClicked(File file) {
				/** No SaveButtonClicked event, we just want the field itself. */
			}

			@Override
			public void onSendButtonClicked() {
				/** No SendButtonClicked event, we just want the field itself. */
			}
		}, paraName);
	}

	/**
	 * This method is called each time the field is modified.
	 */
	@Override
	public void update(JTextField textField) {
		SwingUtilities.invokeLater(new Runnable() {

			@Override
			public void run() {
				updateComboBox();
			}
		});
	}

	/**
	 * This method is called each time the field is modified. A Runnable is used it is impossible to
	 * modify the comboBox from a DocumentEvent.
	 */
	void updateComboBox() {
		String content = field.getText();
		if (!content.equals(lastContent)) {
			if (content.length() >= 2) {
				lastContent = content;
				comboBox.removeAllItems();
				try {
					for (String s : RequestCtrl.getTargetNames(content)) {
						comboBox.addItem(s);
					}
				} catch (CantSendQueryException e) {
					LOGGER.log(Level.WARNING,
							"Can't get table names for the resolver", e);
				}
				comboBox.getEditor().setItem(content);
				comboBox.showPopup();
			}
			if (content.isEmpty()) {
				requestPanelListener.onParameterRemoved(paramName);
			} else {
				requestPanelListener.onParameterUpdated(paramName, content);
			}
		}
	}

}