/*
 * 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.apache.tuscany.sca.host.webapp;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Enumeration;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;

import org.apache.tuscany.sca.core.ExtensionPointRegistry;
import org.apache.tuscany.sca.core.UtilityExtensionPoint;
import org.apache.tuscany.sca.host.http.ServletHost;
import org.apache.tuscany.sca.host.http.ServletHostExtensionPoint;
import org.apache.tuscany.sca.node.Node;
import org.apache.tuscany.sca.node.NodeFactory;
import org.apache.tuscany.sca.node.configuration.NodeConfiguration;

public class WebAppHelper {
    private static final String ROOT = "/";
    // The prefix for the parameters in web.xml which configure the folders that contain SCA contributions
    private static final String CONTRIBUTIONS = "contributions";
    // The prefix for the parameters in web.xml which configure the individual SCA contributions
    private static final String CONTRIBUTION = "contribution";
    private static final String NODE_CONFIGURATION = "node.configuration";
    private static final String WEB_COMPOSITE = "/WEB-INF/web.composite";
    private static final String DOMAIN_URI = "domain.uri";
    private static final String NODE_URI = "node.uri";
    public static final String DOMAIN_NAME_ATTR = "org.apache.tuscany.sca.domain.name";
    public static final String SCA_NODE_ATTRIBUTE = Node.class.getName();
    private static NodeFactory factory;
    private static WebAppServletHost host;

    private static URL getResource(ServletContext servletContext, String location) throws IOException {
        URI uri = URI.create(location);
        if (uri.isAbsolute()) {
            return uri.toURL();
        } else {
            String path = location;
            if (!path.startsWith(ROOT)) {
                path = ROOT + path;
            }
            URL url = servletContext.getResource(path);
            if (url != null && url.getProtocol().equals("jndi")) {
                //this is Tomcat case, we should use getRealPath
                File warRootFile = new File(servletContext.getRealPath(path));
                return warRootFile.toURI().toURL();
            } else {
                //this is Jetty case
                return url;
            }
        }
    }
    
    private static String[] parse(String listOfValues) {
        if (listOfValues == null) {
            return null;
        }
        return listOfValues.split("(\\s|,)+");
    }

    @SuppressWarnings("unchecked")
    private static NodeConfiguration getNodeConfiguration(ServletContext servletContext) throws IOException,
        URISyntaxException {
        NodeConfiguration configuration = null;
        String nodeConfigURI = (String)servletContext.getAttribute(NODE_CONFIGURATION);
        if (nodeConfigURI != null) {
            URL url = getResource(servletContext, nodeConfigURI);
            configuration = factory.loadConfiguration(url.openStream(), url);
        } else {
            configuration = factory.createNodeConfiguration();
            Enumeration<String> names = servletContext.getAttributeNames();
            while (names.hasMoreElements()) {
                String name = names.nextElement();
                if (name.equals(CONTRIBUTION) || name.startsWith(CONTRIBUTION + ".")) {
                    // We need to have a way to select one or more folders within the webapp as the contributions
                    String listOfValues = (String)servletContext.getAttribute(name);
                    if (listOfValues != null) {
                        for (String path : parse(listOfValues)) {
                            if ("".equals(path)) {
                                continue;
                            }
                            File f = new File(getResource(servletContext, path).toURI());
                            configuration.addContribution(f.toURI().toURL());
                        }
                    }
                } else if (name.equals(CONTRIBUTIONS) || name.startsWith(CONTRIBUTIONS + ".")) {
                    String listOfValues = (String)servletContext.getAttribute(name);
                    if (listOfValues != null) {
                        for (String path : parse(listOfValues)) {
                            if ("".equals(path)) {
                                continue;
                            }
                            File f = new File(getResource(servletContext, path).toURI());
                            if (f.isDirectory()) {
                                for (File n : f.listFiles()) {
                                    configuration.addContribution(n.toURI().toURL());
                                }
                            } else {
                                configuration.addContribution(f.toURI().toURL());
                            }
                        }
                    }
                }
            }

            if (configuration.getContributions().isEmpty()) {
                // TODO: Which path should be the default root
                configuration.addContribution(getResource(servletContext, ROOT));
            }
            URL composite = getResource(servletContext, WEB_COMPOSITE);
            if (composite != null) {
                configuration.getContributions().get(0).addDeploymentComposite(composite);
            }
            String nodeURI = (String)servletContext.getAttribute(NODE_URI);
            if (nodeURI == null) {
                nodeURI = new File(servletContext.getRealPath(ROOT)).getName();
            }
            configuration.setURI(nodeURI);
            String domainURI = (String)servletContext.getAttribute(DOMAIN_URI);
            if (domainURI != null) {
                configuration.setDomainURI(domainURI);
            } else {
                domainURI = servletContext.getInitParameter("org.apache.tuscany.sca.defaultDomainURI");
                if (domainURI != null) {
                    configuration.setDomainURI(getDomainName(domainURI));
                    configuration.setDomainRegistryURI(domainURI);
                }
            }
        }
        return configuration;
    }

    // TODO: Temp for now to get the old samples working till i clean up all the domain uri/name after the ML discussion.
    private static String getDomainName(String configURI) {
        String domainName;
        if (configURI.startsWith("tuscany:vm:")) {
            domainName = configURI.substring("tuscany:vm:".length());
        } else if (configURI.startsWith("tuscany:")) {
            int i = configURI.indexOf('?');
            if (i == -1) {
                domainName = configURI.substring("tuscany:".length());
            } else {
                domainName = configURI.substring("tuscany:".length(), i);
            }
        } else {
            domainName = configURI;
        }
        return domainName;
    }

    public synchronized static ServletHost init(final ServletContext servletContext) {
        if (host == null) {
            try {

                String configValue = servletContext.getInitParameter("org.apache.tuscany.sca.config");
                if (configValue != null) {
                    factory = NodeFactory.newInstance(configValue);
                } else {
                    factory = NodeFactory.newInstance();
                }
                
                // Add ServletContext as a utility
                ExtensionPointRegistry registry = factory.getExtensionPointRegistry();
                UtilityExtensionPoint utilityExtensionPoint = registry.getExtensionPoint(UtilityExtensionPoint.class);
                utilityExtensionPoint.addUtility(ServletContext.class, servletContext);
                
                ServletHostExtensionPoint servletHosts = registry.getExtensionPoint(ServletHostExtensionPoint.class);
                servletHosts.setWebApp(true);

                // TODO: why are the init parameters copied to the attributes?
                for (Enumeration<?> e = servletContext.getInitParameterNames(); e.hasMoreElements();) {
                    String name = (String)e.nextElement();
                    String value = servletContext.getInitParameter(name);
                    servletContext.setAttribute(name, value);
                }

                host = getServletHost(servletContext);

            } catch (ServletException e) {
                throw new RuntimeException(e);
            }
        }
        Node node = (Node)servletContext.getAttribute(SCA_NODE_ATTRIBUTE);
        if (node == null) {
            try {
                node = createAndStartNode(servletContext);
            } catch (ServletException e) {
                throw new RuntimeException(e);
            }
            servletContext.setAttribute(SCA_NODE_ATTRIBUTE, node);
        }

        return host;
    }

    private static WebAppServletHost getServletHost(final ServletContext servletContext) throws ServletException {
        WebAppServletHost host = getServletHost(factory);
        host.init(new ServletConfig() {
            public String getInitParameter(String name) {
                return servletContext.getInitParameter(name);
            }

            public Enumeration<?> getInitParameterNames() {
                return servletContext.getInitParameterNames();
            }

            public ServletContext getServletContext() {
                return servletContext;
            }

            public String getServletName() {
                return servletContext.getServletContextName();
            }
        });
        return host;
    }

    private static WebAppServletHost getServletHost(NodeFactory factory) {
        ExtensionPointRegistry registry = factory.getExtensionPointRegistry();
        return (WebAppServletHost)org.apache.tuscany.sca.host.http.ServletHostHelper.getServletHost(registry);
    }

    private static Node createAndStartNode(final ServletContext servletContext) throws ServletException {
        NodeConfiguration configuration;
        try {
            configuration = getNodeConfiguration(servletContext);
        } catch (IOException e) {
            throw new ServletException(e);
        } catch (URISyntaxException e) {
            throw new ServletException(e);
        }
        Node node = factory.createNode(configuration).start();
        return node;
    }

    public static void stop(ServletContext servletContext) {
        Node node = (Node)servletContext.getAttribute(SCA_NODE_ATTRIBUTE);
        if (node != null) {
            node.stop();
            servletContext.setAttribute(SCA_NODE_ATTRIBUTE, null);
        }
    }

    public static NodeFactory getNodeFactory() {
        return factory;
    }
}
