/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.netbeans.modules.web.project.jaxws;

import java.io.IOException;
import java.io.OutputStream;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.netbeans.api.j2ee.core.Profile;
import org.netbeans.api.java.classpath.ClassPath;
import org.netbeans.api.java.project.classpath.ProjectClassPathModifier;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.SourceGroup;
import org.netbeans.api.project.libraries.Library;
import org.netbeans.api.project.libraries.LibraryManager;
import org.netbeans.api.project.ui.OpenProjects;
import org.netbeans.modules.j2ee.common.dd.DDHelper;
import org.netbeans.modules.j2ee.core.api.support.SourceGroups;
import org.netbeans.modules.j2ee.dd.api.common.NameAlreadyUsedException;
import org.netbeans.modules.j2ee.dd.api.web.DDProvider;
import org.netbeans.modules.j2ee.dd.api.web.Listener;
import org.netbeans.modules.j2ee.dd.api.web.Servlet;
import org.netbeans.modules.j2ee.dd.api.web.ServletMapping;
import org.netbeans.modules.j2ee.dd.api.web.WebApp;
import org.netbeans.modules.j2ee.dd.api.webservices.WebservicesMetadata;
import org.netbeans.modules.j2ee.deployment.devmodules.api.Deployment;
import org.netbeans.modules.j2ee.deployment.devmodules.api.J2eePlatform;
import org.netbeans.modules.j2ee.metadata.model.api.MetadataModel;
import org.netbeans.modules.web.api.webmodule.WebModule;
import org.netbeans.modules.web.project.WebProject;
import org.netbeans.modules.web.project.WebProjectWebServicesSupport;
import org.netbeans.modules.websvc.api.jaxws.project.LogUtils;
import org.netbeans.modules.websvc.api.jaxws.project.WSUtils;
import org.netbeans.modules.websvc.api.jaxws.project.config.Endpoint;
import org.netbeans.modules.websvc.api.jaxws.project.config.Endpoints;
import org.netbeans.modules.websvc.api.jaxws.project.config.EndpointsProvider;
import org.netbeans.modules.websvc.api.jaxws.project.config.JaxWsModel;
import org.netbeans.modules.websvc.api.jaxws.project.config.Service;
import org.netbeans.modules.websvc.jaxws.api.JAXWSSupport;
import org.netbeans.modules.websvc.jaxws.spi.ProjectJAXWSSupport;
import org.netbeans.spi.project.support.ant.AntProjectHelper;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.filesystems.FileLock;
import org.openide.filesystems.FileObject;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle;

/**
 *
 * @author mkuchtiak
 */
public class WebProjectJAXWSSupport extends ProjectJAXWSSupport /*implements JAXWSSupportImpl*/ {
    private WebProject project;
    //servlet name and servlet listener for non-JSR 109 web services
    private static final String servletClassName = "com.sun.xml.ws.transport.http.servlet.WSServlet"; //NOI18N
    private static final String servletListener = "com.sun.xml.ws.transport.http.servlet.WSServletContextListener"; //NOI18N

    /** Creates a new instance of JAXWSSupport */
    public WebProjectJAXWSSupport(WebProject project, AntProjectHelper antProjectHelper) {
        super(project,antProjectHelper);
        this.project = project;
    }

    @Override
    public FileObject getWsdlFolder(boolean create) throws java.io.IOException {
        WebModule webModule = WebModule.getWebModule(project.getProjectDirectory());
        if (webModule!=null) {
            FileObject webInfFo = webModule.getWebInf();
            if (webInfFo!=null) {
                FileObject wsdlFo = webInfFo.getFileObject("wsdl"); //NOI18N
                if (wsdlFo!=null) return wsdlFo;
                else if (create) {
                    return webInfFo.createFolder("wsdl"); //NOI18N
                }
            }
        }
        return null;
    }

