/*******************************************************************************
 * Copyright (C) 2009 The University of Manchester
 * 
 * Modifications to the initial code base are copyright of their respective
 * authors, or their employers as appropriate.
 * 
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 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 Lesser General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307
 ******************************************************************************/
package org.apache.taverna.ui.perspectives.myexperiment;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.ParseException;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Vector;

import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.SwingUtilities;

import org.apache.taverna.ui.perspectives.myexperiment.model.Base64;
import org.apache.taverna.ui.perspectives.myexperiment.model.MyExperimentClient;
import org.apache.taverna.ui.perspectives.myexperiment.model.SearchEngine;
import org.apache.taverna.ui.perspectives.myexperiment.model.Util;
import org.apache.taverna.ui.perspectives.myexperiment.model.SearchEngine.QuerySearchInstance;
import org.apache.taverna.workbench.icons.WorkbenchIcons;

import org.apache.log4j.Logger;

/**
 * @author Sergejs Aleksejevs
 */
public class SearchTabContentPanel extends JPanel implements ActionListener {
  // CONSTANTS
  private final static int SEARCH_HISTORY_LENGTH = 50;
  private final static int SEARCH_FAVOURITES_LENGTH = 30;
  protected final static String SEARCH_FROM_FAVOURITES = "searchFromFavourites";
  protected final static String SEARCH_FROM_HISTORY = "searchFromHistory";
  protected final static String ADD_FAVOURITE_SEARCH_INSTANCE = "addFavouriteSearchInstance";
  protected final static String REMOVE_FAVOURITE_SEARCH_INSTANCE = "removeFavouriteSearchInstance";

  private final MainComponent pluginMainComponent;
  private final MyExperimentClient myExperimentClient;
  private final Logger logger;

  // COMPONENTS
  private JSplitPane spMainSplitPane;
  private SearchOptionsPanel jpSearchOptions;
  private JPanel jpFavouriteSearches;
  private JPanel jpSearchHistory;
  private SearchResultsPanel jpSearchResults;
  private final ImageIcon iconFavourite = new ImageIcon(MyExperimentPerspective.getLocalResourceURL("favourite_icon"));
  private final ImageIcon iconRemove = new ImageIcon(MyExperimentPerspective.getLocalResourceURL("destroy_icon"));

  // Data storage
  private QuerySearchInstance siPreviousSearch;
  private LinkedList<QuerySearchInstance> llFavouriteSearches;
  private LinkedList<QuerySearchInstance> llSearchHistory;

  // Search components 
  private final SearchEngine searchEngine; // The search engine for executing keyword query searches 
  private final Vector<Long> vCurrentSearchThreadID; // This will keep ID of the current search thread (there will only be one such thread)

  public SearchTabContentPanel(MainComponent component, MyExperimentClient client, Logger logger) {
	super();

	// set main variables to ensure access to myExperiment, logger and the parent component
	this.pluginMainComponent = component;
	this.myExperimentClient = client;
	this.logger = logger;

	// initialise the favourite searches
	String strFavouriteSearches = (String) myExperimentClient.getSettings().get(MyExperimentClient.INI_FAVOURITE_SEARCHES);
	if (strFavouriteSearches != null) {
	  Object oFavouriteSearches = Base64.decodeToObject(strFavouriteSearches);
	  this.llFavouriteSearches = (LinkedList<QuerySearchInstance>) oFavouriteSearches;
	} else {
	  this.llFavouriteSearches = new LinkedList<QuerySearchInstance>();
	}

	// initialise the search history
	String strSearchHistory = (String) myExperimentClient.getSettings().get(MyExperimentClient.INI_SEARCH_HISTORY);
	if (strSearchHistory != null) {
	  Object oSearchHistory = Base64.decodeToObject(strSearchHistory);
	  this.llSearchHistory = (LinkedList<QuerySearchInstance>) oSearchHistory;
	} else {
	  this.llSearchHistory = new LinkedList<QuerySearchInstance>();
	}

	this.initialiseUI();
	this.updateFavouriteSearches();
	this.updateSearchHistory();

	// initialise the search engine
	vCurrentSearchThreadID = new Vector<Long>(1);
	vCurrentSearchThreadID.add(null); // this is just a placeholder, so that it's possible to update this value instead of adding new ones later
	this.searchEngine = new SearchEngine(vCurrentSearchThreadID, false, jpSearchResults, pluginMainComponent, myExperimentClient, logger);

	SwingUtilities.invokeLater(new Runnable() {
	  public void run() {
		// THIS MIGHT NOT BE NEEDED AS THE SEARCH OPTIONS BOX NOW
		// SETS THE MINIMUM SIZE OF THE SIDEBAR PROPERLY
		spMainSplitPane.setDividerLocation(390);
		spMainSplitPane.setOneTouchExpandable(true);
		spMainSplitPane.setDoubleBuffered(true);
	  }
	});
  }

