package com.redhat.ceylon.eclipse.imp.search;

import java.util.List;
import java.util.Set;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Status;
import org.eclipse.search.ui.ISearchQuery;
import org.eclipse.search.ui.ISearchResult;
import org.eclipse.search.ui.text.AbstractTextSearchResult;
import org.eclipse.ui.IEditorPart;

import com.redhat.ceylon.compiler.typechecker.context.PhasedUnit;
import com.redhat.ceylon.compiler.typechecker.model.Declaration;
import com.redhat.ceylon.compiler.typechecker.tree.Node;
import com.redhat.ceylon.compiler.typechecker.tree.Tree;
import com.redhat.ceylon.compiler.typechecker.tree.Tree.CompilationUnit;
import com.redhat.ceylon.eclipse.imp.builder.CeylonBuilder;
import com.redhat.ceylon.eclipse.imp.editor.CeylonEditor;
import com.redhat.ceylon.eclipse.imp.editor.Util;
import com.redhat.ceylon.eclipse.imp.parser.CeylonParseController;

abstract class FindSearchQuery implements ISearchQuery {
	
	private final Declaration referencedDeclaration;
	//private final IProject project;
	private AbstractTextSearchResult result = new CeylonSearchResult(this);
	private int count = 0;
	private IEditorPart editor;

	FindSearchQuery(Declaration referencedDeclaration, IProject project) {
		this.referencedDeclaration = referencedDeclaration;
		//this.project = project;
		this.editor = Util.getCurrentEditor();
	}

	@Override
	public IStatus run(IProgressMonitor monitor) throws OperationCanceledException {
	    //List<PhasedUnit> units = CeylonBuilder.getUnits(project);
	    //if (units==null) units = CeylonBuilder.getUnits();
	    
	    List<PhasedUnit> units = CeylonBuilder.getUnits();
        for (PhasedUnit pu: units) {
	        CompilationUnit cu = getRootNode(pu);
            Set<Node> nodes = getNodes(cu);
	        //TODO: should really add these as we find them:
            for (Node node: nodes) {
    			FindContainerVisitor fcv = new FindContainerVisitor(node);
    			cu.visit(fcv);
                if (node.getToken()==null) {
                    //a synthetic node inserted in the tree
                }
                else {
        			result.addMatch(new CeylonSearchMatch(fcv.getDeclaration(), 
        			        CeylonBuilder.getFile(pu), 
        					node.getStartIndex(), 
        					node.getStopIndex()-node.getStartIndex()+1,
        					node.getToken()));
                }
    		}
    		count+=nodes.size();
        }
		return Status.OK_STATUS;
	}

    Tree.CompilationUnit getRootNode(PhasedUnit pu) {
        if (editor instanceof CeylonEditor) {
            CeylonParseController cpc = ((CeylonEditor)editor).getParseController();
            if ( editor.isDirty() &&
                    pu.getUnit().equals(cpc.getRootNode().getUnit()) ) {
                return cpc.getRootNode();
            }
        }
        return pu.getCompilationUnit();
    }
    
    protected abstract Set<Node> getNodes(Tree.CompilationUnit cu);
    
    protected abstract String labelString();

	@Override
	public ISearchResult getSearchResult() {
		return result;
	}

	@Override
	public String getLabel() {
		return "Displaying " + count + " " + labelString() + 
		        " '" + referencedDeclaration.getName() + "'";
	}

	@Override
	public boolean canRunInBackground() {
		return true;
	}

	@Override
	public boolean canRerun() {
		return false;
	}
}
@@ -502,16 +502,54 @@
 torPart;
+%0Aimport org.eclipse.ui.IWorkbenchPage;
 %0A%0Aimport
@@ -1351,25 +1351,26 @@
 te I
-EditorPart editor
+WorkbenchPage page
 ;%0A%0A%09
@@ -1529,22 +1529,20 @@
 %0A%09%09this.
-editor
+page
  = Util.
@@ -1548,21 +1548,18 @@
 .get
-CurrentEditor
+ActivePage
 ();%0A
@@ -2685,24 +2685,87 @@
 dUnit pu) %7B%0A
+        for (IEditorPart editor: page.getDirtyEditors()) %7B%0A    
         if (
@@ -2794,24 +2794,28 @@
 onEditor) %7B%0A
+    
             
@@ -2903,13 +2903,19 @@
     
+    
 if ( 
+/*
 edit
@@ -2929,17 +2929,20 @@
 rty() &&
-%0A
+*/%0A 
         
@@ -2953,16 +2953,19 @@
         
+   
 pu.getUn
@@ -3021,24 +3021,28 @@
             
+    
 return cpc.g
@@ -3051,24 +3051,42 @@
 RootNode();%0A
+                %7D%0A
             

Make FindXxxxx queries handle all dirty editors correctly