    /** Get wsdlLocation information
     * Useful for web service from wsdl
     * @param name service "display" name
     */
    @Override
    public String getWsdlLocation(String serviceName) {
        String localWsdl = serviceName+".wsdl"; //NOI18N
        JaxWsModel jaxWsModel = (JaxWsModel)project.getLookup().lookup(JaxWsModel.class);
        if (jaxWsModel!=null) {
            Service service = jaxWsModel.findServiceByName(serviceName);
            if (service!=null) {
                String localWsdlFile = service.getLocalWsdlFile();
                if (localWsdlFile!=null) localWsdl=localWsdlFile;
            }
        }
        String prefix = "WEB-INF/wsdl/"; //NOI18N
        return prefix+serviceName+"/"+localWsdl; //NOI18N
    }

    /**
     * This is to support non-JSR 109 containers. In this case, a regular jaxws web service
     * is created and the deployment descriptor is updated with the jaxws-ri servlet and
     * listener.
     */
    private void addServiceEntriesToDD(String serviceName) {
        //add servlet entry to web.xml
        String servletName = serviceName;

        WebApp webApp = getWebApp();
        if(webApp != null){
            Servlet servlet;
            try{
                servlet = (Servlet)webApp.addBean("Servlet", new String[]{"ServletName","ServletClass"},
                        new Object[]{servletName,servletClassName}, "ServletName");
                servlet.setLoadOnStartup(new java.math.BigInteger("1"));
                webApp.addBean("ServletMapping", new String[]{"ServletName","UrlPattern"},
                        new Object[]{servletName, "/" + serviceName}, "ServletName");

                if(!webAppHasListener(webApp, servletListener)){
                    webApp.addBean("Listener", new String[]{"ListenerClass"},
                            new Object[]{servletListener}, "ListenerClass");
                }
                // This also saves server specific configuration, if necessary.
                webApp.write(getDeploymentDescriptor());
            } catch (ClassNotFoundException exc) {
                Logger.getLogger("global").log(Level.INFO, exc.getLocalizedMessage());
            } catch (NameAlreadyUsedException exc) {
                Logger.getLogger("global").log(Level.INFO, exc.getLocalizedMessage());
            } catch (IOException exc) {
                Logger.getLogger("global").log(Level.INFO, exc.getLocalizedMessage());
            }
        }
    }

    @Override
    protected void addServletElement(Project project, String wsName, String serviceImpl) throws IOException {
        WebApp webApp = getWebApp();
        if(webApp != null) {
            boolean addServletEntry = false;
            JAXWSSupport wss = JAXWSSupport.getJAXWSSupport(project.getProjectDirectory());
            if (wss != null) {
                Map properties = wss.getAntProjectHelper().getStandardPropertyEvaluator().getProperties();
                if (properties != null) {
                    String serverInstance = (String)properties.get("j2ee.server.instance"); //NOI18N
                    if (serverInstance != null) {
                        J2eePlatform j2eePlatform = Deployment.getDefault().getJ2eePlatform(serverInstance);
                        if (j2eePlatform != null) {
                            if (j2eePlatform.isToolSupported("JaxWs-in-j2ee14-supported")) addServletEntry = true;
                        }
                    }
                }
            }
            if (addServletEntry) {
                try{
                    Servlet servlet = (Servlet)webApp.addBean("Servlet", new String[]{"ServletName","ServletClass"},
                            new Object[]{wsName,serviceImpl}, "ServletName");
                    servlet.setLoadOnStartup(new java.math.BigInteger("1"));
                    webApp.addBean("ServletMapping", new String[]{"ServletName","UrlPattern"},
                            new Object[]{wsName, "/" + wsName}, "UrlPattern");
                    // This also saves server specific configuration, if necessary.
                    webApp.write(getDeploymentDescriptor());
                } catch (ClassNotFoundException exc) {
                    Logger.getLogger("global").log(Level.INFO, exc.getLocalizedMessage());
                } catch (NameAlreadyUsedException exc) {
                    Logger.getLogger("global").log(Level.INFO, exc.getLocalizedMessage());
                }
            }
        }
    }
    /**
     * Remove the web.xml entries for the non-JSR 109 web service.
     *
     * @param serviceName Name of the web service to be removed
     */
    private void removeServiceEntriesFromDD(String serviceName) {
        WebApp webApp = getWebApp();
        if (webApp != null) {
            boolean changed = removeNonJsr109ServletsFromDD(webApp, serviceName);

            //determine if there are other web services in the project
            //if none, remove the listener
            boolean hasMoreWebServices = false;
            Servlet[] remainingServlets = webApp.getServlet();
            for(int i = 0; i < remainingServlets.length; i++){
                if(remainingServlets[i].getServletClass().equals(servletClassName)){
                    hasMoreWebServices = true;
                    break;
                }
            }
            if(!hasMoreWebServices){
                Listener[] listeners = webApp.getListener();
                for(int i = 0; i < listeners.length; i++){
                    Listener listener = listeners[i];
                    if(listener.getListenerClass().equals(servletListener)){
                        webApp.removeListener(listener);
                        changed = true;
                        break;
                    }
                }
            }
            if(changed){
                try{
                    webApp.write(getDeploymentDescriptor());
                } catch(IOException e){
                    Exceptions.printStackTrace(e);
                }
            }
        }
    }

