/**********************************************************************
 * Copyright (c) 2005, 2010 IBM Corporation.
 * 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:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/

package org.eclipse.ptp.pldt.common.analysis;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

import org.eclipse.cdt.core.dom.IName;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression;
import org.eclipse.cdt.core.dom.ast.IASTMacroExpansion;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTNodeLocation;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition;
import org.eclipse.cdt.core.dom.ast.IASTStatement;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.c.CASTVisitor;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.dialogs.MessageDialogWithToggle;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.ptp.pldt.common.Artifact;
import org.eclipse.ptp.pldt.common.CommonPlugin;
import org.eclipse.ptp.pldt.common.ScanReturn;
import org.eclipse.ptp.pldt.common.messages.Messages;
import org.eclipse.ptp.pldt.common.util.SourceInfo;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;

/**
 * This dom-walker helper collects interesting constructs (currently
 * function calls and constants), and adds markers to the source file for
 * C/C++ code. <br>
 * This base class encapsulates the common behaviors for both C and C++
 * code and for visitors looking for MPI, OpenMP, LAPI, etc. etc. types of artifacts
 * 
 * @author Beth Tibbitts
 * @since 4.0
 * 
 */
public class PldtAstVisitor extends CASTVisitor {


	/**
	 * @since 4.0
	 */
	public static String ARTIFACT_CALL = "Artifact Call"; //$NON-NLS-1$
	/**
	 * @since 4.0
	 */
	public static String ARTIFACT_CONSTANT = "Artifact Constant"; //$NON-NLS-1$
	protected static String ARTIFACT_NAME = "Artifact Name"; //$NON-NLS-1$
	protected static String PREFIX = ""; //$NON-NLS-1$
	private static /*final*/ boolean traceOn=false;
	
	private static boolean dontAskToModifyIncludePathAgain=false;
	protected boolean allowPrefixOnlyMatch=false;

	/**
	 * List of include paths that we'll probably want to consider in the work that this visitor does.
	 * For example, only paths found in this list (specified in PLDT preferences) would be considered
	 * to be a path from which definitions of "Artifacts" would be found.
	 * <br>
	 * Note that this can now be dynamically modified during artifact analysis, thus no longer final
	 */
	private /*final*/ List<String> includes_;
	private final String fileName;
	private final ScanReturn scanReturn;

	/**
	 * 
	 * @param includes
	 *            list of include paths that we'll probably want to consider in
	 *            the work that this visitor does
	 * @param fileName
	 *            the name of the file that this visitor is visiting(?)
	 * @param prefixOnlyMatch
	 *            if true, then artifact is recognized if it starts with the plugin-specific prefix
	 *            (e.g. "MPI_"  etc.) instead of forcing a lookup of the location of the header file
	 *            in which the API is found.  This proves to be difficult for users to get right, so prefix-only
	 *            recognition of artifacts is allowed here.
	 * @param scanReturn
	 *            the ScanReturn object to which the artifacts that we find will
	 *            be appended.

	 */
	public PldtAstVisitor(List<String> includes, String fileName, boolean prefixOnlyMatch, ScanReturn scanReturn ) {
		this.includes_ = includes;
		this.fileName = fileName;
		this.scanReturn = scanReturn;
		dontAskToModifyIncludePathAgain=false;
		this.allowPrefixOnlyMatch=prefixOnlyMatch;
		if(!traceOn) traceOn=CommonPlugin.getTraceOn();
		if(traceOn)System.out.println("PldtAstVisitor, traceOn="+traceOn); //$NON-NLS-1$
	}
	/**
	 * Constructor without prefixOnlyMatch arg, assumes false
	 */
	public PldtAstVisitor(List<String> includes, String fileName, ScanReturn scanReturn) {
		this(includes, fileName, false, scanReturn);
	}


	/**
	 * Skip statements that are included.
	 */
	public int visit(IASTStatement statement) { 
		if (preprocessorIncluded(statement)) {
			return ASTVisitor.PROCESS_SKIP;
		}
		return ASTVisitor.PROCESS_CONTINUE; 
	}