  private void initialiseUI() {
	// create search options panel
	jpSearchOptions = new SearchOptionsPanel(this, this.pluginMainComponent, this.myExperimentClient, this.logger);
	jpSearchOptions.setMaximumSize(new Dimension(1024, 0)); // HACK: this is to make sure that search options box won't be stretched

	// create favourite searches panel
	jpFavouriteSearches = new JPanel();
	jpFavouriteSearches.setMaximumSize(new Dimension(1024, 0)); // HACK: this is to make sure that favourite searches box won't be stretched
	jpFavouriteSearches.setLayout(new GridBagLayout());
	jpFavouriteSearches.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), " Favourite Searches "), BorderFactory.createEmptyBorder(0, 5, 5, 5)));

	// create search history panel
	jpSearchHistory = new JPanel();
	jpSearchHistory.setMaximumSize(new Dimension(1024, 0)); // HACK: this is to make sure that search history box won't be stretched
	jpSearchHistory.setLayout(new GridBagLayout());
	jpSearchHistory.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), " Search History "), BorderFactory.createEmptyBorder(0, 5, 5, 5)));

	// create the search sidebar
	JPanel jpSearchSidebar = new JPanel();
	jpSearchSidebar.setLayout(new GridBagLayout());

	GridBagConstraints gbConstraints = new GridBagConstraints();
	gbConstraints.anchor = GridBagConstraints.NORTHWEST;
	gbConstraints.fill = GridBagConstraints.BOTH;
	gbConstraints.weightx = 1;
	gbConstraints.gridx = 0;

	gbConstraints.gridy = 0;
	jpSearchSidebar.add(jpSearchOptions, gbConstraints);

	gbConstraints.gridy = 1;
	jpSearchSidebar.add(jpFavouriteSearches, gbConstraints);

	gbConstraints.gridy = 2;
	jpSearchSidebar.add(jpSearchHistory, gbConstraints);

	JPanel jpSidebarContainer = new JPanel();
	jpSidebarContainer.setLayout(new BorderLayout());
	jpSidebarContainer.add(jpSearchSidebar, BorderLayout.NORTH);

	// wrap sidebar in a scroll pane
	JScrollPane spSearchSidebar = new JScrollPane(jpSidebarContainer);
	spSearchSidebar.getVerticalScrollBar().setUnitIncrement(ResourcePreviewBrowser.PREFERRED_SCROLL);
	spSearchSidebar.setMinimumSize(new Dimension(jpSidebarContainer.getMinimumSize().width + 20, 0));

	// create panel for search results
	this.jpSearchResults = new SearchResultsPanel(this, pluginMainComponent, myExperimentClient, logger);

	spMainSplitPane = new JSplitPane();
	spMainSplitPane.setLeftComponent(spSearchSidebar);
	spMainSplitPane.setRightComponent(jpSearchResults);

	// PUT EVERYTHING TOGETHER
	this.setLayout(new BorderLayout());
	this.add(spMainSplitPane);
  }

  private void addToSearchListQueue(LinkedList<QuerySearchInstance> searchInstanceList, QuerySearchInstance searchInstanceToAdd, int queueSize) {
	// check if such entry is already in the list
	int iDuplicateIdx = searchInstanceList.indexOf(searchInstanceToAdd);

	// only do the following if the new search instance list OR current instance is not the same
	// as the last one in the list
	if (searchInstanceList.size() == 0
		|| iDuplicateIdx != searchInstanceList.size() - 1) {
	  // if the current item is already in the list, remove it (then re-add at the end of the list)
	  if (iDuplicateIdx >= 0)
		searchInstanceList.remove(iDuplicateIdx);

	  // we want to keep the history size constant, therefore when it reaches a certain
	  // size, oldest element needs to be removed
	  if (searchInstanceList.size() >= queueSize)
		searchInstanceList.remove();

	  // in either case, add the new element to the tail of the search history
	  searchInstanceList.offer(searchInstanceToAdd);
	}
  }

  private void addToFavouriteSearches(QuerySearchInstance searchInstance) {
	this.addToSearchListQueue(this.llFavouriteSearches, searchInstance, SEARCH_FAVOURITES_LENGTH);
	Collections.sort(this.llFavouriteSearches);
  }

  // the method to update search history listing
  protected void updateFavouriteSearches() {
	this.jpFavouriteSearches.removeAll();

	if (this.llFavouriteSearches.size() == 0) {
	  GridBagConstraints c = new GridBagConstraints();
	  c.weightx = 1.0;
	  c.anchor = GridBagConstraints.WEST;
	  this.jpFavouriteSearches.add(Util.generateNoneTextLabel("No favourite searches"), c);
	} else {
	  for (int i = this.llFavouriteSearches.size() - 1; i >= 0; i--) {
		addEntryToSearchListingPanel(this.llFavouriteSearches, i, SEARCH_FROM_FAVOURITES, this.jpFavouriteSearches, this.iconRemove, REMOVE_FAVOURITE_SEARCH_INSTANCE, "<html>Click to remove from your local favourite searches.<br>"
			+ "(This will not affect your myExperiment profile settings.)</html>");
	  }
	}

	this.jpFavouriteSearches.repaint();
	this.jpFavouriteSearches.revalidate();
  }

  private void addToSearchHistory(QuerySearchInstance searchInstance) {
	this.addToSearchListQueue(this.llSearchHistory, searchInstance, SEARCH_HISTORY_LENGTH);
  }

  // the method to update search history listing
  protected void updateSearchHistory() {
	this.jpSearchHistory.removeAll();

	if (this.llSearchHistory.size() == 0) {
	  GridBagConstraints c = new GridBagConstraints();
	  c.weightx = 1.0;
	  c.anchor = GridBagConstraints.WEST;
	  this.jpSearchHistory.add(Util.generateNoneTextLabel(SearchResultsPanel.NO_SEARCHES_STATUS), c);
	} else {
	  for (int i = this.llSearchHistory.size() - 1; i >= 0; i--) {
		addEntryToSearchListingPanel(this.llSearchHistory, i, SEARCH_FROM_HISTORY, this.jpSearchHistory, this.iconFavourite, ADD_FAVOURITE_SEARCH_INSTANCE, "<html>Click to add to your local favourite"
			+ " searches - these will be available every time you use Taverna.<br>(This will not affect your"
			+ " myExperiment profile settings.)</html>");
	  }
	}

	this.jpSearchHistory.repaint();
	this.jpSearchHistory.revalidate();

	// also update search history in History tab
	if (this.pluginMainComponent.getHistoryBrowser() != null) {
	  this.pluginMainComponent.getHistoryBrowser().refreshSearchHistory();
	}
  }

  private void addEntryToSearchListingPanel(List<QuerySearchInstance> searchInstanceList, int iIndex, String searchAction, JPanel panelToPopulate, ImageIcon entryIcon, String iconAction, String iconActionTooltip) {
	// labels with search query and search settings
	JClickableLabel jclCurrentEntryLabel = new JClickableLabel(searchInstanceList.get(iIndex).getSearchQuery(), searchAction
		+ ":" + iIndex, this, WorkbenchIcons.findIcon, SwingUtilities.LEFT, searchInstanceList.get(iIndex).toString());
	JLabel jlCurrentEntrySettings = new JLabel(searchInstanceList.get(iIndex).detailsAsString());
	jlCurrentEntrySettings.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0));

	// grouping search details and search settings together
	JPanel jpCurentEntryDetails = new JPanel();
	jpCurentEntryDetails.setLayout(new GridBagLayout());
	GridBagConstraints c = new GridBagConstraints();

	c.anchor = GridBagConstraints.WEST;
	jpCurentEntryDetails.add(jclCurrentEntryLabel, c);
	c.weightx = 1.0;
	jpCurentEntryDetails.add(jlCurrentEntrySettings, c);

	// creating a "button" to add current item to favourites
	JClickableLabel jclFavourite = new JClickableLabel("", iconAction + ":"
		+ iIndex, this, entryIcon, SwingUtilities.LEFT, iconActionTooltip);
	jclFavourite.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0));

	// putting all pieces of current item together
	JPanel jpCurrentEntry = new JPanel();
	jpCurrentEntry.setLayout(new GridBagLayout());

	c.anchor = GridBagConstraints.WEST;
	c.weightx = 1.0;
	jpCurrentEntry.add(jpCurentEntryDetails, c);

	c.anchor = GridBagConstraints.WEST;
	c.weightx = 0;
	jpCurrentEntry.add(jclFavourite, c);

	// adding current item to the history list 
	c.fill = GridBagConstraints.HORIZONTAL;
	c.weightx = 1.0;
	c.gridx = 0;
	c.gridy = GridBagConstraints.RELATIVE;
	panelToPopulate.add(jpCurrentEntry, c);
  }

  public void actionPerformed(ActionEvent e) {
	if (e.getSource().equals(this.jpSearchOptions.bSearch)) {
	  // "Search" button was clicked

	  // if no search query is specified, display error message
	  if (jpSearchOptions.getSearchQuery().length() == 0) {
		javax.swing.JOptionPane.showMessageDialog(null, "Search query is empty. Please specify your search query and try again.", "Error", JOptionPane.WARNING_MESSAGE);
		jpSearchOptions.focusSearchQueryField();
	  } else {
		// will ensure that if the value in the search result limit editor
		// is invalid, it is processed properly
		try {
		  this.jpSearchOptions.jsResultLimit.commitEdit();
		} catch (ParseException ex) {
		  JOptionPane.showMessageDialog(null, "Invalid search result limit value. This should be an\n"
			  + "integer in the range of "
			  + SearchOptionsPanel.SEARCH_RESULT_LIMIT_MIN
			  + ".."
			  + SearchOptionsPanel.SEARCH_RESULT_LIMIT_MAX, "MyExperiment Plugin - Error", JOptionPane.WARNING_MESSAGE);
		  this.jpSearchOptions.tfResultLimitTextField.selectAll();
		  this.jpSearchOptions.tfResultLimitTextField.requestFocusInWindow();
		  return;
		}

		// all fine, settings present - store the settings..
		siPreviousSearch = new SearchEngine.QuerySearchInstance(jpSearchOptions.getSearchQuery(), jpSearchOptions.getResultCountLimit(), jpSearchOptions.getSearchWorkflows(), jpSearchOptions.getSearchFiles(), jpSearchOptions.getSearchPacks(), jpSearchOptions.getSearchUsers(), jpSearchOptions.getSearchGroups());

		// .. and execute the query
		this.jpSearchOptions.focusSearchQueryField();
		this.runSearch();
	  }
	} else if (e.getSource() instanceof JClickableLabel) {
	  if (e.getActionCommand().startsWith(SEARCH_FROM_HISTORY)
		  || e.getActionCommand().startsWith(SEARCH_FROM_FAVOURITES)) {
		// the part of the action command that is following the prefix is the ID in the search history / favourites storage;
		// this search instance is removed from history and will be re-added at the top of it when search is launched 
		int iEntryID = Integer.parseInt(e.getActionCommand().substring(e.getActionCommand().indexOf(":") + 1));
		final QuerySearchInstance si = (e.getActionCommand().startsWith(SEARCH_FROM_HISTORY) ? this.llSearchHistory.remove(iEntryID) : this.llFavouriteSearches.get(iEntryID)); // in case of favourites, no need to remove the entry

		// re-set search options in the settings box and re-run the search
		SwingUtilities.invokeLater(new Runnable() {
		  public void run() {
			jpSearchOptions.setSearchQuery(si.getSearchQuery());
			jpSearchOptions.setSearchAllResourceTypes(false); // reset the 'all resource types'
			jpSearchOptions.setSearchWorkflows(si.getSearchWorkflows());
			jpSearchOptions.setSearchFiles(si.getSearchFiles());
			jpSearchOptions.setSearchPacks(si.getSearchPacks());
			jpSearchOptions.setSearchUsers(si.getSearchUsers());
			jpSearchOptions.setSearchGroups(si.getSearchGroups());
			jpSearchOptions.setResultCountLimit(si.getResultCountLimit());

			// set this as the 'latest' search
			siPreviousSearch = si;

			// run the search (and update the search history)
			runSearch();
		  }
		});
	  } else if (e.getActionCommand().startsWith(ADD_FAVOURITE_SEARCH_INSTANCE)) {
		// get the ID of the entry in the history listing first; then fetch the instance itself
		int iHistID = Integer.parseInt(e.getActionCommand().substring(e.getActionCommand().indexOf(":") + 1));
		final QuerySearchInstance si = this.llSearchHistory.get(iHistID);

		// add item to favourites and re-draw the panel
		SwingUtilities.invokeLater(new Runnable() {
		  public void run() {
			addToFavouriteSearches(si);
			updateFavouriteSearches();
		  }
		});
	  } else if (e.getActionCommand().startsWith(REMOVE_FAVOURITE_SEARCH_INSTANCE)) {
		// get the ID of the entry in the favourite searches listing first; then remove the instance with that ID from the list
		int iFavouriteID = Integer.parseInt(e.getActionCommand().substring(e.getActionCommand().indexOf(":") + 1));
		this.llFavouriteSearches.remove(iFavouriteID);

		// item removed from favourites - re-draw the panel now
		SwingUtilities.invokeLater(new Runnable() {
		  public void run() {
			updateFavouriteSearches();
		  }
		});
	  }
	} else if (e.getSource().equals(this.jpSearchResults.bRefresh)) {
	  // "Refresh" button clicked; disable clearing results and re-run previous search
	  this.jpSearchResults.bClear.setEnabled(false);
	  this.rerunLastSearch();
	} else if (e.getSource().equals(this.jpSearchResults.bClear)) {
	  // "Clear" button clicked - clear last search and disable re-running it
	  siPreviousSearch = null;
	  vCurrentSearchThreadID.set(0, null);
	  this.jpSearchResults.clear();
	  this.jpSearchResults.setStatus(SearchResultsPanel.NO_SEARCHES_STATUS);
	  this.jpSearchResults.bClear.setEnabled(false);
	  this.jpSearchResults.bRefresh.setEnabled(false);
	}
  }

  // search history will get updated by default
  private void runSearch() {
	runSearch(true);
  }

  // makes preparations and runs the current search 
  // (has an option not to update the search history)
  private void runSearch(boolean bUpdateHistory) {
	if (bUpdateHistory) {
	  // add current search to search history ..
	  this.addToSearchHistory(siPreviousSearch);

	  // .. update the search history box ..
	  SwingUtilities.invokeLater(new Runnable() {
		public void run() {
		  updateSearchHistory();
		}
	  });
	}

	// ..and run the query
	this.searchEngine.searchAndPopulateResults(siPreviousSearch);
  }

  // re-executes the search for the most recent query
  // (if searches have already been done before or were not cleared)
  public void rerunLastSearch() {
	if (this.siPreviousSearch != null) {
	  runSearch();
	}
  }

  public SearchResultsPanel getSearchResultPanel() {
	return (this.jpSearchResults);
  }

  public LinkedList<QuerySearchInstance> getSearchFavouritesList() {
	return (this.llFavouriteSearches);
  }

  public LinkedList<QuerySearchInstance> getSearchHistory() {
	return (this.llSearchHistory);
  }

}
