/*******************************************************************************
 * Copyright (c) 2003, 2004 IBM Corporation and others.
 * 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.jst.ws.internal.axis.consumption.ui.task;


import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IPluginDescriptor;
import org.eclipse.core.runtime.IPluginRegistry;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jst.ws.internal.axis.consumption.core.common.JavaWSDLParameter;
import org.eclipse.jst.ws.internal.axis.consumption.ui.plugin.WebServiceAxisConsumptionUIPlugin;
import org.eclipse.jst.ws.internal.common.J2EEUtils;
import org.eclipse.wst.command.internal.env.ui.eclipse.EclipseProgressMonitor;
import org.eclipse.wst.command.internal.provisional.env.core.SimpleCommand;
import org.eclipse.wst.command.internal.provisional.env.core.common.Environment;
import org.eclipse.wst.command.internal.provisional.env.core.common.MessageUtils;
import org.eclipse.wst.command.internal.provisional.env.core.common.ProgressMonitor;
import org.eclipse.wst.command.internal.provisional.env.core.common.SimpleStatus;
import org.eclipse.wst.command.internal.provisional.env.core.common.Status;
import org.eclipse.wst.command.internal.provisional.env.core.common.StatusException;
import org.eclipse.wst.common.componentcore.ComponentCore;
import org.eclipse.wst.common.componentcore.resources.IVirtualComponent;
import org.eclipse.wst.common.componentcore.resources.IVirtualFolder;
import org.eclipse.wst.common.componentcore.resources.IVirtualResource;

public class AddJarsToProjectBuildPathTask extends SimpleCommand {

	private String DESCRIPTION = "TASK_DESC_JARS_TO_PROJECT";
	private String LABEL = "TASK_LABEL_JARS_TO_PROJECT";

	private IJavaProject javaProject_;
	private IClasspathEntry[] oldClasspath_;
	private IClasspathEntry[] newClasspath_;
	private JavaWSDLParameter javaWSDLParam_;
	private boolean isJ2EE_13 = true;
	private MessageUtils msgUtils_;
	
	private IProject project;
	private String module_;

	public AddJarsToProjectBuildPathTask()
	  {
			String pluginId = "org.eclipse.jst.ws.axis.consumption.ui";
			msgUtils_ = new MessageUtils(pluginId + ".plugin", this);
			setDescription(msgUtils_.getMessage(DESCRIPTION));
			setName(msgUtils_.getMessage(LABEL));
			module_ = J2EEUtils.getFirstWebModuleName(project);
		}
	
	public AddJarsToProjectBuildPathTask(String module)
  {
		String pluginId = "org.eclipse.jst.ws.axis.consumption.ui";
		msgUtils_ = new MessageUtils(pluginId + ".plugin", this);
		setDescription(msgUtils_.getMessage(DESCRIPTION));
		setName(msgUtils_.getMessage(LABEL));
		module_ = module;
	}

	/**
	* Execute AddJarsToProjectBuildPathTask
	*/
	public Status execute(Environment env) {
//		try {
//			if (project.hasNature(IWebNatureConstants.J2EE_NATURE_ID)) {
//				J2EEWebNatureRuntime webNatureRuntime =
//					(J2EEWebNatureRuntime) project.getNature(
//						IWebNatureConstants.J2EE_NATURE_ID);
//				isJ2EE_13 = webNatureRuntime.isJ2EE1_3();
//			}
//		} catch (Exception e) {
//		}
//    Status status = new SimpleStatus("");
//		if (!isJ2EE_13)
//		{
//		//	AddJar(project, null, "XERCES_API_JAR", status, environment);
//		}
//		return status;
		
		Status status = new SimpleStatus("");
//		 TODO: workaround for 90515 
		//
		   // Get the current classpath.
		   //
		   javaProject_ = null;
		   oldClasspath_ = null;
		   try
		   {    
			 javaProject_ = JavaCore.create(project);    
			 if (javaProject_ != null)
			 {
			   oldClasspath_ = javaProject_.getRawClasspath();
			 }
			 else
			 {
			   status = new SimpleStatus("", msgUtils_.getMessage("MSG_WARN_NO_JAVA_NATURE"), Status.ERROR);	
			   env.getStatusHandler().reportError(status);
			   return status;
			 }
		   }
		   catch (JavaModelException e)
		   {
			   status = new SimpleStatus("", msgUtils_.getMessage("MSG_WARN_NO_JAVA_NATURE"), Status.ERROR);
			   env.getStatusHandler().reportError(status);
			   return status;	   	
		   }


			try {
				
				ArrayList aList = new ArrayList();
				String classpathEntry = null;
				IVirtualComponent component = ComponentCore.createComponent(project, module_);
				if (component != null) {
					
					IVirtualFolder webInfLib = component.getFolder(new Path(
							"/WEB-INF/lib"));
					if (webInfLib != null) {
						IVirtualResource[] resources = webInfLib.members();
						IResource aResource = null;
						
						for (int i = 0; i < resources.length; i++) {
							aResource = resources[i].getUnderlyingResource();
							classpathEntry = aResource.getLocation().toString();
							if (!FoundClasspathEntry(classpathEntry)) {
								aList.add(classpathEntry);
							}
						}
					}
				}
				
				int newListSize = aList.size();
				
				if (newListSize == 0) {
					return status;
				}
				
				// Update classpath
				newClasspath_ = new IClasspathEntry[oldClasspath_.length + newListSize];
				Iterator iter = aList.iterator();
		
				int j=0;
				while (iter.hasNext()) {
					newClasspath_[j] = JavaCore.newLibraryEntry(new Path((String)iter.next()), null, null);
					j++;
				}
				for (int i=0; i<oldClasspath_.length; i++) {
					newClasspath_[j+i] = oldClasspath_[i];
				}
 
			   	 ProgressMonitor monitor = env.getProgressMonitor();
			   	 IProgressMonitor eclipseMonitor = null;
			   	 if (monitor instanceof EclipseProgressMonitor)
			   	 {
			   	 	eclipseMonitor = ((EclipseProgressMonitor)monitor).getMonitor();
			   	 }
				 javaProject_.setRawClasspath(newClasspath_,eclipseMonitor);
			}
			   catch (JavaModelException e)
			   {
				 status = new SimpleStatus("", msgUtils_.getMessage("MSG_ERROR_BAD_BUILDPATH"), Status.WARNING, e);
				 try
				 {
				 	env.getStatusHandler().report(status);	
				 }
				 catch(StatusException se)
				 {
				 	status = new SimpleStatus("", "User aborted", Status.ERROR);
				 }
			   }
			 catch (CoreException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
//			 end of workaround
			return status;
		}  
		   

		private boolean FoundClasspathEntry(String classpathEntry)  {
			   

			   boolean found = false;
			   for (int i=0; i<oldClasspath_.length && !found; i++)
			   {
				 if (oldClasspath_[i].getPath().toString().toLowerCase().equals(classpathEntry.toLowerCase())) {
					 found=true;
				 }
			   }
		   	 return found;
		}

	private void AddJar(IProject webProject, String pluginId, String jarName, Status status, Environment env)  {
	   //
	   // Get the current classpath.
	   //
	   javaProject_ = null;
	   oldClasspath_ = null;
	   try
	   {    
		 javaProject_ = JavaCore.create(webProject);    
		 if (javaProject_ != null)
		 {
		   oldClasspath_ = javaProject_.getRawClasspath();
		 }
		 else
		 {
		   status = new SimpleStatus("", msgUtils_.getMessage("MSG_WARN_NO_JAVA_NATURE"), Status.ERROR);	
		   env.getStatusHandler().reportError(status);
		   return;
		 }
	   }
	   catch (JavaModelException e)
	   {
		   status = new SimpleStatus("", msgUtils_.getMessage("MSG_WARN_NO_JAVA_NATURE"), Status.ERROR);
		   env.getStatusHandler().reportError(status);
		   return;	   	
	   }

	   boolean found = false;
	   for (int i=0; i<oldClasspath_.length; i++)
	   {
		 found = found || oldClasspath_[i].getPath().toString().toLowerCase().endsWith(jarName.toLowerCase());
	   }

	   if (found) 
	   {
		 return;
	   }

	   newClasspath_ = new IClasspathEntry[oldClasspath_.length + 1];
	   int i=0;
	   while (i<oldClasspath_.length)
	   {
		 newClasspath_[i] = oldClasspath_[i];
		 i++;
	   }

	   try
	   {
		 if(pluginId!=null)
		 {
		   newClasspath_[i++] = JavaCore.newLibraryEntry(getTheJarPath(pluginId,jarName), null, null);
		 }
		 else
		 {
		   newClasspath_[i++] = JavaCore.newVariableEntry(getTheJarPath(pluginId,jarName), null, null);
		 }
	   }
	   catch (CoreException e)
	   {
		 status = new SimpleStatus("", msgUtils_.getMessage("MSG_ERROR_BAD_BUILDPATH"), Status.WARNING, e);
		 try
		 {
		 	env.getStatusHandler().report(status);
		 }
		 catch(StatusException se)
		 {
		 	status = new SimpleStatus("","User aborted",Status.ERROR);
		 }
		 return;
	   }

	   //
	   // Then update the project classpath.
	   //
	   try
	   {
	   	 ProgressMonitor monitor = env.getProgressMonitor();
	   	 IProgressMonitor eclipseMonitor = null;
	   	 if (monitor instanceof EclipseProgressMonitor)
	   	 {
	   	 	eclipseMonitor = ((EclipseProgressMonitor)monitor).getMonitor();
	   	 }
		 javaProject_.setRawClasspath(newClasspath_,eclipseMonitor);
	   }
	   catch (JavaModelException e)
	   {
		 status = new SimpleStatus("", msgUtils_.getMessage("MSG_ERROR_BAD_BUILDPATH"), Status.WARNING, e);
		 try
		 {
		 	env.getStatusHandler().report(status);	
		 }
		 catch(StatusException se)
		 {
		 	status = new SimpleStatus("", "User aborted", Status.ERROR);
		 }
		 return;
	   }
	 }

	//
	// Returns the local native pathname of the jar.
	//
	private IPath getTheJarPath(String pluginId, String theJar)
		throws CoreException {
		try {
			if (pluginId != null) {
				IPluginRegistry pluginRegistry = Platform.getPluginRegistry();
				IPluginDescriptor pluginDescriptor =
					pluginRegistry.getPluginDescriptor(pluginId);
				URL localURL =
					Platform.asLocalURL(
						new URL(pluginDescriptor.getInstallURL(), theJar));
				return new Path(localURL.getFile());
			} else {
				return new Path(theJar);
			}
		} catch (MalformedURLException e) {
			throw new CoreException(
				new org.eclipse.core.runtime.Status(
					IStatus.WARNING,
					WebServiceAxisConsumptionUIPlugin.ID,
					0,
					msgUtils_.getMessage("MSG_BAD_AXIS_JAR_URL"),
					e));
		} catch (IOException e) {
			throw new CoreException(
				new org.eclipse.core.runtime.Status(
					IStatus.WARNING,
					WebServiceAxisConsumptionUIPlugin.ID,
					0,
					msgUtils_.getMessage("MSG_BAD_AXIS_JAR_URL"),
					e));
		}
	}

	public void setProject(IProject project)
	{
	  this.project = project;
	}
}