	/**
	 * Skip decls that are included.
	 * 
	 * @param declaration
	 * @return
	 */
	public int visit(IASTDeclaration declaration) {//called; both paths get taken
		if (preprocessorIncluded(declaration)) {
			return ASTVisitor.PROCESS_SKIP;
		}
		return ASTVisitor.PROCESS_CONTINUE;
	}

	/**
	 * Process a function name from an expression and determine if it should be
	 * marked as an Artifact. If so, append it to the scanReturn object that
	 * this visitor is populating.
	 * 
	 * An artifact is a function name that was found in the MPI include path,
	 * as defined in the MPI preferences.
	 * 
	 * @param astExpr
	 * @param funcName
	 */
	public void processFuncName(IASTName funcName, IASTExpression astExpr) {
		//IASTTranslationUnit tu = funcName.getTranslationUnit();
		String strName=funcName.toString();
		if ((this.allowPrefixOnlyMatch&&matchesPrefix(strName)) || isArtifact(funcName)) { // brt C++ test 2/16/10
			SourceInfo sourceInfo = getSourceInfo(astExpr, Artifact.FUNCTION_CALL);
			if (sourceInfo != null) {
				if(traceOn) System.out.println("found artifact: " + funcName.toString()); //$NON-NLS-1$
				// Note: we're determining the artifact name twice. (also in chooseName())
				String artName=funcName.toString();
				String rawName=funcName.getRawSignature();
				//String bName=funcName.getBinding().getName();
				if(!artName.equals(rawName)) {
					if(rawName.length()==0)rawName="  "; //$NON-NLS-1$
					artName=artName+"  ("+rawName+")"; // indicate orig pre-pre-processor value in parens //$NON-NLS-1$ //$NON-NLS-2$
					// note: currently rawName seems to always be empty.
				}
					scanReturn.addArtifact(new Artifact(fileName, sourceInfo
							.getStartingLine(), 1, artName, sourceInfo));
				 
			}
		}
	}

	/**
	 * 
	 * @param astExpr
	 */
	public void processExprWithConstant(IASTExpression astExpr) {
		IASTName funcName = ((IASTIdExpression) astExpr).getName();
		//IASTTranslationUnit tu = funcName.getTranslationUnit();
		String strName=funcName.toString();
		if ((this.allowPrefixOnlyMatch&& matchesPrefix(strName)) || isArtifact(funcName)) {
			SourceInfo sourceInfo = getSourceInfo(astExpr, Artifact.FUNCTION_CALL);
			if (sourceInfo != null) {
				//System.out.println("found MPI artifact: " + funcName.toString());
				scanReturn.addArtifact(new Artifact(fileName, sourceInfo.getStartingLine(), 1,
						funcName.toString(), sourceInfo));
			}
		}
	}