    /**
     * Remove the web.xml servlets for the non-JSR 109 web service.
     *
     * @param serviceName Name of the web service to be removed
     */
    private boolean removeNonJsr109ServletsFromDD(WebApp webApp, String serviceName) {
        boolean changed = false;
        //first remove the servlet
        Servlet[] servlets = webApp.getServlet();
        for(int i = 0; i < servlets.length; i++){
            Servlet servlet = servlets[i];
            if(servlet.getServletName().equals(serviceName)){
                webApp.removeServlet(servlet);
                changed = true;
                break;
            }
        }
        //remove the servlet mapping
        ServletMapping[] mappings = webApp.getServletMapping();
        for(int i = 0; i < mappings.length; i++){
            ServletMapping mapping = mappings[i];
            if(mapping.getServletName().equals(serviceName)){
                webApp.removeServletMapping(mapping);
                changed = true;
            }
        }
        return changed;
    }

    private boolean webAppHasListener(WebApp webApp, String listenerClass){
        Listener[] listeners = webApp.getListener();
        for(int i = 0; i < listeners.length; i++){
            Listener listener = listeners[i];
            if(listenerClass.equals(listener.getListenerClass())){
                return true;
            }
        }
        return false;
    }
    /**
     * Returns the directory that contains the deployment descriptor in the project
     */
    @Override
    public FileObject getDeploymentDescriptorFolder() {
        WebModule webModule = WebModule.getWebModule(project.getProjectDirectory());
        if(webModule != null) {
            return webModule.getWebInf();
        }
        return null;
    }

    private WebApp getWebApp() {
        try {
            FileObject deploymentDescriptor = getDeploymentDescriptor();
            if(deploymentDescriptor != null) {
                return DDProvider.getDefault().getDDRoot(deploymentDescriptor);
            }
        } catch (java.io.IOException e) {
            Logger.getLogger("global").log(Level.INFO, e.getLocalizedMessage());
        }
        return null;
    }

    private boolean isProjectOpened() {
        // XXX workaround: OpenProjects.getDefault() can be null
        // when called from ProjectOpenedHook.projectOpened() upon IDE startup
        if (OpenProjects.getDefault() == null) {
            return true;
        }

        Project[] projects = OpenProjects.getDefault().getOpenProjects();
        for (int i = 0; i < projects.length; i++) {
            if (projects[i].equals(project)) {
                return true;
            }
        }
        return false;
    }

    private FileObject getDeploymentDescriptor() throws IOException {
        WebModule webModule = WebModule.getWebModule(project.getProjectDirectory());
        if (webModule != null) {
            FileObject ddFo = webModule.getDeploymentDescriptor();
            if (ddFo == null) {
                FileObject webInfFo = webModule.getWebInf();
                if (webInfFo != null) {
                    ddFo = DDHelper.createWebXml(webModule.getJ2eeProfile(), webInfFo);
                }
            }
            return ddFo;
        } else {
            DialogDisplayer.getDefault().notify(
                    new NotifyDescriptor.Message(NbBundle.getMessage(WebProjectWebServicesSupport.class,"MSG_WebInfCorrupted"), // NOI18N
                    NotifyDescriptor.ERROR_MESSAGE));
            return null;
        }
    }

