/**
 * 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.camel.spring.handler;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import javax.xml.bind.Binder;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import org.apache.camel.builder.xml.Namespaces;
import org.apache.camel.model.FromDefinition;
import org.apache.camel.model.SendDefinition;
import org.apache.camel.spi.NamespaceAware;
import org.apache.camel.spring.CamelBeanPostProcessor;
import org.apache.camel.spring.CamelConsumerTemplateFactoryBean;
import org.apache.camel.spring.CamelContextFactoryBean;
import org.apache.camel.spring.CamelEndpointFactoryBean;
import org.apache.camel.spring.CamelJMXAgentDefinition;
import org.apache.camel.spring.CamelProducerTemplateFactoryBean;
import org.apache.camel.spring.CamelPropertyPlaceholderDefinition;
import org.apache.camel.spring.CamelRouteContextFactoryBean;
import org.apache.camel.spring.CamelThreadPoolFactoryBean;
import org.apache.camel.spring.remoting.CamelProxyFactoryBean;
import org.apache.camel.spring.remoting.CamelServiceExporter;
import org.apache.camel.util.ObjectHelper;
import org.apache.camel.view.ModelFileGenerator;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
import org.springframework.beans.factory.xml.ParserContext;

/**
 * Camel namespace for the spring XML configuration file.
 */
public class CamelNamespaceHandler extends NamespaceHandlerSupport {
    private static final String SPRING_NS = "http://camel.apache.org/schema/spring";
    private static final Log LOG = LogFactory.getLog(CamelNamespaceHandler.class);
    protected BeanDefinitionParser endpointParser = new BeanDefinitionParser(CamelEndpointFactoryBean.class);
    protected BeanDefinitionParser beanPostProcessorParser = new BeanDefinitionParser(CamelBeanPostProcessor.class);
    protected Set<String> parserElementNames = new HashSet<String>();
    private JAXBContext jaxbContext;
    private Map<String, BeanDefinitionParser> parserMap = new HashMap<String, BeanDefinitionParser>();
    private Map<String, BeanDefinition> autoRegisterMap = new HashMap<String, BeanDefinition>();

    public static void renameNamespaceRecursive(Node node) {
        if (node.getNodeType() == Node.ELEMENT_NODE) {
            Document doc = node.getOwnerDocument();
            if (node.getNamespaceURI().startsWith(SPRING_NS + "/v")) {
                doc.renameNode(node, SPRING_NS, node.getNodeName());
            }
        }
        NodeList list = node.getChildNodes();
        for (int i = 0; i < list.getLength(); ++i) {
            renameNamespaceRecursive(list.item(i));
        }
    }

    public ModelFileGenerator createModelFileGenerator() throws JAXBException {
        return new ModelFileGenerator(getJaxbContext());
    }

    public void init() {
        // register routeContext parser
        registerParser("routeContext", new RouteContextDefinitionParser());

        addBeanDefinitionParser("proxy", CamelProxyFactoryBean.class, true);
        addBeanDefinitionParser("template", CamelProducerTemplateFactoryBean.class, true);
        addBeanDefinitionParser("consumerTemplate", CamelConsumerTemplateFactoryBean.class, true);
        addBeanDefinitionParser("export", CamelServiceExporter.class, true);
        addBeanDefinitionParser("endpoint", CamelEndpointFactoryBean.class, true);
        addBeanDefinitionParser("threadPool", CamelThreadPoolFactoryBean.class, true);

        // jmx agent and property placeholder cannot be used outside of the camel context
        addBeanDefinitionParser("jmxAgent", CamelJMXAgentDefinition.class, false);
        addBeanDefinitionParser("propertyPlaceholder", CamelPropertyPlaceholderDefinition.class, false);

        // errorhandler could be the sub element of camelContext or defined outside camelContext
        BeanDefinitionParser errorHandlerParser = new ErrorHandlerDefinitionParser();
        registerParser("errorHandler", errorHandlerParser);
        parserMap.put("errorHandler", errorHandlerParser);

        // camel context
        boolean osgi = false;
        Class cl = CamelContextFactoryBean.class;
        try {
            cl = Class.forName("org.apache.camel.osgi.CamelContextFactoryBean");
            osgi = true;
        } catch (Throwable t) {
            // not running with camel-osgi so we fallback to the regular factory bean
            LOG.trace("Cannot find class so assuming not running in OSGi container: " + t.getMessage());
        }
        if (osgi) {
            LOG.info("camel-osgi.jar/camel-spring-osgi.jar detected in classpath");
        } else {
            LOG.info("camel-osgi.jar/camel-spring-osgi.jar not detected in classpath");
        }
        if (LOG.isDebugEnabled()) {
            LOG.debug("Using " + cl.getCanonicalName() + " as CamelContextBeanDefinitionParser");
        }
        registerParser("camelContext", new CamelContextBeanDefinitionParser(cl));
    }

