package jp.ac.osaka_u.sanken.sparql.gui;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JScrollPane;
import javax.swing.JButton;
import javax.swing.table.DefaultTableModel;

import com.hp.hpl.jena.rdf.model.RDFNode;

import jp.ac.osaka_u.sanken.sparql.EndpointSettingsManager;
import jp.ac.osaka_u.sanken.sparql.SparqlAccessorFactory;
import jp.ac.osaka_u.sanken.sparql.SparqlQueryListener;
import jp.ac.osaka_u.sanken.sparql.SparqlResultListener;
import jp.ac.osaka_u.sanken.sparql.SparqlResultSet;
import jp.ac.osaka_u.sanken.sparql.ThreadedSparqlAccessor;

public class SparqlSearchPanel extends JPanel {

	private static final long serialVersionUID = 1L;
	private JPanel executePanel = null;  //  @jve:decl-index=0:visual-constraint="428,142"
	private JTextArea queryTextArea = null;
	private JPanel footerPanel = null;
	private JScrollPane resultListScrollPane = null;  //  @jve:decl-index=0:visual-constraint="153,224"
	private JTable resultList = null;  //  @jve:decl-index=0:visual-constraint="369,21"
	private JButton runQueryButton = null;  //  @jve:decl-index=0:visual-constraint="390,64"
	private JSplitPane mainSplitPane = null;

	private SparqlAccessorForm parent;
	
	private DefaultTableModel tableModel;

	private ThreadedSparqlAccessor sa;

	
	/**
	 * This is the default constructor
	 */
	public SparqlSearchPanel(SparqlAccessorForm parent) {
		super();
		initialize();
		this.parent = parent;
	}

	/**
	 * This method initializes this
	 * 
	 * @return void
	 */
	private void initialize() {
		this.setSize(300, 200);
		this.setLayout(new BorderLayout());
		this.add(getExecutePanel(), BorderLayout.NORTH);
		this.add(getMainSplitPane(), BorderLayout.CENTER);
	}

	private JSplitPane getMainSplitPane(){
		if (mainSplitPane == null){
			mainSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, getQueryScrollPane(), getFooterPanel());
			mainSplitPane.setDividerLocation(200);
		}
		
		return mainSplitPane;
	}
	
	/**
	 * This method initializes keywordPanel	
	 * 	
	 * @return javax.swing.JPanel	
	 */
	private JPanel getExecutePanel() {
		if (executePanel == null) {
			executePanel = new JPanel();
			executePanel.setLayout(new BorderLayout());
			executePanel.add(getRunQueryButton(), BorderLayout.EAST);
		}
		return executePanel;
	}

	/**
	 * This method initializes keywordTextField	
	 * 	
	 * @return javax.swing.JTextField	
	 */
	private JTextArea getQueryTextField() {
		if (queryTextArea == null) {
			queryTextArea = new JTextArea();
		}
		return queryTextArea;
	}
	
	/**
	 * 検索ワードを取得する
	 * @return
	 */
	public String getFindWord(){
		return getQueryTextField().getText();
	}

	private SparqlResultListener createSparqlResultListener2(){
		return new SparqlResultListener() {
			
			@Override
			public void resultReceived(SparqlResultSet result) {
				// 結果をまずはlistに追加
				setProcessing(false);
				setResults(result);
			}

			@Override
			public void uncaughtException(Thread t, Throwable e) {
				// TODO 自動生成されたメソッド・スタブ
				JOptionPane.showMessageDialog(parent, "Execute error:"+e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
				setProcessing(false);
			}
		};
	}

	/**
	 * This method initializes footerPanel	
	 * 	
	 * @return javax.swing.JPanel	
	 */
	private JPanel getFooterPanel() {
		if (footerPanel == null) {
			footerPanel = new JPanel();
			footerPanel.setLayout(new BorderLayout());
			footerPanel.add(getResultListScrollPane(), BorderLayout.CENTER);
		}
		return footerPanel;
	}

	/**
	 * This method initializes resultListScrollPane	
	 * 	
	 * @return javax.swing.JScrollPane	
	 */
	private JScrollPane getResultListScrollPane() {
		if (resultListScrollPane == null) {
			resultListScrollPane = new JScrollPane(getResultList());
		}
		return resultListScrollPane;
	}

	/**
	 * This method initializes resultList	
	 * 	
	 * @return javax.swing.JList	
	 */
	private JTable getResultList() {
		if (resultList == null) {
			resultList = new JTable();
		}
		return resultList;
	}
	
	public void setResults(SparqlResultSet result){
		List<Map<String, RDFNode>> list = result.getDefaultResult();
		
		if (list.size() == 0){
			tableModel = new DefaultTableModel();
			getResultList().setModel(tableModel);
			return;
		}
		
		// headerセット
		Map<String, RDFNode> columns = list.get(0);
		List<String> clm = new ArrayList<String>();
		for (String key : columns.keySet()){
			clm.add(key);
		}
		tableModel = new DefaultTableModel(clm.toArray(new String[]{}), 0);

		
		// 中身セット
		for (Map<String, RDFNode> r : list){
			List<Object> row = new ArrayList<Object>();
			for (String key : clm){
				RDFNode node = r.get(key);
				row.add(node);
			}
			tableModel.addRow(row.toArray(new Object[]{}));
		}
		
		getResultList().setModel(tableModel);
		
		parent.setResults(result);
	}

	private boolean processing = false;
	private JScrollPane queryScrollPane = null;
	
	private void setProcessing(boolean processing){
		this. processing = processing;
		getRunQueryButton().setEnabled(!processing);
		getResultList().setEnabled(!processing);
		
		parent.setProcessing(processing);
	}
	
	private boolean isProcessing(){
		return this.processing;
	}
	
	/**
	 * This method initializes runQueryButton	
	 * 	
	 * @return javax.swing.JButton	
	 */
	private JButton getRunQueryButton() {
		if (runQueryButton == null) {
			runQueryButton = new JButton("Run Query");
			runQueryButton.addActionListener(new ActionListener() {
				
				@Override
				public void actionPerformed(ActionEvent e) {
					if (isProcessing()){
						return;
					}
					setProcessing(true);
					sa = SparqlAccessorFactory.createSparqlAccessor(EndpointSettingsManager.instance.getSetting(parent.getCurrentEndPoint()), new SparqlQueryListener() {
						
						@Override
						public void sparqlExecuted(String query) {
							parent.addLogText("----------------");
							parent.addLogText(query);
						}
					});
					sa.executeQuery(getFindWord(), createSparqlResultListener2());
				}
			});
		}
		return runQueryButton;
	}

	/**
	 * This method initializes queryScrollPane	
	 * 	
	 * @return javax.swing.JScrollPane	
	 */
	private JScrollPane getQueryScrollPane() {
		if (queryScrollPane == null) {
			queryScrollPane = new JScrollPane(getQueryTextField());
		}
		return queryScrollPane;
	}

}