    @Override
    protected void addJaxwsArtifacts(Project project, String wsName, String serviceImpl) throws Exception {

        // check if the wsimport class is already present - this means we don't need to add the library
        SourceGroup[] sgs = SourceGroups.getJavaSourceGroups(project);
        if (sgs.length > 0) {
            ClassPath classPath = ClassPath.getClassPath(sgs[0].getRootFolder(),ClassPath.COMPILE);
            if (classPath != null) {
                FileObject wsimportFO = classPath.findResource("com/sun/tools/ws/ant/WsImport.class"); // NOI18N

                if (wsimportFO == null) {
                    //Add the Metro library to the project to be packed with the archive
                    Library metroLib = LibraryManager.getDefault().getLibrary("metro"); //NOI18N
                    if (metroLib != null) {
                        try {
                            ProjectClassPathModifier.addLibraries(
                                    new Library[] {metroLib},
                                    sgs[0].getRootFolder(),
                                    ClassPath.COMPILE);
                        }catch(IOException e){
                            throw new Exception("Unable to add Metro library", e);
                        }
                    } else {
                        throw new Exception("Unable to add Metro Library"); //NOI18N
                    }
                }
            }
        }

        //Add the servlet and listener entry in web.xml
        addServiceEntriesToDD(wsName);

        //create the sun-jaxws deployment descriptor
        FileObject ddFolder = getDeploymentDescriptorFolder();
        if(ddFolder != null){
            FileObject sunjaxwsFile = ddFolder.getFileObject("sun-jaxws.xml");
            if(sunjaxwsFile == null){
                WSUtils.generateSunJaxwsFile(ddFolder);
            }

            sunjaxwsFile = ddFolder.getFileObject("sun-jaxws.xml");
            Endpoints endpoints = EndpointsProvider.getDefault().getEndpoints(sunjaxwsFile);
            Endpoint endpoint = endpoints.newEndpoint();
            endpoint.setEndpointName(wsName);
            endpoint.setImplementation(serviceImpl);
            endpoint.setUrlPattern("/" + wsName);
            endpoints.addEnpoint(endpoint);
            FileLock lock = null;
            OutputStream os = null;
            synchronized (this) {
                try{
                    lock = sunjaxwsFile.lock();
                    os = sunjaxwsFile.getOutputStream(lock);
                    endpoints.write(os);
                }finally{
                    if(lock != null) {
                        lock.releaseLock();
                    }

                    if(os != null) {
                        os.close();
                    }
                }
            }
        }else{
            String mes = NbBundle.getMessage(WebProjectJAXWSSupport.class, "MSG_CannotFindWEB-INF"); // NOI18N
            NotifyDescriptor desc = new NotifyDescriptor.Message(mes, NotifyDescriptor.Message.ERROR_MESSAGE);
            DialogDisplayer.getDefault().notify(desc);
        }
    }

    /** return root folder for xml artifacts
     */
    @Override
    protected FileObject getXmlArtifactsRoot() {
        return project.getWebModule().getConfDir();
    }

    /**
     * Notification when Service (created from java) is removed from jax-ws.xml
     * (JAXWSSupport needs to react when @WebService annotation is removed
     * or when impl.class is removed (manually from project)
     * Default implementation does nothing.
     */
    @Override
    public void serviceFromJavaRemoved(String serviceName) {
        JaxWsModel jaxWsModel = (JaxWsModel)project.getLookup().lookup(JaxWsModel.class);
        Boolean isJsr109 = jaxWsModel.getJsr109();
        if(isJsr109!=null && !isJsr109){
            try{
                removeNonJsr109Entries(serviceName);
            }catch(IOException e){
                Exceptions.printStackTrace(e);
            }
        } else {
            try{
                removeJsr109Entries(serviceName);
            }catch(IOException e){
                Exceptions.printStackTrace(e);
            }
        }

    }