    private void addBeanDefinitionParser(String elementName, Class<?> type, boolean register) {
        BeanDefinitionParser parser = new BeanDefinitionParser(type);
        if (register) {
            registerParser(elementName, parser);
        }
        parserMap.put(elementName, parser);
    }

    protected void createBeanPostProcessor(ParserContext parserContext, String contextId, Element childElement, BeanDefinitionBuilder parentBuilder) {
        String beanPostProcessorId = contextId + ":beanPostProcessor";
        childElement.setAttribute("id", beanPostProcessorId);
        BeanDefinition definition = beanPostProcessorParser.parse(childElement, parserContext);
        // only register to camel context id as a String. Then we can look it up later
        // otherwise we get a circular reference in spring and it will not allow custom bean post processing
        // see more at CAMEL-1663
        definition.getPropertyValues().addPropertyValue("camelId", contextId);
        parentBuilder.addPropertyReference("beanPostProcessor", beanPostProcessorId);
    }

    protected void registerParser(String name, org.springframework.beans.factory.xml.BeanDefinitionParser parser) {
        parserElementNames.add(name);
        registerBeanDefinitionParser(name, parser);
    }

    protected Object parseUsingJaxb(Element element, ParserContext parserContext, Binder<Node> binder) {
        try {
            return binder.unmarshal(element);
        } catch (JAXBException e) {
            throw new BeanDefinitionStoreException("Failed to parse JAXB element", e);
        }
    }

    public JAXBContext getJaxbContext() throws JAXBException {
        if (jaxbContext == null) {
            jaxbContext = createJaxbContext();
        }
        return jaxbContext;
    }

    protected JAXBContext createJaxbContext() throws JAXBException {
        StringBuilder packages = new StringBuilder();
        for (Class cl : getJaxbPackages()) {
            if (packages.length() > 0) {
                packages.append(":");
            }
            packages.append(cl.getName().substring(0, cl.getName().lastIndexOf('.')));
        }
        return JAXBContext.newInstance(packages.toString(), getClass().getClassLoader());
    }

    protected Set<Class> getJaxbPackages() {
        Set<Class> classes = new HashSet<Class>();
        classes.add(org.apache.camel.spring.CamelContextFactoryBean.class);
        classes.add(org.apache.camel.ExchangePattern.class);
        classes.add(org.apache.camel.model.RouteDefinition.class);
        classes.add(org.apache.camel.model.config.StreamResequencerConfig.class);
        classes.add(org.apache.camel.model.dataformat.DataFormatsDefinition.class);
        classes.add(org.apache.camel.model.language.ExpressionDefinition.class);
        classes.add(org.apache.camel.model.loadbalancer.RoundRobinLoadBalancerDefinition.class);
        return classes;
    }

    protected class RouteContextDefinitionParser extends BeanDefinitionParser {

        public RouteContextDefinitionParser() {
            super(CamelRouteContextFactoryBean.class);
        }

        @Override
        protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
            renameNamespaceRecursive(element);
            super.doParse(element, parserContext, builder);

