/*******************************************************************************
 * Copyright (c) 2005 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.consumption.command.common;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.jem.util.emf.workbench.ProjectUtilities;
import org.eclipse.jst.j2ee.application.internal.operations.FlexibleJavaProjectCreationDataModelProvider;
import org.eclipse.jst.j2ee.internal.J2EEVersionConstants;
import org.eclipse.jst.j2ee.project.datamodel.properties.IFlexibleJavaProjectCreationDataModelProperties;
import org.eclipse.jst.server.core.FacetUtil;
import org.eclipse.jst.ws.internal.common.J2EEUtils;
import org.eclipse.jst.ws.internal.common.ServerUtils;
import org.eclipse.jst.ws.internal.consumption.ConsumptionMessages;
import org.eclipse.jst.ws.internal.consumption.common.FacetUtils;
import org.eclipse.osgi.util.NLS;
import org.eclipse.wst.command.internal.env.core.common.StatusUtils;
import org.eclipse.wst.common.componentcore.internal.util.IModuleConstants;
import org.eclipse.wst.common.environment.IEnvironment;
import org.eclipse.wst.common.frameworks.datamodel.AbstractDataModelOperation;
import org.eclipse.wst.common.frameworks.datamodel.DataModelFactory;
import org.eclipse.wst.common.frameworks.datamodel.IDataModel;
import org.eclipse.wst.common.frameworks.datamodel.IDataModelOperation;
import org.eclipse.wst.common.project.facet.core.IFacetedProject;
import org.eclipse.wst.common.project.facet.core.IFacetedProjectTemplate;
import org.eclipse.wst.common.project.facet.core.IProjectFacet;
import org.eclipse.wst.common.project.facet.core.IProjectFacetVersion;
import org.eclipse.wst.common.project.facet.core.ProjectFacetsManager;
import org.eclipse.wst.common.project.facet.core.VersionFormatException;
import org.eclipse.wst.server.core.IRuntime;
import org.eclipse.wst.server.core.IServer;
import org.eclipse.wst.server.core.IServerType;
import org.eclipse.wst.server.core.ServerCore;

public class CreateModuleCommand extends AbstractDataModelOperation
{
	
	public final static int WEB = J2EEUtils.WEB;    
	public final static int EJB = J2EEUtils.EJB;    
	public final static int APPCLIENT = J2EEUtils.APPCLIENT;
	public final static int EAR = J2EEUtils.EAR;
    
    //Templates
    //TODO  Remove these template constants once J2EE tools defines constants (bug 117531)
    public final static String WEB_TEMPLATE = "template.jst.web";
    public final static String EJB_TEMPLATE = "template.jst.ejb";
    public final static String APPCLIENT_TEMPLATE = "template.jst.appclient";
    public final static String EAR_TEMPLATE = "template.jst.ear";
	
	private String   projectName;
	private String   moduleName;  // may be null for non-flexible project
	private int      moduleType;;
	private String   j2eeLevel;
	private String   serverFactoryId;
	private String   serverInstanceId_;
	private IEnvironment env;
    private IProgressMonitor monitor_;
	
    private org.eclipse.wst.common.project.facet.core.runtime.IRuntime facetRuntime;
    
	public CreateModuleCommand(){
	}
	
  public IStatus execute( IProgressMonitor monitor, IAdaptable adaptable )
  {
    monitor_ = monitor;
		this.env = getEnvironment();
		IStatus status = Status.OK_STATUS;
		
		// check if data ready
		status = checkDataReady();
		if (status.getSeverity()==Status.ERROR){
			return status;
		}	

        //ensure the project does not exist
        IProject project = ProjectUtilities.getProject(projectName);
        if (!project.exists())
        {
          // create the component according to the component type specified
          int type = getModuleType();
          switch (type) {
          case WEB:
            status = createWebComponent();
            break;
          case EJB:
             status = createEJBComponent();
            break;
          case APPCLIENT:
            status = createAppClientComponent();
            break;
          case EAR:
            status = createEARComponent();
            break;

          default:
            return StatusUtils.errorStatus( NLS.bind(ConsumptionMessages.MSG_ERROR_COMPONENT_CREATION, new String[]{moduleName}) );         
          }          
        }
		
        
        // check if flexible project exists
        /*
		if (project==null || !project.exists()){
			status = createFlexibleJavaProject();
			if (status.getSeverity()==Status.ERROR){
				return status;
			}			
		}
        */
        /*
		// check if project and/or component exists
        if (projectName!=null) {
          if (moduleName==null){
            if (project.exists())
              return status;
          }
          else {
			if (J2EEUtils.exists(projectName, moduleName))
				return status;
          }
        }
		else {
			return StatusUtils.errorStatus(NLS.bind(ConsumptionMessages.MSG_ERROR_COMPONENT_CREATION, new String[]{projectName, moduleName}) );
		} 
        */       
        

		
	
		return status;
	}

	private IStatus checkDataReady(){
		
		if (projectName==null || serverFactoryId==null){
			return StatusUtils.errorStatus( NLS.bind(ConsumptionMessages.MSG_ERROR_COMPONENT_CREATION, new String[]{projectName, moduleName}) );
		}
		
		return Status.OK_STATUS;
	}
	
	
	/**
	 * Create a Web component
	 * @return
	 */
	public IStatus createWebComponent(){   
    
      IStatus status = Status.OK_STATUS;      
      
      try
      {
        IFacetedProject fproject = ProjectFacetsManager.create(projectName, null, monitor_);

        //Decide which facets to install based on the templateId and the selected server. 
        Set facetsToAdd = getFacetsToAdd(WEB_TEMPLATE); 
        Set facetsToAddModified = facetsToAdd;
        //If the J2EE level has been set, modify the Web facet version to be consistent.
        if (j2eeLevel!=null && j2eeLevel.length()>0)
        {
          String webVersion = getWebVersionFromJ2EELevel(j2eeLevel);
          facetsToAddModified = new HashSet();
          Iterator itr = facetsToAdd.iterator();
          while (itr.hasNext())
          {
            //If this is the web facet, get the right version.
            IProjectFacetVersion pfv = (IProjectFacetVersion)itr.next();
            IProjectFacet pf = pfv.getProjectFacet(); 
            if (pf.getId().equals(IModuleConstants.JST_WEB_MODULE))
            {
              IProjectFacetVersion webfv = pf.getVersion(webVersion);
              facetsToAddModified.add(webfv);
            }
            else
            {
              facetsToAddModified.add(pfv); 
            }
          }
        }
        
        //Set up the install actions.
        Set actions = FacetUtils.getInstallActions(facetsToAddModified);
        fproject.modify(actions, monitor_);
        
        Set newFacetVersions = fproject.getProjectFacets();
        Set fixedFacets = new HashSet();
        for (Iterator iter = newFacetVersions.iterator(); iter.hasNext();) {
            IProjectFacetVersion facetVersion = (IProjectFacetVersion) iter.next();
            fixedFacets.add(facetVersion.getProjectFacet());
        }
        fproject.setFixedProjectFacets(fixedFacets);
        
        
        //Set the runtime        
        if (facetRuntime != null)
        {
          fproject.setRuntime(facetRuntime, monitor_);
        }        
        
      } catch (CoreException ce)
      {
        System.out.println("Exception occurred when creating a faceted project.");
        return StatusUtils.errorStatus(NLS.bind(ConsumptionMessages.MSG_ERROR_PROJECT_CREATION, new String[] { projectName }), ce);
      }
		return status;
      		
	}
	
	/**
	 * Create an EAR component
	 * @return
	 */
	public IStatus createEARComponent(){
      IStatus status = Status.OK_STATUS;      
      
      try
      {
        IFacetedProject fproject = ProjectFacetsManager.create(projectName, null, monitor_);

        //Decide which facets to install based on the templateId and the selected server. 
        Set facetsToAdd = getFacetsToAdd(EAR_TEMPLATE); 
        Set facetsToAddModified = facetsToAdd;
        //If the J2EE level has been set, modify the Web facet version to be consistent.
        if (j2eeLevel!=null && j2eeLevel.length()>0)
        {
          String webVersion = getEARVersionFromJ2EELevel(j2eeLevel);
          facetsToAddModified = new HashSet();
          Iterator itr = facetsToAdd.iterator();
          while (itr.hasNext())
          {
            //If this is the ear facet, get the right version.
            IProjectFacetVersion pfv = (IProjectFacetVersion)itr.next();
            IProjectFacet pf = pfv.getProjectFacet(); 
            if (pf.getId().equals(IModuleConstants.JST_EAR_MODULE))
            {
              IProjectFacetVersion webfv = pf.getVersion(webVersion);
              facetsToAddModified.add(webfv);
            }
            else
            {
              facetsToAddModified.add(pfv); 
            }
          }
        }
        
        //Set up the install actions.
        Set actions = FacetUtils.getInstallActions(facetsToAddModified);
        fproject.modify(actions, monitor_);
        
        Set newFacetVersions = fproject.getProjectFacets();
        Set fixedFacets = new HashSet();
        for (Iterator iter = newFacetVersions.iterator(); iter.hasNext();) {
            IProjectFacetVersion facetVersion = (IProjectFacetVersion) iter.next();
            fixedFacets.add(facetVersion.getProjectFacet());
        }
        fproject.setFixedProjectFacets(fixedFacets);
        
        
        //Set the runtime        
        if (facetRuntime != null)
        {
          fproject.setRuntime(facetRuntime, monitor_);
        }        
        
      } catch (CoreException ce)
      {
        System.out.println("Exception occurred when creating a faceted project.");
        return StatusUtils.errorStatus(NLS.bind(ConsumptionMessages.MSG_ERROR_PROJECT_CREATION, new String[] { projectName }), ce);
      }
        return status;
	}
	
	/**
	 * Create an EJB Component
	 * @return
	 */
	public IStatus createEJBComponent(){
      IStatus status = Status.OK_STATUS;      
      
      try
      {
        IFacetedProject fproject = ProjectFacetsManager.create(projectName, null, monitor_);

        //Decide which facets to install based on the templateId and the selected server. 
        Set facetsToAdd = getFacetsToAdd(EJB_TEMPLATE); 
        Set facetsToAddModified = facetsToAdd;
        //If the J2EE level has been set, modify the Web facet version to be consistent.
        if (j2eeLevel!=null && j2eeLevel.length()>0)
        {
          String webVersion = getEJBVersionFromJ2EELevel(j2eeLevel);
          facetsToAddModified = new HashSet();
          Iterator itr = facetsToAdd.iterator();
          while (itr.hasNext())
          {
            //If this is the web facet, get the right version.
            IProjectFacetVersion pfv = (IProjectFacetVersion)itr.next();
            IProjectFacet pf = pfv.getProjectFacet(); 
            if (pf.getId().equals(IModuleConstants.JST_EJB_MODULE))
            {
              IProjectFacetVersion webfv = pf.getVersion(webVersion);
              facetsToAddModified.add(webfv);
            }
            else
            {
              facetsToAddModified.add(pfv); 
            }
          }
        }
        
        //Set up the install actions.
        Set actions = FacetUtils.getInstallActions(facetsToAddModified);
        fproject.modify(actions, monitor_);
        
        Set newFacetVersions = fproject.getProjectFacets();
        Set fixedFacets = new HashSet();
        for (Iterator iter = newFacetVersions.iterator(); iter.hasNext();) {
            IProjectFacetVersion facetVersion = (IProjectFacetVersion) iter.next();
            fixedFacets.add(facetVersion.getProjectFacet());
        }
        fproject.setFixedProjectFacets(fixedFacets);
        
        
        //Set the runtime        
        if (facetRuntime != null)
        {
          fproject.setRuntime(facetRuntime, monitor_);
        }        
        
      } catch (CoreException ce)
      {
        System.out.println("Exception occurred when creating a faceted project.");
        return StatusUtils.errorStatus(NLS.bind(ConsumptionMessages.MSG_ERROR_CREATE_EJB_COMPONENT, new String[] { projectName }), ce);
      }
        return status;      

	}
	
	/**
	 * Create an Application Client component
	 * @return
	 */
	public IStatus createAppClientComponent()
    {
      IStatus status = Status.OK_STATUS;      
      
      try
      {
        IFacetedProject fproject = ProjectFacetsManager.create(projectName, null, monitor_);

        //Decide which facets to install based on the templateId and the selected server. 
        Set facetsToAdd = getFacetsToAdd(APPCLIENT_TEMPLATE); 
        Set facetsToAddModified = facetsToAdd;
        //If the J2EE level has been set, modify the Web facet version to be consistent.
        if (j2eeLevel!=null && j2eeLevel.length()>0)
        {
          String webVersion = getAppClientVersionFromJ2EELevel(j2eeLevel);
          facetsToAddModified = new HashSet();
          Iterator itr = facetsToAdd.iterator();
          while (itr.hasNext())
          {
            //If this is the web facet, get the right version.
            IProjectFacetVersion pfv = (IProjectFacetVersion)itr.next();
            IProjectFacet pf = pfv.getProjectFacet(); 
            if (pf.getId().equals(IModuleConstants.JST_APPCLIENT_MODULE))
            {
              IProjectFacetVersion webfv = pf.getVersion(webVersion);
              facetsToAddModified.add(webfv);
            }
            else
            {
              facetsToAddModified.add(pfv); 
            }
          }
        }
        
        //Set up the install actions.
        Set actions = FacetUtils.getInstallActions(facetsToAddModified);
        fproject.modify(actions, monitor_);
        
        Set newFacetVersions = fproject.getProjectFacets();
        Set fixedFacets = new HashSet();
        for (Iterator iter = newFacetVersions.iterator(); iter.hasNext();) {
            IProjectFacetVersion facetVersion = (IProjectFacetVersion) iter.next();
            fixedFacets.add(facetVersion.getProjectFacet());
        }
        fproject.setFixedProjectFacets(fixedFacets);
        
        
        //Set the runtime        
        if (facetRuntime != null)
        {
          fproject.setRuntime(facetRuntime, monitor_);
        }        
        
      } catch (CoreException ce)
      {
        System.out.println("Exception occurred when creating a faceted project.");
        return StatusUtils.errorStatus(NLS.bind(ConsumptionMessages.MSG_ERROR_CREATE_APPCLIENT_COMPONENT, new String[] { projectName }), ce);
      }
        return status;      
      
        /*
		IStatus status = Status.OK_STATUS;
        
		try
		{
		  IDataModel projectInfo = DataModelFactory.createDataModel(new AppClientComponentCreationDataModelProvider());
		  projectInfo.setProperty(IAppClientComponentCreationDataModelProperties.PROJECT_NAME,projectName);
          if (moduleName!=null)      
		      projectInfo.setProperty(IAppClientComponentCreationDataModelProperties.COMPONENT_NAME, moduleName);
		  if (j2eeLevel!=null)		  
			  projectInfo.setProperty(IAppClientComponentCreationDataModelProperties.COMPONENT_VERSION, Integer.valueOf(j2eeLevel));
		  
		  //Don't create an EAR. The ADD_TO_EAR property gets defaulted to TRUE for everything except Web projects.
		  projectInfo.setProperty(IAppClientComponentCreationDataModelProperties.ADD_TO_EAR, Boolean.FALSE);
		  
		  IDataModelOperation op = projectInfo.getDefaultOperation();

			op.execute( monitor_, null);
		}
		catch (Exception e)
		{
			status = StatusUtils.errorStatus( NLS.bind(ConsumptionMessages.MSG_ERROR_CREATE_APPCLIENT_COMPONENT, new String[]{projectName}), e);
		}
        
		return status;
        */		
	}
	
	/**
	 * Creates Flexible Java Project structure
	 * This project is required if it doesn't already exist in order to create the component 
	 * @return
	 * 
	 * Note: This call may not be necessary once J2EE implements creating a flex project automatically
	 * 		with the creation of components.
	 */
	public IStatus createFlexibleJavaProject(){
		IStatus status = Status.OK_STATUS;
		try
		{
		  IDataModel projectInfo = DataModelFactory.createDataModel(new FlexibleJavaProjectCreationDataModelProvider());
		  projectInfo.setProperty(IFlexibleJavaProjectCreationDataModelProperties.PROJECT_NAME,projectName);
  
		  String runtimeTargetId = null;
		  if( serverInstanceId_ == null )
		  {
			// We don't have a server instance so we will get the first runtimeTarget from the factory ID.
			runtimeTargetId = ServerUtils.getServerTargetIdFromFactoryId(serverFactoryId, ServerUtils.getServerTargetModuleType(moduleType), j2eeLevel);		
		  }
		  else
		  {
			// We have a server instance so we will just get it's runtimeTargetId.
			IServer server = ServerCore.findServer( serverInstanceId_ );
			runtimeTargetId = server.getRuntime().getId();  
		  }
		  
		  projectInfo.setProperty(IFlexibleJavaProjectCreationDataModelProperties.RUNTIME_TARGET_ID,runtimeTargetId);
		  projectInfo.setProperty(IFlexibleJavaProjectCreationDataModelProperties.ADD_SERVER_TARGET,Boolean.TRUE);
		  IDataModelOperation op = projectInfo.getDefaultOperation();
		  if (env!=null)
			  op.execute( monitor_, null);
		  else 
			  op.execute(new NullProgressMonitor(), null);

		}
		catch (Exception e)
		{
			status = StatusUtils.errorStatus( NLS.bind(ConsumptionMessages.MSG_ERROR_CREATE_FLEX_PROJET, new String[]{projectName}), e);
		}
		return status;		
	}
    
      /*
       * @return Set Returns the Set of facets to add to the new project, 
       * choosing the highest level of each facet that works on the selected server.
       */
      private Set getFacetsToAdd(String templateId)
      {
        Set facets = new HashSet();
        
        //Set the facet runtime.
        setFacetRuntime();
        if (facetRuntime != null)
        {
          IFacetedProjectTemplate template = ProjectFacetsManager.getTemplate(templateId);
          Set templateFacets = template.getFixedProjectFacets();
          Iterator templateFacetsItr = templateFacets.iterator();
          while (templateFacetsItr.hasNext())
          {
            IProjectFacet fixedFacet = (IProjectFacet)templateFacetsItr.next();
            List versions = null;
            try {
                versions = fixedFacet.getSortedVersions(false);
            } catch (VersionFormatException e) {
                Set versionSet = fixedFacet.getVersions();
                Iterator itr = versionSet.iterator();
                versions = new ArrayList();
                while (itr.hasNext())
                {
                    versions.add(itr.next());
                }            
            } catch (CoreException e) {
                Set versionSet = fixedFacet.getVersions();
                Iterator itr = versionSet.iterator();
                versions = new ArrayList();
                while (itr.hasNext())
                {
                    versions.add(itr.next());
                }            
            } 
            Iterator versionsItr = versions.iterator();
            while(versionsItr.hasNext())
            {
              IProjectFacetVersion pfv = (IProjectFacetVersion)versionsItr.next();
              Set pfvs = new HashSet();
              pfvs.add(pfv);           
              
              //Check against Runtime
              if (FacetUtils.doesRuntimeSupportFacets(facetRuntime, pfvs))
              {
                  //We have a match. Add this one to the master set.
                  facets.add(pfv);
                  break;
              }                        
            }
          }
        }
        else
        {
          facets = FacetUtils.getInitialFacetVersionsFromTemplate(templateId);
        }
     
        
        return facets;
      }
      
      private void setFacetRuntime()
      {
        
        if (serverInstanceId_ != null && serverInstanceId_.length()>0)
        {
          IServer server = ServerCore.findServer(serverInstanceId_);
          IRuntime sRuntime = server.getRuntime();
          facetRuntime = FacetUtil.getRuntime(sRuntime);      
        }
        else
        {
          IServerType st = ServerCore.findServerType(serverFactoryId);
          String runtimeTypeId = st.getRuntimeType().getId();   
          //Find the facet runtime
          IRuntime[] runtimes = ServerCore.getRuntimes();
          for (int i=0; i<runtimes.length; i++)
          {
            IRuntime sRuntime = runtimes[i];
            if ( !sRuntime.isStub() && sRuntime.getRuntimeType().getId().equals(runtimeTypeId))
            {
              facetRuntime = FacetUtil.getRuntime(sRuntime);
            }
          }
        }
      }      
    
   private String getWebVersionFromJ2EELevel(String j2eeVersion)
   {
        int aVersion = Integer.valueOf(j2eeLevel).intValue();
        switch (aVersion) {
        case J2EEVersionConstants.J2EE_1_2_ID:
            return "2.2";

        case J2EEVersionConstants.J2EE_1_3_ID:
            return "2.3";

        case J2EEVersionConstants.J2EE_1_4_ID:
            return "2.4";
            
        default:
            return "2.4";
        }                
   }
	
   private String getEJBVersionFromJ2EELevel(String j2eeVersion)
   {
        int aVersion = Integer.valueOf(j2eeLevel).intValue();
        switch (aVersion) {
        case J2EEVersionConstants.J2EE_1_2_ID:
            return "1.1";

        case J2EEVersionConstants.J2EE_1_3_ID:
            return "2.0";

        case J2EEVersionConstants.J2EE_1_4_ID:
            return "2.1";
            
        default:
            return "2.1";
        }                
   }
   
   private String getAppClientVersionFromJ2EELevel(String j2eeVersion)
   {
        int aVersion = Integer.valueOf(j2eeLevel).intValue();
        switch (aVersion) {
        case J2EEVersionConstants.J2EE_1_2_ID:
            return "1.2";

        case J2EEVersionConstants.J2EE_1_3_ID:
            return "1.3";

        case J2EEVersionConstants.J2EE_1_4_ID:
            return "1.4";
            
        default:
            return "1.4";
        }                
   }
   
   private String getEARVersionFromJ2EELevel(String j2eeVersion)
   {
        int aVersion = Integer.valueOf(j2eeLevel).intValue();
        switch (aVersion) {
        case J2EEVersionConstants.J2EE_1_2_ID:
            return "1.2";

        case J2EEVersionConstants.J2EE_1_3_ID:
            return "1.3";

        case J2EEVersionConstants.J2EE_1_4_ID:
            return "1.4";
            
        default:
            return "1.4";
        }                
   }
   
	public void setModuleName(String moduleName)
	{
		this.moduleName = moduleName;
	}	

	public int getModuleType()
	{
		return moduleType;
	}

	public void setModuleType(int moduleType)
	{
		this.moduleType = moduleType;
	}

	public void setProjectName(String projectName)
	{
		this.projectName = projectName;
	}

	/**
	 * Expecting 12,13,14 etc.
	 * @param level
	 */
	public void setJ2eeLevel(String level)
	{
		if (level !=null && level.indexOf(".")!=-1)
			j2eeLevel = J2EEUtils.getJ2EEIntVersionAsString(level);
		else
			j2eeLevel = level;
	}

	public void setServerFactoryId(String serverFactoryId)
	{
		this.serverFactoryId = serverFactoryId;
	}
	
	public void setServerInstanceId( String serverInstanceId )
	{
	  serverInstanceId_ = serverInstanceId;
	}

}
