/*******************************************************************************
* Copyright (c) 2006 IONA Technologies PLC
* 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:
*     IONA Technologies PLC - initial API and implementation
*******************************************************************************/
package org.eclipes.stp.soas.deploy.runtime.cxf.internal.simplefrontend;

import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import org.eclipes.stp.soas.deploy.runtime.cxf.CxfRuntimePlugin;
import org.eclipse.core.filesystem.URIUtil;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeHierarchy;
import org.eclipse.stp.common.logging.LoggingProxy;
import org.eclipse.stp.sc.common.internal.model.RuntimeCore;
import org.eclipse.stp.sc.common.utils.JDTUtils;
import org.eclipse.stp.sc.jaxws.ScJaxWsResources;
import org.eclipse.stp.sc.jaxws.deploy.DeployException;
import org.eclipse.stp.sc.jaxws.properties.ScJaxWsPropertyConstants;
import org.eclipse.stp.sc.jaxws.utils.PackageHelper;
import org.eclipse.stp.sc.jaxws.utils.ScJDTUtils;
import org.eclipse.stp.sc.jaxws.workspace.JaxWsWorkspaceManager;
import org.eclipse.stp.soas.deploy.core.IServiceDescriptor;
import org.eclipse.stp.soas.deploy.core.IPackageConfiguration;
import org.eclipse.stp.soas.deploy.core.IPackageConstructor;
import org.eclipse.stp.soas.deploy.core.IPackageCreationContext;
import org.eclipse.stp.soas.deploy.core.IPackageOutputDescriptor;
import org.eclipse.stp.soas.deploy.core.IServerType;
import org.eclipse.stp.soas.deploy.core.utils.DeploymentUtil;
import org.eclipse.stp.soas.deploy.tomcat.WarPackageOutputDescriptor;

public class SimplePackageConstructor implements IPackageConstructor {
	private static final LoggingProxy LOG = LoggingProxy.getlogger(SimplePackageConstructor.class);
	private static String WAR_FILE_EXTENSION = ".war";
	private IProject project;
	private PackageHelper pkgHelper;
	
	public List<IPackageOutputDescriptor> createPackage(IServiceDescriptor pkg,
			IPackageCreationContext context, IPackageConfiguration configuration)
			throws CoreException {		
		
		    IFile tempFile = pkg.getFile();
		    project = tempFile.getProject();
		    File outputFolder = context.getOutputFolder();
		    try {
	        	
	             // copy web.xml file
		    	IContainer container = JaxWsWorkspaceManager.getWSDLFolder(project);
		    	IFile webXmlFile = ScJDTUtils.getFileFromContainer(container, "web.xml");

	            if (!webXmlFile.exists()) {
	            	IPath path = RuntimeCore.getInstallPath(project);
	                
	                String webXmlFilePath = path.toOSString() + File.separator + "etc" + File.separator + "web.xml";
	                LOG.debug("web.xml file to copy:" + webXmlFilePath);
	                JaxWsWorkspaceManager.copyFile(webXmlFilePath,
	                                          webXmlFile,
	                                          JaxWsWorkspaceManager.COPY_NO_OVERWRITE,
	                                          new NullProgressMonitor());
	            }
	            

	            LOG.debug("generating cxf_servlet.xml...");
	            generateServletConf(project); 

	            project.refreshLocal(IProject.DEPTH_INFINITE, null);
	             
	            LOG.debug("generating war file");
	            pkgHelper = new PackageHelper(project.getFile(project.getName() + ".wsdl"), WAR_FILE_EXTENSION);			
				
				//IFolder folder = ResourcesPlugin.getWorkspace().getRoot().getFolder(URIUtil.toPath(outputFolder.toURI()));
	            IFile file = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(URIUtil.toPath(outputFolder.toURI()));
				IFolder folder = (IFolder)tempFile.getProject().getFolder(file.getProjectRelativePath());
				pkgHelper.startToPackage((IFolder)folder);				
				//pkgHelper.addFileToPackage(wsdlFile, PackageHelper.WSDL_DIR);
				pkgHelper.stopPackage();
	            //generateWarFile(wsdlFile);
				
	            project.refreshLocal(IProject.DEPTH_INFINITE, null); 
	            
	            if (context.getTarget() == null) {
	            	return null;
	            }
	            
	            IServerType ist = DeploymentUtil.convertWTPServerTypeToSTPServerType(context.getTarget().getServerType());
	            ArrayList<IPackageOutputDescriptor> rtnValue = new ArrayList<IPackageOutputDescriptor>();
	            rtnValue.add(new WarPackageOutputDescriptor(pkgHelper.getPackageFile(),
						pkg.getTechnologyType(), ist, pkgHelper
						.getPackageFile().getPath(), pkgHelper.getPackageFile()
						.getName()));
	            return rtnValue;
	            
	        } catch (Exception e) {
	            LOG.error("deploy error", e);
				LOG.error("create package error", e);			
				throw new CoreException(new Status(Status.ERROR, CxfRuntimePlugin.PLUGIN_ID, 0, 
						ScJaxWsResources
						.getString("error.deploy.assemble"), e)); 
	        }
			
	}
	 
	
    /**
     * genereate Celtix servlet configuration files for wsdl model
     * @param project, the project
     * @param wsdlFile, the wsdl file to generate config
     * @throws CoreException
     */
    private void generateServletConf(IProject proj)
        throws DeployException {
        try {
            List<SimpleWebDeployDescriptor> descList = new LinkedList<SimpleWebDeployDescriptor>();
            
            descList.add(generateEndpointConf(proj));

            IFile configFile = JaxWsWorkspaceManager.getServletConfigFile(proj);
//            IFile configFile = proj.getFolder(SimpleLogicalPackage.WSDL_FOLDER_STUB).getFile(JaxWsWorkspaceManager.SERVLET_CONFIG_FILENAME);
            writeServletConfig(configFile.getRawLocation().toOSString(), descList);
        } catch (CoreException coreE) {
            LOG.error(coreE);
            throw new DeployException("Error during generate servlet config:" + coreE.toString(), coreE);
        }
    }