            // now lets parse the routes with JAXB
            Binder<Node> binder;
            try {
                binder = getJaxbContext().createBinder();
            } catch (JAXBException e) {
                throw new BeanDefinitionStoreException("Failed to create the JAXB binder", e);
            }
            Object value = parseUsingJaxb(element, parserContext, binder);

            if (value instanceof CamelRouteContextFactoryBean) {
                CamelRouteContextFactoryBean factoryBean = (CamelRouteContextFactoryBean)value;
                builder.addPropertyValue("routes", factoryBean.getRoutes());
            }
        }
    }


    protected class CamelContextBeanDefinitionParser extends BeanDefinitionParser {

        public CamelContextBeanDefinitionParser(Class type) {
            super(type);
        }

        @Override
        protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
            renameNamespaceRecursive(element);
            super.doParse(element, parserContext, builder);

            String contextId = element.getAttribute("id");

            // lets avoid folks having to explicitly give an ID to a camel context
            if (ObjectHelper.isEmpty(contextId)) {
                contextId = "camelContext";
                element.setAttribute("id", contextId);
            }

            // now lets parse the routes with JAXB
            Binder<Node> binder;
            try {
                binder = getJaxbContext().createBinder();
            } catch (JAXBException e) {
                throw new BeanDefinitionStoreException("Failed to create the JAXB binder", e);
            }
            Object value = parseUsingJaxb(element, parserContext, binder);
            
            if (value instanceof CamelContextFactoryBean) {
                // set the property value with the JAXB parsed value
                CamelContextFactoryBean factoryBean = (CamelContextFactoryBean)value;
                builder.addPropertyValue("id", contextId);
                builder.addPropertyValue("routes", factoryBean.getRoutes());
                builder.addPropertyValue("intercepts", factoryBean.getIntercepts());
                builder.addPropertyValue("interceptFroms", factoryBean.getInterceptFroms());
                builder.addPropertyValue("interceptSendToEndpoints", factoryBean.getInterceptSendToEndpoints());
                builder.addPropertyValue("dataFormats", factoryBean.getDataFormats());
                builder.addPropertyValue("onCompletions", factoryBean.getOnCompletions());
                builder.addPropertyValue("onExceptions", factoryBean.getOnExceptions());
                builder.addPropertyValue("builderRefs", factoryBean.getBuilderRefs());
                builder.addPropertyValue("routeRefs", factoryBean.getRouteRefs());
                builder.addPropertyValue("properties", factoryBean.getProperties());
                builder.addPropertyValue("packageScan", factoryBean.getPackageScan());
                if (factoryBean.getPackages().length > 0) {
                    builder.addPropertyValue("packages", factoryBean.getPackages());
                }
                builder.addPropertyValue("camelPropertyPlaceholder", factoryBean.getCamelPropertyPlaceholder());
                builder.addPropertyValue("camelJMXAgent", factoryBean.getCamelJMXAgent());
                builder.addPropertyValue("threadPoolProfiles", factoryBean.getThreadPoolProfiles());
                // add any depends-on
                addDependsOn(factoryBean, builder);
            }

            boolean createdBeanPostProcessor = false;
            NodeList list = element.getChildNodes();
            int size = list.getLength();
            for (int i = 0; i < size; i++) {
                Node child = list.item(i);
                if (child instanceof Element) {
                    Element childElement = (Element)child;
                    String localName = child.getLocalName();
                    if (localName.equals("beanPostProcessor")) {
                        createBeanPostProcessor(parserContext, contextId, childElement, builder);
                        createdBeanPostProcessor = true;
                    } else if (localName.equals("endpoint")) {
                        registerEndpoint(childElement, parserContext, contextId);
                    } else {
                        BeanDefinitionParser parser = parserMap.get(localName);
                        if (parser != null) {
                            BeanDefinition definition = parser.parse(childElement, parserContext);
                            String id = childElement.getAttribute("id");
                            if (ObjectHelper.isNotEmpty(id)) {
                                parserContext.registerComponent(new BeanComponentDefinition(definition, id));
                                // set the templates with the camel context
                                if (localName.equals("template") || localName.equals("consumerTemplate")
                                    || localName.equals("proxy") || localName.equals("export")) {
                                    // set the camel context
                                    definition.getPropertyValues().addPropertyValue("camelContext", new RuntimeBeanReference(contextId));
                                }
                            }
                        }
                    }
                }
            }

            // register as endpoint defined indirectly in the routes by from/to types having id explicit set
            registerEndpointsWithIdsDefinedInFromOrToTypes(element, parserContext, contextId, binder);

            // register templates if not already defined
            registerTemplates(element, parserContext, contextId);

            // lets inject the namespaces into any namespace aware POJOs
            injectNamespaces(element, binder);
            if (!createdBeanPostProcessor) {
                // no bean processor element so lets create it by our self
                Element childElement = element.getOwnerDocument().createElement("beanPostProcessor");
                element.appendChild(childElement);
                createBeanPostProcessor(parserContext, contextId, childElement, builder);
            }
        }
    }

    protected void addDependsOn(CamelContextFactoryBean factoryBean, BeanDefinitionBuilder builder) {
        String dependsOn = factoryBean.getDependsOn();
        if (ObjectHelper.isNotEmpty(dependsOn)) {
            // comma, whitespace and semi colon is valid separators in Spring depends-on
            String[] depends = dependsOn.split(",|;|\\s");
            if (depends == null) {
                throw new IllegalArgumentException("Cannot separate depends-on, was: " + dependsOn);
            } else {
                for (String depend : depends) {
                    depend = depend.trim();
                    if (LOG.isDebugEnabled()) {
                        LOG.debug("Adding dependsOn " + depend + " to CamelContext(" + factoryBean.getId() + ")");
                    }
                    builder.addDependsOn(depend);
                }
            }
        }
    }

    protected void injectNamespaces(Element element, Binder<Node> binder) {
        NodeList list = element.getChildNodes();
        Namespaces namespaces = null;
        int size = list.getLength();
        for (int i = 0; i < size; i++) {
            Node child = list.item(i);
            if (child instanceof Element) {
                Element childElement = (Element)child;
                Object object = binder.getJAXBNode(child);
                if (object instanceof NamespaceAware) {
                    NamespaceAware namespaceAware = (NamespaceAware)object;
                    if (namespaces == null) {
                        namespaces = new Namespaces(element);
                    }
                    namespaces.configure(namespaceAware);
                }
                injectNamespaces(childElement, binder);
            }
        }
    }

    /**
     * Used for auto registering endpoints from the <tt>from</tt> or <tt>to</tt> DSL if they have an id attribute set
     */
    protected void registerEndpointsWithIdsDefinedInFromOrToTypes(Element element, ParserContext parserContext, String contextId, Binder<Node> binder) {
        NodeList list = element.getChildNodes();
        int size = list.getLength();
        for (int i = 0; i < size; i++) {
            Node child = list.item(i);
            if (child instanceof Element) {
                Element childElement = (Element)child;
                Object object = binder.getJAXBNode(child);
                // we only want from/to types to be registered as endpoints
                if (object instanceof FromDefinition || object instanceof SendDefinition) {
                    registerEndpoint(childElement, parserContext, contextId);
                }
                // recursive
                registerEndpointsWithIdsDefinedInFromOrToTypes(childElement, parserContext, contextId, binder);
            }
        }
    }

    /**
     * Used for auto registering producer and consumer templates if not already defined in XML.
     */
    protected void registerTemplates(Element element, ParserContext parserContext, String contextId) {
        boolean template = false;
        boolean consumerTemplate = false;

        NodeList list = element.getChildNodes();
        int size = list.getLength();
        for (int i = 0; i < size; i++) {
            Node child = list.item(i);
            if (child instanceof Element) {
                Element childElement = (Element)child;
                String localName = childElement.getLocalName();
                if ("template".equals(localName)) {
                    template = true;
                } else if ("consumerTemplate".equals(localName)) {
                    consumerTemplate = true;
                }
            }
        }

        // either we have not used template before or we have auto registered it already and therefore we
        // need it to allow to do it so it can remove the existing auto registered as there is now a clash id
        // since we have multiple camel contexts
        boolean canDoTemplate = autoRegisterMap.get("template") != null
                || !parserContext.getRegistry().isBeanNameInUse("template");
        if (!template && canDoTemplate) {
            String id = "template";
            // auto create a template
            Element templateElement = element.getOwnerDocument().createElement("template");
            templateElement.setAttribute("id", id);
            BeanDefinitionParser parser = parserMap.get("template");
            BeanDefinition definition = parser.parse(templateElement, parserContext);

            // auto register it
            autoRegisterBeanDefinition(id, definition, parserContext, contextId);
        }

        // either we have not used template before or we have auto registered it already and therefore we
        // need it to allow to do it so it can remove the existing auto registered as there is now a clash id
        // since we have multiple camel contexts
        boolean canDoConsumerTemplate = autoRegisterMap.get("consumerTemplate") != null
                || !parserContext.getRegistry().isBeanNameInUse("consumerTemplate");
        if (!consumerTemplate && canDoConsumerTemplate) {
            String id = "consumerTemplate";
            // auto create a template
            Element templateElement = element.getOwnerDocument().createElement("consumerTemplate");
            templateElement.setAttribute("id", id);
            BeanDefinitionParser parser = parserMap.get("consumerTemplate");
            BeanDefinition definition = parser.parse(templateElement, parserContext);

            // auto register it
            autoRegisterBeanDefinition(id, definition, parserContext, contextId);
        }

    }

    private void autoRegisterBeanDefinition(String id, BeanDefinition definition, ParserContext parserContext, String contextId) {
        // it is a bit cumbersome to work with the spring bean definition parser
        // as we kinda need to eagerly register the bean definition on the parser context
        // and then later we might find out that we should not have done that in case we have multiple camel contexts
        // that would have a id clash by auto registering the same bean definition with the same id such as a producer template

        // see if we have already auto registered this id
        BeanDefinition existing = autoRegisterMap.get(id);
        if (existing == null) {
            // no then add it to the map and register it
            autoRegisterMap.put(id, definition);
            parserContext.registerComponent(new BeanComponentDefinition(definition, id));
            if (LOG.isDebugEnabled()) {
                LOG.debug("Registered default: " + definition.getBeanClassName() + " with id: " + id + " on camel context: " + contextId);
            }
        } else {
            // ups we have already registered it before with same id, but on another camel context
            // this is not good so we need to remove all traces of this auto registering.
            // end user must manually add the needed XML elements and provide unique ids access all camel context himself.
            if (LOG.isDebugEnabled()) {
                LOG.debug("Unregistered default: " + definition.getBeanClassName() + " with id: " + id
                    + " as we have multiple camel contexts and they must use unique ids."
                    + " You must define the definition in the XML file manually to avoid id clashes when using multiple camel contexts");
            }

            parserContext.getRegistry().removeBeanDefinition(id);
        }
    }

    private void registerEndpoint(Element childElement, ParserContext parserContext, String contextId) {
        String id = childElement.getAttribute("id");
        // must have an id to be registered
        if (ObjectHelper.isNotEmpty(id)) {
            BeanDefinition definition = endpointParser.parse(childElement, parserContext);
            definition.getPropertyValues().addPropertyValue("camelContext", new RuntimeBeanReference(contextId));
            // Need to add this dependency of CamelContext for Spring 3.0
            try {
                Method method = definition.getClass().getMethod("setDependsOn", String[].class);
                method.invoke(definition, (Object)new String[]{contextId});
            } catch (Exception e) {
                // Do nothing here
            }
            parserContext.registerBeanComponent(new BeanComponentDefinition(definition, id));
        }
    }
    
}
