content: /*
   * Copyright (c) 2009 Andrejs Jermakovics.
   * 
   * All rights reserved. This program and the accompanying materials
   * are made available under the terms of the Eclipse Public License v1.0
   * which accompanies this distribution, and is available at
   * http://www.eclipse.org/legal/epl-v10.html
   *
   * Contributors:
   *     Andrejs Jermakovics - initial implementation
   */
  package it.unibz.instasearch.ui;
  
  import it.unibz.instasearch.InstaSearchPlugin;
  import it.unibz.instasearch.indexing.Field;
  import it.unibz.instasearch.indexing.WorkspaceIndexerJDT;
  import it.unibz.instasearch.indexing.SearchQuery;
  import it.unibz.instasearch.prefs.PreferenceConstants;
  
  import java.util.Arrays;
  import java.util.Collections;
  import java.util.HashMap;
  import java.util.List;
  import java.util.Map.Entry;
  import java.util.Set;
  import java.util.TreeSet;
  
  import org.apache.commons.lang.StringUtils;
  import org.eclipse.core.resources.IFile;
  import org.eclipse.core.resources.IProject;
  import org.eclipse.core.resources.IResource;
  import org.eclipse.core.runtime.IAdaptable;
  import org.eclipse.jface.dialogs.DialogPage;
  import org.eclipse.jface.preference.StringButtonFieldEditor;
  import org.eclipse.jface.text.TextSelection;
  import org.eclipse.jface.viewers.IStructuredSelection;
  import org.eclipse.search.ui.ISearchPage;
  import org.eclipse.search.ui.ISearchPageContainer;
  import org.eclipse.swt.SWT;
  import org.eclipse.swt.events.SelectionAdapter;
  import org.eclipse.swt.events.SelectionEvent;
  import org.eclipse.swt.layout.GridData;
  import org.eclipse.swt.layout.GridLayout;
  import org.eclipse.swt.widgets.Button;
  import org.eclipse.swt.widgets.Composite;
  import org.eclipse.swt.widgets.Label;
  import org.eclipse.swt.widgets.Link;
  import org.eclipse.swt.widgets.Text;
  import org.eclipse.ui.IWorkingSet;
  import org.eclipse.ui.dialogs.TypeFilteringDialog;
  
  public class InstaSearchPage extends DialogPage implements ISearchPage
  {
  	public static final String ID = "it.unibz.instasearch.ui.InstaSearchPage";
  	/**
  	 * 
  	 */
  	private ISearchPageContainer container;
  	private Text searchText;
  	private Button similarSearch;
  	private StringButtonFieldEditor extensionEditor;
  	//private Button jarSearch;
  
  	public boolean performAction()
  	{
  		HashMap<Field, Set<String>> filter = new HashMap<Field, Set<String>>();
  		
  		if( container.getSelectedScope() == ISearchPageContainer.SELECTED_PROJECTS_SCOPE 
  				&& container.getSelectedProjectNames().length != 0 ) // projects
  		{
  			TreeSet<String> selectedProjects = new TreeSet<String>();
  			Collections.addAll(selectedProjects, container.getSelectedProjectNames());
  			filter.put(Field.PROJ, selectedProjects);
  			
  		} else if( container.getSelectedScope() == ISearchPageContainer.WORKING_SET_SCOPE 
  				&& container.getSelectedWorkingSets().length != 0 ) { // working sets
  			
  			filter.put(Field.WS, getWorkingSetSearchString());
  			
  		} else if( container.getSelectedScope() == ISearchPageContainer.SELECTION_SCOPE 
  				&& !container.getSelection().isEmpty() )
  		{
  			getSelectedResources(filter);
  		}
  		
  		filter.put(Field.EXT, getSelectedExtensions());
  		extensionEditor.store();
  		
  		String searchString = searchText.getText();
  		
  		InstaSearchView searchView = InstaSearchUI.showSearchView();
  		
  		if( searchView != null ) {
  			int maxResults = SearchQuery.UNLIMITED_RESULTS;
  			searchString += convertFilterToString(filter);
  			SearchQuery searchQuery = new SearchQuery(searchString, maxResults);
  			searchQuery.setExact( similarSearch.getSelection() );
  			searchQuery.setFilter(null); // put filters in search string instead
  			
  			searchView.setSearchString(searchString); // to display
  			searchView.search(searchQuery, false);
  		}
  		
  		return true;
  	}
  
  	private void getSelectedResources(HashMap<Field, Set<String>> filter) 
  	{	
  		if( container.getSelection() instanceof IStructuredSelection ) {
  			
  			IStructuredSelection sel = (IStructuredSelection) container.getSelection();
  			
  			for(Object elem: sel.toArray()) 
  			{
  				if( elem instanceof IAdaptable ) {
  					
  					IResource res = null;
  					
  					if( elem instanceof IResource)
  						res = (IResource) elem;
  					else {
  						IAdaptable adaptable = (IAdaptable) elem;
  						res = (IResource) adaptable.getAdapter(IResource.class);
  					}
  					
  					if( res == null ) continue;
  					
  					switch(res.getType())
  					{
  					case IResource.PROJECT:
  						Set<String> projects = filter.containsKey(Field.PROJ)?filter.get(Field.PROJ):new TreeSet<String>();
  						projects.add( ((IProject)res).getName() );
  						filter.put(Field.PROJ, projects);
  						break;
  					case IResource.FILE:
  						Set<String> files = filter.containsKey(Field.FILE)?filter.get(Field.FILE):new TreeSet<String>();
  						files.add( ((IFile)res).getFullPath().toString() );
  						filter.put(Field.FILE, files);
  						break;
  					case IResource.FOLDER:
  						Set<String> folders = filter.containsKey(Field.DIR)?filter.get(Field.DIR):new TreeSet<String>();
  						folders.add( res.getFullPath().toString() );
  						filter.put(Field.DIR, folders);
  						break;
  					}
  					
  				}
  			}
  		}
  	}
  
  	/**
  	 * @param filter
  	 * @return
  	 */
  	private static String convertFilterToString(HashMap<Field, Set<String>> filter) {
  		
  		String filterString = "";
  		
  		for(Entry<Field, Set<String>> entry: filter.entrySet()) {
  			
  			String fieldFilterString = getFieldFilterString(entry.getKey(), entry.getValue());
  			
  			if( !"".equals(fieldFilterString) )
  				filterString += " " + fieldFilterString;
  		}
  		
  		return filterString;
  	}
  
  	private Set<String> getSelectedExtensions() {
  		
  		TreeSet<String> extSet = new TreeSet<String>();
  		
  		String exts = extensionEditor.getStringValue();
  		
  		if( exts != null && ! "".equals(exts) && ! "*".equals(exts)) {
  			exts = exts.replace(" ", "");
  			exts = exts.replace("*.", "");
  			Collections.addAll(extSet, exts.split(","));
  		}
  		
  		return extSet;
  	}
  
  	private Set<String> getWorkingSetSearchString() {
  		
  		Set<String> wsNames = new TreeSet<String>();
  		
  		for(IWorkingSet ws: container.getSelectedWorkingSets()) {
  			String workingSet = ws.getName();
  			wsNames.add(workingSet);
  		}
  		
  		return wsNames;
  	}
  	
  	private static String getFieldFilterString(Field field, Set<String> values)
  	{
  		String filterString = null;
  	
  		if( values.size() == 0 )
  			return "";
  		
  		for (String val : values) {
  			if( filterString == null ) filterString = "";
  			else filterString += ",";
  			filterString += val;
  		}
  		
  		if( filterString.contains(" ") )
  			filterString = '"' + filterString + '"';
  		
  		return field.toString() + ':' + filterString;
  	}
  	
  	
  	
  	public void setContainer(ISearchPageContainer container)
  	{
  		this.container = container;
  	}
  
  	public void createControl(Composite parent)
  	{
  		Composite pageComposite = new Composite(parent, SWT.FILL);
  		
  		GridLayout pageLayout = new GridLayout();
  		pageLayout.numColumns = 1;
  		
  		pageComposite.setLayout(pageLayout);
  		pageComposite.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true,false,1,1));
  		
  		Label label = new Label(pageComposite, SWT.LEFT);
  		label.setText("Search:");
  		label.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, false,false,1,1));
  		
  		searchText = new Text(pageComposite, SWT.SINGLE | SWT.BORDER | SWT.FILL);
  		searchText.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true,false,1,1));
  
  		if (container.getSelection() instanceof TextSelection) {
  			String selection = ((TextSelection) container.getSelection()).getText();
  			searchText.setText(selection);
  		}
  		
  		createShowViewLink(pageComposite);
  		
  		similarSearch = new Button(pageComposite, SWT.CHECK);
  		similarSearch.setText("Find similar matches");
  		similarSearch.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true,false,1,1));
  		
  		if( InstaSearchPlugin.getInstaSearch() != null && InstaSearchPlugin.getInstaSearch().getIndexer() instanceof WorkspaceIndexerJDT )
  		{
  //			jarSearch = new Button(pageComposite, SWT.CHECK);
  //			jarSearch.setText("Exclude JAR files");
  //			jarSearch.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true,false,1,1));
  		}
  		
  		createExtensionEditor(pageComposite);
  		
  		
  		setControl( searchText );
  	}
  
  	private void createExtensionEditor(Composite pageComposite) {
  		
  		GridLayout pageLayout = new GridLayout();
  		pageLayout.numColumns = 1;
  		pageLayout.marginWidth = 1;
  		
  		Composite labelComposite = new Composite(pageComposite, SWT.FILL);
  		labelComposite.setLayout(pageLayout);
  		Label label = new Label(labelComposite, SWT.NONE );
  		label.setText("File types:");
  		labelComposite.setLayoutData(new GridData(GridData.BEGINNING,GridData.CENTER,true,false,1,1));
  		
  		Composite extensionsComposite = new Composite(pageComposite, SWT.FILL);
  		extensionsComposite.setLayout(pageLayout);
  		extensionsComposite.setLayoutData(new GridData(GridData.FILL,GridData.CENTER,true,false,2,1));
  		
  		extensionEditor = new StringButtonFieldEditor(PreferenceConstants.P_SEARCH_EXTENSIONS, "", extensionsComposite) {
  			protected String changePressed() {
  				String exts = this.getStringValue();
  				exts = exts.replace(" ", "");
  				
  				List<String> extList = Arrays.asList(exts.split(","));
  				TypeFilteringDialog dialog = new TypeFilteringDialog(getShell(), extList);
  		        dialog.open();
  		        
  		        Object[] newSelectedTypes = dialog.getResult();
  		        
  		        return StringUtils.join(newSelectedTypes, ",");
  		     }
  			
  		};
  		extensionEditor.setChangeButtonText("Choose...");
  		extensionEditor.setEmptyStringAllowed(true);
  		extensionEditor.setPreferenceStore(InstaSearchPlugin.getDefault().getPreferenceStore());
  		extensionEditor.load();
  		
  		Text txt = extensionEditor.getTextControl(extensionsComposite);
  		txt.setToolTipText("E.g:\njava, xml");
  	}
  
  	private void createShowViewLink(Composite pageComposite) 
  	{	
  		Composite linkComposite = new Composite(pageComposite, SWT.FILL);
  		GridLayout pageLayout = new GridLayout();
  		pageLayout.numColumns = 2;
  		pageLayout.marginWidth = 1;
  		
  		linkComposite.setLayout(pageLayout);
  		linkComposite.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true, false,1,1));
  		
  		Link openViewLink = new Link(linkComposite, SWT.NONE);
  		openViewLink.setText("You can search directly from the <a>search view</a>");
  		openViewLink.addSelectionListener(new SelectionAdapter() {
  			public void widgetSelected(SelectionEvent e) {
  				InstaSearchUI.showSearchView();
  			}
  		});
  		openViewLink.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, false,false,1,1));
  	}
  
  	@Override
  	public void setVisible(boolean visible)
  	{
  		super.setVisible(visible);
  		searchText.setFocus();
  		container.setPerformActionEnabled(true);
  	}
  	
  	
  }
  