package net.sourceforge.phpeclipse.builder;

import java.util.Map;

import net.sourceforge.phpdt.internal.ui.util.PHPFileUtil;
import net.sourceforge.phpeclipse.PHPeclipsePlugin;
import net.sourceforge.phpeclipse.phpeditor.PHPParserAction;
import net.sourceforge.phpeclipse.resourcesview.PHPProject;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;

/**
 * Builder for .php files. 
 * 
 * 
 * @see org.eclipse.core.resources.IncrementalProjectBuilder
 * @see org.eclipse.core.resources.IResourceDelta
 */
public class ParserBuilder extends IncrementalProjectBuilder {
  private final static int TOTAL_WORK = 100;

  /**
   * Constructor
   */
  public ParserBuilder() {
  }

  /**
   * 
   */
  protected IProject[] build(int kind, Map args, IProgressMonitor monitor) throws CoreException {
    monitor.beginTask("Parsing files", TOTAL_WORK);

    if (kind == IncrementalProjectBuilder.FULL_BUILD) {
      IResourceDelta delta = getDelta(getProject());

      processFull(getProject(), monitor);

    } else { // INCREMENTAL_BUILD or AUTO_BUILD

      IResourceDelta delta = getDelta(getProject());
      if (delta != null) {
        delta.accept(new ParserVisitor(getProject(), monitor));
      }

    }
    monitor.done();
    return null;
  }

  /**
   * Performs a <code>FULL_BUILD</code> by visiting all nodes in the resource
   * tree under the specified project.  
   * 
   * @param iProject
   */
  public void processFull(final IProject iProject, final IProgressMonitor monitor) {
		final IdentifierIndexManager indexManager = PHPeclipsePlugin.getDefault().getIndexManager(iProject);
    // Create resource visitor logic
    IResourceVisitor myVisitor = new IResourceVisitor() {
      public boolean visit(IResource resource) throws CoreException {
        if (resource.getType() == IResource.FILE) {
          if (monitor.isCanceled()) {
            throw new OperationCanceledException();
          }
          if ((resource.getFileExtension() != null) && PHPFileUtil.isPHPFile((IFile) resource)) {
            monitor.worked(1);
            monitor.subTask("Parsing: " + resource.getFullPath());
            // check for parsing errors
            PHPParserAction.parseFile((IFile) resource);
            // update indexfile for the project:
            PHPProject nature = (PHPProject) iProject.getNature(PHPeclipsePlugin.PHP_NATURE_ID);
						indexManager.addFile((IFile) resource);
          }
        }

        return true;
      }
    };

    // Process the project using the visitor just created
    try {

//      if (iProject.hasNature(PHPeclipsePlugin.PHP_NATURE_ID)) {
//        thePHPProject = new PHPProject();
//        thePHPProject.setProject(iProject);
//      }
			indexManager.initialize();
      iProject.accept(myVisitor);
			indexManager.writeFile();
    } catch (CoreException e) {
      e.printStackTrace();
    }

  }

  /** 
   * Sets initialization data for this builder.
   * <p>
   * This method is part of the <code>IExecutableExtension</code>
   * interface.
   * </p>
   * <p>
   * Subclasses are free to extend this method to pick up 
   * initialization parameters from the plug-in plug-in manifest 
   * (<code>plugin.xml</code>) file,
   * but should be sure to invoke this method on their superclass.
   * <p>
   * For example, the following method looks for a boolean-valued 
   * parameter named "trace":
   * <pre>
   *     public void setInitializationData(IConfigurationElement cfig, 
   *             String propertyName, Object data) 
   * 		        throws CoreException {
   *         super.setInitializationData(cfig, propertyName, data);
   *         if (data instanceof Hashtable) { 
   *             Hashtable args = (Hashtable) data; 
   *             String traceValue = (String) args.get("trace"); 
   *             TRACING = (traceValue!=null && traceValue.equals("true"));
   *         }
   *     }
   * </pre>
   * </p>
   */
  public void setInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException {
    super.setInitializationData(config, propertyName, data);

  }

  /**
   * Informs this builder that it is being started by the build management
   * infrastructure.  By the time this method is run, the builder's project
   * is available and <code>setInitializationData</code> has been called.
   * The default implementation should be called by all overriding methods.
   *
   * @see #setInitializationData
   */
  protected void startupOnInitialize() {
    //   traceMsg("Parse Builder Initialize - startupOnInitialize()");
  }

  /**
  * Write trace statements.  
  * System.out.println with prefix tagging used for simplicity.
  */
  //  private void traceMsg(String msg) {
  //    if (PHPeclipsePlugin.DEBUG | traceEnabled)
  //      System.out.println(
  //        buildMode
  //          + "<"
  //          + getProject()
  //          + "> "
  //          + "\t\t\t"
  //          + buildMark
  //          + msg);
  //  }
}