	/**
	 * Determines if the funcName is an instance of the type of artifact in
	 * which we are interested. <br>
	 * An artifact is a function name that was found in the  include path (e.g. MPI or OpenMP),
	 * as defined in the PLDT preferences.
	 * 
	 * @param funcName
	 */
	protected boolean isArtifact(IASTName funcName) {
		IBinding binding = funcName.resolveBinding();
		String name = binding.getName();
		String rawSig = funcName.getRawSignature();
		name = chooseName(name, rawSig);

		IASTTranslationUnit tu = funcName.getTranslationUnit();

		// Use index instead of full AST for the header file inclusion stuff
		// Without full AST, further introspection into APIs will need to
		// explicitly ask for it from the Index
		IName[] names = tu.getDeclarations(binding); // get from the index not ast of e.g. header files
		for (int i = 0; i < names.length; i++) {
			IName name2 = names[i];
			IASTFileLocation floc = name2.getFileLocation();
			if (floc == null) {
				if (traceOn)
					System.out.println("PldtAstVisitor  IASTFileLocn null for "+ name2 + " (" + funcName + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				return false; // (e.g. 'ptr' )
			}
			String filename = floc.getFileName();
			IPath path = new Path(filename);
			if (isInIncludePath(path)) {
				// System.out.println("    found "+path+"  in artifact path (via index)!");
				return true;
			} else {
				if (traceOn) {
					System.out.println(name+ " was found in "+ path+ " but  PLDT preferences have been set to only include: "+ includes_.toString()); //$NON-NLS-1$ //$NON-NLS-2$
				}
				// add them here?
				if (allowIncludePathAdd()) {
					boolean addit = addIncludePath(path, name,dontAskToModifyIncludePathAgain);
					if (addit)
						return true;
				}
			}
		}
		return false;
	}
	
	/**
	 * Choose how to distinguish between binding name, and raw signature.<br>
	 * Could be overridden by subclasses if, for example, a name with a prefix e.g. "MPI::foo" should be preferred over "foo".<br>
	 * Here, the default case is that we always choose the regular/binding name, unless it's empty, in which case we choose the rawSignature.
	 * @param bindingName
	 * @param rawSignature
	 * @return
	 */
	protected String chooseName(String bindingName, String rawSignature){
		String name=bindingName;
		if(bindingName.length()==0) {
			name=rawSignature;
		}
		return name;
	}
 
	public void processMacroLiteral(IASTLiteralExpression expression) {
		IASTNodeLocation[] locations = expression.getNodeLocations();
		if ((locations.length == 1) && (locations[0] instanceof IASTMacroExpansion)) {//path taken &not
			// found a macro, does it come from the include path required to be "one of ours"?
			IASTMacroExpansion astMacroExpansion = (IASTMacroExpansion) locations[0];
			IASTPreprocessorMacroDefinition preprocessorMacroDefinition = astMacroExpansion
					.getMacroDefinition();
			// String shortName =
			// preprocessorMacroDefinition.getName().toString()+'='+literal;
			String shortName = preprocessorMacroDefinition.getName().toString();
			IASTNodeLocation[] preprocessorLocations = preprocessorMacroDefinition
					.getNodeLocations();
			while ((preprocessorLocations.length == 1)
					&& (preprocessorLocations[0] instanceof IASTMacroExpansion)) {
				preprocessorLocations = ((IASTMacroExpansion) preprocessorLocations[0])
						.getMacroDefinition().getNodeLocations();
			}

			if ((preprocessorLocations.length == 1)
					&& isInIncludePath(new Path(preprocessorLocations[0].asFileLocation()
							.getFileName()))) {
				SourceInfo sourceInfo = getSourceInfo(astMacroExpansion);
				if (sourceInfo != null) {
					scanReturn.addArtifact(new Artifact(fileName, sourceInfo.getStartingLine(), 1, // column:
							shortName, sourceInfo));
				}

			}
		}
	}

	/**
	 * Is this path found in the include path in which we are interested?
	 * E.g. is it in the  include path specified in PLDT preferences,
	 * which would identify it as an  artifact of interest?
	 * 
	 * @param includeFilePath under consideration
	 * @return true if this is found in the include path from PLDT preferences
	 */
	private boolean isInIncludePath(IPath includeFilePath) {
		if (includeFilePath == null)
			return false;
		for (String includeDir : includes_) {
			IPath includePath = new Path(includeDir);
			if(traceOn)System.out.println("PldtAstVisitor: is "+includeFilePath+" found in "+includeDir+"?"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			if (includePath.isPrefixOf(includeFilePath))
				return true;
		}
		return false;
	}

	/**
	 * Get exact source location info for a function call
	 * 
	 * @param astExpr
	 * @param constructType
	 * @return
	 */
	private SourceInfo getSourceInfo(IASTExpression astExpr, int constructType) {
		SourceInfo sourceInfo = null;
		IASTNodeLocation[] locations = astExpr.getNodeLocations();
		if (locations.length == 1) {
			IASTFileLocation astFileLocation = null;
			if (locations[0] instanceof IASTFileLocation) {
				astFileLocation = (IASTFileLocation) locations[0];
			}
			// handle the case e.g. #define foo MPI_fn - recognize foo() as MPI_fn()
			else if (locations[0] instanceof IASTMacroExpansion) {
				IASTMacroExpansion me=(IASTMacroExpansion)locations[0];
				astFileLocation=me.asFileLocation();
			}
			if(astFileLocation!=null) {
				sourceInfo = new SourceInfo();
				sourceInfo.setStartingLine(astFileLocation.getStartingLineNumber());
				sourceInfo.setStart(astFileLocation.getNodeOffset());
				sourceInfo.setEnd(astFileLocation.getNodeOffset() + astFileLocation.getNodeLength());
				sourceInfo.setConstructType(constructType);			
			}
		}
		return sourceInfo;
	}

	/**
	 * Get exact source location info for a constant originated from Macro
	 * expansion(s)
	 * 
	 * @param iASTMacroExpansion
	 *            represents the original macro
	 * @return
	 */
	private SourceInfo getSourceInfo(IASTMacroExpansion iASTMacroExpansion) {
		SourceInfo sourceInfo = null;
		IASTFileLocation iASTFileLocation = iASTMacroExpansion.asFileLocation();
		sourceInfo = new SourceInfo();
		sourceInfo.setStartingLine(iASTFileLocation.getStartingLineNumber());
		sourceInfo.setStart(iASTFileLocation.getNodeOffset());
		sourceInfo.setEnd(iASTFileLocation.getNodeOffset() + iASTFileLocation.getNodeLength());
		sourceInfo.setConstructType(Artifact.CONSTANT);

		return sourceInfo;
	}
	
	private boolean preprocessorIncluded(IASTNode astNode) {
		if (astNode.getFileLocation() == null)
			return false;
		String location = astNode.getFileLocation().getFileName();
		String tuFilePath = astNode.getTranslationUnit().getFilePath();
		return !location.equals(tuFilePath);
	}

	public void processIdExprAsLiteral(IASTIdExpression expression) {
		IASTName name = expression.getName();
		String strName=name.toString();
		if ((this.allowPrefixOnlyMatch&& matchesPrefix(strName)) || isArtifact(name)) {// brt C++ test 2/16/10
			SourceInfo sourceInfo = getSourceInfo(expression, Artifact.CONSTANT);
			if (sourceInfo != null) {
				scanReturn.addArtifact(new Artifact(fileName, sourceInfo.getStartingLine(), 1, // column:
						name.toString(), sourceInfo));
			}
		}
	}

	/**
	 * allow dynamic adding to include path?  Can be overridden by derived classes.
	 * @return
	 */
	public boolean allowIncludePathAdd() {
		return !dontAskToModifyIncludePathAgain;
	}
	/**
	 * Replace the includes list in this visitor so the change will be recognized.
	 * @param includes
	 */
	@SuppressWarnings("unchecked")
  protected void replaceIncludes(String includes) {
		includes_=convertToList(includes);
	}
    @SuppressWarnings({ "unchecked"})
	public List convertToList(String stringList)
    {
        StringTokenizer st = new StringTokenizer(stringList, File.pathSeparator + "\n\r");//$NON-NLS-1$
        List dirs = new ArrayList();
        while (st.hasMoreElements()) {
            dirs.add(st.nextToken());
        }
        return dirs;
    }
	/** 
	 * Add an include path to the prefs - probably found dynamically during analysis
	 * and requested to be added by the user
	 * <br>
	 * Note that the path will be to the actual file in which the name was found;
	 * the path that will be added to the prefs is the parent directory of that file.
	 * @param path
	 * @param name the name (function etc) that was found in the path
	 * @param dontAskAgain  initial value of toggle "don't ask again"
	 * 
	 * @returns whether the user chose to add the path or not
	 */
	public boolean addIncludePath( IPath path,  String name/*, IPreferenceStore store, String id*/, boolean dontAskAgain) {

		IPreferenceStore store=getPreferenceStore();
		String id=getIncludesPrefID();
		String type=getTypeName();
		boolean doitThisTime=false;
		
		if(store==null || id == null) {
			CommonPlugin.log(IStatus.ERROR, "PLDT: Visitor subclass does not implement getPreferenceStore() or "+ //$NON-NLS-1$
					"getIncludesPrefID() to return non-null values."); //$NON-NLS-1$
			return false;
		}
		
		try {
		 String value = store.getString(id);
		if(traceOn)System.out.println("value: "+value); //$NON-NLS-1$
		
		if (!dontAskAgain) {
        // probably inefficient string construction, but rarely called.
        String msg = Messages.PldtAstVisitor_20
            + name
            + Messages.PldtAstVisitor_21
            + path.toString()
            + Messages.PldtAstVisitor_22
            + type
            + Messages.PldtAstVisitor_23
            + value
            + Messages.PldtAstVisitor_24;
        String title = Messages.PldtAstVisitor_25 + type + Messages.PldtAstVisitor_26;
        boolean[] twoAnswers = askUI(title, msg, dontAskToModifyIncludePathAgain);
        doitThisTime = twoAnswers[0];
        dontAskAgain = twoAnswers[1];
        dontAskToModifyIncludePathAgain = dontAskAgain;
      }

      if (doitThisTime) {
        String s = java.io.File.pathSeparator;
        String parent = path.toFile().getParent();
        // add path separator (: or ; ?) if necessary
        if (!value.endsWith(s)) {
          value += s;
        }
        // add this new include path location to the value stored in
        // preferences, and add it to the value within this class as well.
        value += parent + s;
        store.putValue(id, value);
        replaceIncludes(value);
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
		return doitThisTime;
	}

	/**
	 * needs to be overrridden for derived classes that need to dynamically update the pref store 
	 * e.g. for the includes path.  This type name is used for messages, etc.
	 * @return artifact type name such as "MPI", "OpenMP" etc.
	 */	
	protected String getTypeName() {
		return ""; //$NON-NLS-1$
	}

	/**
	 * needs to be overrridden for derived classes that need to dynamically update the pref store 
	 * e.g. for the includes path
	 * @return
	 */
	protected String getIncludesPrefID() {
		return null;
	}
	/**
	 * needs to be overrridden for derived classes that need to dynamically update the pref store 
	 * e.g. for the includes path
	 * @return
	 */
	protected IPreferenceStore getPreferenceStore() {
		return null;
	}


	/**
	 * Dialog to ask a question in the UI thread
	 * @author beth
	 *
	 */	
	public boolean[] askUI(final String title, final String message, boolean dontAskAgain) {
	  boolean[] twoAnswers = new boolean[2];
		RunGetAnswer runner = new RunGetAnswer(title,message,dontAskAgain);
		
		Display.getDefault().syncExec(runner);
		boolean answer=runner.getAnswer();
		dontAskAgain=runner.getDontAskAgain();
		twoAnswers[0]=answer;
		twoAnswers[1]=dontAskAgain;
		return twoAnswers;
	}
	/**
	 * Runnable used by askUI to ask a question in the UI thread
	 * @author beth
	 *
	 */
	  class RunGetAnswer implements Runnable {
	    boolean answer, dontAskAgain;
	    String title, message;

	    RunGetAnswer(String title, String message, boolean initialToggleState) {
	      this.title = title;
	      this.message = message;
	      this.dontAskAgain=initialToggleState;
	    }

	    public void run() {
	      IWorkbench wb = PlatformUI.getWorkbench();
	      IWorkbenchWindow w = wb.getActiveWorkbenchWindow();
	      Shell shell = w.getShell();
	      if (shell == null) {
	        Display display = CommonPlugin.getStandardDisplay();
	        shell = display.getActiveShell();
	      }
	      
	      // see also: openYesNoCancelQuestion
	      String toggleMessage=Messages.PldtAstVisitor_28;
	      IPreferenceStore store = null;
	      String key = null;
	      MessageDialogWithToggle md;
	      md=MessageDialogWithToggle.openYesNoQuestion(shell, title, message, toggleMessage, dontAskAgain, store, key);
	      int retCode=md.getReturnCode();  // yes=2
	      answer = (retCode==2);
	      dontAskAgain= md.getToggleState();  
	    }

	    public boolean getAnswer() {
	      return answer;
	    }
	    public boolean getDontAskAgain() {
	      return dontAskAgain;
	    }
	  }

	/**
	 * will be overridden where needed; note that for C code, the test for if
	 * the prefix matches has already been done before this is called so this
	 * test isn't necessary. FIXME improve this convoluted logic
	 * 
	 * @param name
	 * @return
	 * @since 4.0
	 */
	  public boolean matchesPrefix(String name) {
		  return true;
	  }

}