    /**
     * Removes the servlet entry from web.xml and
     * the endpoint entry from the sun-jaxws.xml file
     */
    @Override
    public void removeNonJsr109Entries(String serviceName) throws IOException {
        //delete web.xml entry
        removeServiceEntriesFromDD(serviceName);
        //delete entry in sun-jaxws.xml file.
        FileObject ddFolder = getDeploymentDescriptorFolder();
        if(ddFolder != null){
            FileObject sunjaxwsFile = ddFolder.getFileObject("sun-jaxws.xml");
            if(sunjaxwsFile != null){
                FileLock lock = null;
                //if there are no more services, delete the file
                JaxWsModel jaxWsModel = (JaxWsModel)project.getLookup().lookup(JaxWsModel.class);
                if(jaxWsModel.getServices().length == 0) {
                    synchronized(this) {
                        try{
                            lock = sunjaxwsFile.lock();
                            sunjaxwsFile.delete(lock);
                        } finally{
                            if(lock != null){
                                lock.releaseLock();
                            }
                        }
                    }
                } else{
                    //remove the entry from the sunjaxwsFile
                    Endpoints endpoints = EndpointsProvider.getDefault().getEndpoints(sunjaxwsFile);
                    Endpoint endpoint = endpoints.findEndpointByName(serviceName);
                    if(endpoint != null){
                        endpoints.removeEndpoint(endpoint);
                        OutputStream os = null;
                        synchronized(this) {
                            try{
                                lock = sunjaxwsFile.lock();
                                os = sunjaxwsFile.getOutputStream(lock);
                                endpoints.write(os);
                            }finally{
                                if(lock != null){
                                    lock.releaseLock();
                                }
                                if(os != null){
                                    os.close();
                                }
                            }
                        }
                    }
                }
            }
        }else{
            String mes = NbBundle.getMessage(WebProjectJAXWSSupport.class, "MSG_CannotFindDDDirectory"); // NOI18N
            NotifyDescriptor desc = new NotifyDescriptor.Message(mes, NotifyDescriptor.Message.ERROR_MESSAGE);
            DialogDisplayer.getDefault().notify(desc);
        }

        //TODO if no more web services, remove the jaxws21 library
    }

    /**
     * Removes the servlet entry from web.xml and
     * the endpoint entry from the sun-jaxws.xml file
     */
    public void removeJsr109Entries(String serviceName) throws IOException {
        WebApp webApp = getWebApp();
        if (webApp != null) {
            JaxWsModel jaxWsModel = (JaxWsModel)project.getLookup().lookup(JaxWsModel.class);
            if (jaxWsModel != null) {
                Service service = jaxWsModel.findServiceByName(serviceName);
                if (service != null) {
                    boolean changed = removeJsr109ServletsFromDD(webApp, service);
                    if(changed){
                        try{
                            webApp.write(getDeploymentDescriptor());
                        } catch(IOException e){
                            Exceptions.printStackTrace(e);
                        }
                    }
                }
            }
        }
    }

    /**
     * Remove the web.xml servlets for the non-JSR 109 web service.
     *
     * @param serviceName Name of the web service to be removed
     */
    private boolean removeJsr109ServletsFromDD(WebApp webApp, Service service) {
        boolean changed = false;
        //first remove the servlet
        String implClass = service.getImplementationClass();
        if (implClass != null) {
            String servletName = null;
            for(Servlet servlet:webApp.getServlet()){
                if(implClass.equals(servlet.getServletClass())) {
                    webApp.removeServlet(servlet);
                    servletName = servlet.getServletName();
                    changed = true;
                    break;
                }
            }
            //remove the servlet mapping
            if (servletName != null) {
                for(ServletMapping mapping:webApp.getServletMapping()) {
                    if(mapping.getServletName().equals(servletName)){
                        webApp.removeServletMapping(mapping);
                        changed = true;
                        break;
                    }
                }
            }
        }
        return changed;
    }