    /**
     * generate endpoint configuration for one service in celtix-servlet.xml
     * @param project, the celtix project
     * @param service, the service to geneate configure
     * @throws CoreException
     */
    private SimpleWebDeployDescriptor generateEndpointConf(IProject proj)
        throws CoreException {
    	SimpleWebDeployDescriptor desc = new SimpleWebDeployDescriptor();
    	
    	desc.setEndpointName(proj.getName());
    	desc.setPattern(proj.getName());
    	
    	//get service class name and impl class name
    	String interfaceName = "";
    	String implName = "";
    	String startPoint = proj.getPersistentProperty(ScJaxWsPropertyConstants.PROPERTY_KEY_STARTING_POINT);
    	IFile startPointFile = proj.getFile(startPoint);
    	ICompilationUnit icu = JDTUtils.getJavaUnitFromFile(startPointFile);
    	IType type = icu.findPrimaryType();
    	if(type.isInterface()){
    		interfaceName = type.getFullyQualifiedName();
    		implName = interfaceName + "PortTypeImpl";
    	}else{
    		implName = type.getFullyQualifiedName();
    		String[] interfaceNames = type.getSuperInterfaceNames();
    		if(interfaceNames != null && interfaceNames.length == 1){
        		ITypeHierarchy hi= type.newSupertypeHierarchy(null);
    			interfaceName = hi.getSuperInterfaces(type)[0].getFullyQualifiedName();
    		}else{
    			interfaceName = null;
    		}
    	}
    	desc.setImplClsName(implName);
    	desc.setServiceClsName(interfaceName);

        LOG.debug("------- endponit cfg ------");
        LOG.debug(desc.toString());
        LOG.debug("------- endponit cfg ------");

        return desc;
    }

    /**
     * write servlet config file to file system
     * @param fileName, the output file name
     * @throws DeployException
     */
    private void writeServletConfig(String fileName,
        List<SimpleWebDeployDescriptor> descList) throws DeployException {
        try {
            FileOutputStream fos = new FileOutputStream(fileName, false);
            PrintStream ps = new PrintStream(fos);
            ps.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
            ps.println("<beans xmlns=\"http://www.springframework.org/schema/beans\"");            
            ps.println("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");
            ps.println("xmlns:simple=\"http://cxf.apache.org/simple\"");
            ps.println("xmlns:soap=\"http://cxf.apache.org/bindings/soap\"");
            ps.println("xsi:schemaLocation=\"");
            ps.println("http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd");
            ps.println("http://cxf.apache.org/bindings/soap http://cxf.apache.org/schemas/configuration/soap.xsd");
            ps.println("http://cxf.apache.org/simple http://cxf.apache.org/schemas/simple.xsd\">");
            ps.println("\n");
            for (SimpleWebDeployDescriptor desc : descList) {
                desc.serizlize(fos);
            }
            ps.println("</beans>");
            ps.close();
        } catch (Exception e) {
            LOG.error(e);
            throw new DeployException("Error during write cxf-servlet.xml file",
                e);
        }
    }
		
}
