package CSU670_Plugin.actions;


import java.util.Iterator;
import java.util.List;

import org.eclipse.jface.action.IAction;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.FindReplaceDocumentAdapter;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.IWorkbenchWindowActionDelegate;
import org.eclipse.jface.dialogs.MessageDialog;

import edu.neu.ccs.demeter.aplib.Traversal;
import edu.neu.ccs.demeter.aplib.sg.Strategy;

import CSU670_Plugin.editors.AspectXEditor;
import CSU670_Plugin.gen.Main;

/**
 * Our sample action implements workbench action delegate.
 * The action proxy will be created by the workbench and
 * shown in the UI. When the user tries to use the action,
 * this delegate will be created and execution will be 
 * delegated to it.
 * @see IWorkbenchWindowActionDelegate
 */
public class AspectXSyntaxHighlight implements IWorkbenchWindowActionDelegate {
	public static final Color red = new Color(Display.getCurrent(),255,0,0);
	public static final Color green = new Color(Display.getCurrent(),0,255,0);
	public static final Color blue = new Color(Display.getCurrent(),0,0,255);
	public static final Color cyan = new Color(Display.getCurrent(),0,255,255);
	public static final Color magenta = new Color(Display.getCurrent(),255,0,255);
	public static final Color yellow = new Color(Display.getCurrent(),255,255,0);
	public static final Color black = new Color(Display.getCurrent(),0,0,0);
	public static final Color white = new Color(Display.getCurrent(),255,255,255);
	public static final Color grey = new Color(Display.getCurrent(), 150,150,150);
	public static AspectXSyntaxHighlight instance=null;
	
	private IWorkbenchWindow window;
	/**
	 * The constructor.
	 */
	public AspectXSyntaxHighlight() {
		super();
		instance=this;
	}

	/**
	 * The action has been activated. The argument of the
	 * method represents the 'real' action sitting
	 * in the workbench UI.
	 * @see IWorkbenchWindowActionDelegate#run
	 */
	public void run(IAction action) {
		String msg="";
		IDocument doc;
		FindReplaceDocumentAdapter f;
		
		do { // so we can "break" out
			try {
				
				if(AspectXEditor.editorCount!=1){
					msg += "Error! Must have exactly one (1) xaj editor\n";
					break;
				}
				if(AspectXEditor.current==null){
					msg += "Error! Only start one editor xaj per session\n";
					break;
				}
				if(Main.userCg==null){
					msg += "Error! Must check syntax first";
					break;
				}
				
				
				doc = AspectXEditor.current.getDocument();
				f = new FindReplaceDocumentAdapter(doc);
				
				String strategy = AspectXEditor.current.currentStrategy();
				
				if(strategy=="") break;
				
				Traversal t = Traversal.compute(Strategy.fromString(strategy), Main.userCg);
				
				List nodes = t.getNodeSets();
				List edges = t.getEdgeSets();
				
				for(Iterator i=nodes.iterator(); i.hasNext();){
					Traversal.NodeSet cur= (Traversal.NodeSet)i.next();
					AspectXEditor.current.highlight(green,
					  f.find(0,cur.getNode()+"[^=a-zA-Z]*=",true,false,false,true).getOffset(),
					  cur.getNode().toString().length()
					);
				}
				
				for(Iterator i=edges.iterator(); i.hasNext();){
					Traversal.EdgeSet cur= (Traversal.EdgeSet)i.next();
					int offset = f.find(0,cur.getEdge().getSource()+"[^=a-zA-Z]*=",true,false,false,true).getOffset();
					AspectXEditor.current.highlight(cyan,
						f.find(offset,"<"+cur.getEdge().getLabel()+">",true,false,false,true)
					);
				}
				
			} catch (Exception e) {
				msg+="Exception!!!";
				e.printStackTrace();
				System.out.println(e.getMessage());
			}		
		} while (false);
		
		if(msg!=""){
			Main.hadERROR=true;
			MessageDialog.openInformation(
				window.getShell(),
				"AspectX Highlight",
				msg);
		}
	}
	
	private static final String keywordregexp 
		= "[(){}.=;:!]|\\b(aspect|ClassDictionary|Traversal|declare|node|set|strategy|nodes|regexp|and|or)\\b";
	
	private static final String commentregexp 
		= "//[^\\n]*|/\\*([^*]|\\*[^/])*\\*/";
	
	public void highlightKeywords(){
		IDocument doc;
		FindReplaceDocumentAdapter f;
		doc = AspectXEditor.current.getDocument();
		f = new FindReplaceDocumentAdapter(doc);
		
		
		try {
			IRegion r;
			for(int i = 0;
				null!=(r=f.find(i,keywordregexp,true,true,false,true));
				i=r.getOffset()+1){
					AspectXEditor.current.highlight(blue,r);
			}
			for(int i = 0;
				null!=(r=f.find(i,commentregexp,true,true,false,true));
				i=r.getOffset()+1){
					AspectXEditor.current.highlight(grey,r);
			}
		} catch (BadLocationException e) {
			//unreachable???
			e.printStackTrace();
		}
		
	}

	/**
	 * Selection in the workbench has been changed. We 
	 * can change the state of the 'real' action here
	 * if we want, but this can only happen after 
	 * the delegate has been created.
	 * @see IWorkbenchWindowActionDelegate#selectionChanged
	 */
	public void selectionChanged(IAction action, ISelection selection) {
	}

	/**
	 * We can use this method to dispose of any system
	 * resources we previously allocated.
	 * @see IWorkbenchWindowActionDelegate#dispose
	 */
	public void dispose() {
	}

	/**
	 * We will cache window object in order to
	 * be able to provide parent shell for the message dialog.
	 * @see IWorkbenchWindowActionDelegate#init
	 */
	public void init(IWorkbenchWindow window) {
		this.window = window;
	}
}