    @Override
    public String addService(String name, String serviceImpl, String wsdlUrl, String serviceName,
            String portName, String packageName, boolean isJsr109, boolean useProvider) {
        // create jax-ws.xml if necessary
        FileObject fo = WSUtils.findJaxWsFileObject(project);
        if (fo==null) {
            try {
                WSUtils.createJaxWsFileObject(project);
                // logging first service creation
                logWsDetected();
            } catch (IOException ex) {
                Exceptions.printStackTrace(ex);
            }
        }
        return super.addService(name, serviceImpl, wsdlUrl, serviceName, portName, packageName, isJsr109, useProvider);
    }

    @Override
    public void addService(String serviceName, String serviceImpl, boolean isJsr109) {
        // create jax-ws.xml if necessary
        FileObject fo = WSUtils.findJaxWsFileObject(project);
        if (fo==null) {
            try {
                WSUtils.createJaxWsFileObject(project);
                // logging first service creation
                logWsDetected();
            } catch (IOException ex) {
                Exceptions.printStackTrace(ex);
            }
        }
        super.addService(serviceName, serviceImpl, isJsr109);
    }

    @Override
    public MetadataModel<WebservicesMetadata> getWebservicesMetadataModel() {
        return project.getWebModule().getWebservicesMetadataModel();
    }

    private void logWsDetected() {
        Object[] params = new Object[3];
        params[0] = LogUtils.WS_STACK_JAXWS;
        params[1] = project.getClass().getName();
        params[2] = "SERVICE"; // NOI18N
        LogUtils.logWsDetect(params);
    }

    @Override
    protected String getProjectJavaEEVersion() {
        WebModule webModule = WebModule.getWebModule(project.getProjectDirectory());
        if (webModule != null) {
            if (Profile.JAVA_EE_6_WEB.equals(webModule.getJ2eeProfile())) {
                return JAVA_EE_VERSION_16;
            } else if (Profile.JAVA_EE_6_FULL.equals(webModule.getJ2eeProfile())) {
                return JAVA_EE_VERSION_16;
            } else if (Profile.JAVA_EE_7_WEB.equals(webModule.getJ2eeProfile())) {
                return JAVA_EE_VERSION_17;
            } else if (Profile.JAVA_EE_7_FULL.equals(webModule.getJ2eeProfile())) {
                return JAVA_EE_VERSION_17;
            } else if (Profile.JAVA_EE_8_WEB.equals(webModule.getJ2eeProfile())) {
                return JAVA_EE_VERSION_18;
            } else if (Profile.JAVA_EE_8_FULL.equals(webModule.getJ2eeProfile())) {
                return JAVA_EE_VERSION_18;
            } else if (Profile.JAKARTA_EE_8_WEB.equals(webModule.getJ2eeProfile())) {
                return JAKARTA_EE_VERSION_8;
            } else if (Profile.JAKARTA_EE_8_FULL.equals(webModule.getJ2eeProfile())) {
                return JAKARTA_EE_VERSION_8;
            } else if (Profile.JAKARTA_EE_9_WEB.equals(webModule.getJ2eeProfile())) {
                return JAKARTA_EE_VERSION_9;
            } else if (Profile.JAKARTA_EE_9_FULL.equals(webModule.getJ2eeProfile())) {
                return JAKARTA_EE_VERSION_9;
            } else if (Profile.JAKARTA_EE_9_1_WEB.equals(webModule.getJ2eeProfile())) {
                return JAKARTA_EE_VERSION_91;
            } else if (Profile.JAKARTA_EE_9_1_FULL.equals(webModule.getJ2eeProfile())) {
                return JAKARTA_EE_VERSION_91;
            } else if (Profile.JAKARTA_EE_10_WEB.equals(webModule.getJ2eeProfile())) {
                return JAKARTA_EE_VERSION_10;
            } else if (Profile.JAKARTA_EE_10_FULL.equals(webModule.getJ2eeProfile())) {
                return JAKARTA_EE_VERSION_10;
            } else if (Profile.JAVA_EE_5.equals(webModule.getJ2eeProfile())) {
              return JAVA_EE_VERSION_15;
            }
        }
        return JAVA_EE_VERSION_NONE;
    }

}
