/*
 *  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.synapse.config.xml.endpoints;

import org.apache.axiom.om.OMAttribute;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMXMLBuilderFactory;
import org.apache.axiom.om.OMXMLParserWrapper;
import org.apache.synapse.SynapseConstants;
import org.apache.synapse.config.xml.XMLConfigConstants;
import org.apache.synapse.config.xml.endpoints.utils.LoadbalanceAlgorithmFactory;
import org.apache.synapse.endpoints.Endpoint;
import org.apache.synapse.endpoints.ServiceDynamicLoadbalanceEndpoint;
import org.apache.synapse.endpoints.algorithms.LoadbalanceAlgorithm;
import org.apache.synapse.endpoints.dispatch.Dispatcher;
import org.apache.synapse.endpoints.dispatch.HttpSessionDispatcher;
import org.apache.synapse.endpoints.dispatch.SoapSessionDispatcher;

import javax.xml.namespace.QName;
import java.net.URL;
import java.util.*;

/**
 * Creates {@link org.apache.synapse.endpoints.DynamicLoadbalanceEndpoint} using an XML configuration.
 * <p/>
 * <pre>
 * <endpoint name="sdLB">
 *       <serviceDynamicLoadbalance algorithm="org.apache.synapse.endpoints.algorithms.RoundRobin"
 *                                  configuration="file:repository/conf/lbservices.xml"/>
 * </endpoint>
 * </pre>
 * <p/>
 * The configuration file has the following format. This can be even specified inline
 * <loadBalancerConfig>
 * <services>
 * <service>
 * <hosts>
 * <host>test1.synapse.apache.org</host>
 * <host>test1.apache.org</host>
 * </hosts>
 * <domain>test1.synapse.apache.domain</domain>
 * </service>
 * <service>
 * <hosts>
 * <host>test2.synapse.apache.org</host>
 * <host>test2.apache.org</host>
 * </hosts>
 * <domain>test2.synapse.apache.domain</domain>
 * </service>
 * </services>
 * </loadBalancerConfig>
 */
public class ServiceDynamicLoadbalanceEndpointFactory extends EndpointFactory {

    private static ServiceDynamicLoadbalanceEndpointFactory instance =
            new ServiceDynamicLoadbalanceEndpointFactory();
    public static final QName SERVICES_QNAME = new QName(SynapseConstants.SYNAPSE_NAMESPACE,
                                                         "services");
    public static final QName LB_CONFIG_QNAME = new QName(SynapseConstants.SYNAPSE_NAMESPACE,
                                                          "loadBalancerConfig");

    private ServiceDynamicLoadbalanceEndpointFactory() {
    }

    public static ServiceDynamicLoadbalanceEndpointFactory getInstance() {
        return instance;
    }

    protected Endpoint createEndpoint(OMElement epConfig, boolean anonymousEndpoint,
                                      Properties properties) {

        OMElement loadbalanceElement =
                epConfig.getFirstChildWithName(new QName(SynapseConstants.SYNAPSE_NAMESPACE,
                                                         "serviceDynamicLoadbalance"));
        if (loadbalanceElement == null) {
            return null;
        }

        String configuration =
                loadbalanceElement.getAttributeValue(new QName(XMLConfigConstants.NULL_NAMESPACE,
                                                               "configuration"));
        OMElement servicesEle;
        if (configuration != null) {
            if (configuration.startsWith("$system:")) {
                configuration = System.getProperty(configuration.substring("$system:".length()));
            }
            // Load the file
            OMXMLParserWrapper builder = null;
            try {
                builder = OMXMLBuilderFactory.createOMBuilder(new URL(configuration).openStream());
            } catch (Exception e) {
                handleException("Could not load ServiceDynamicLoadbalanceEndpoint configuration file " +
                                configuration);
            }
            servicesEle = builder.getDocumentElement().getFirstChildWithName(SERVICES_QNAME);
        } else {
            OMElement lbConfigEle = loadbalanceElement.getFirstChildWithName(LB_CONFIG_QNAME);
            if (lbConfigEle == null) {
                throw new RuntimeException("loadBalancerConfig element not found as a child of " +
                                           "serviceDynamicLoadbalance element");
            }
            servicesEle = lbConfigEle.getFirstChildWithName(SERVICES_QNAME);
        }

        if (servicesEle == null) {
            throw new RuntimeException("services element not found in serviceDynamicLoadbalance configuration");
        }
        Map<String, String> hostDomainMap = new HashMap<String, String>();
        for (Iterator<OMElement> iter = servicesEle.getChildrenWithLocalName("service"); iter.hasNext();) {
            OMElement serviceEle = iter.next();
            OMElement hostsEle =
                    serviceEle.getFirstChildWithName(new QName(SynapseConstants.SYNAPSE_NAMESPACE, "hosts"));
            if (hostsEle == null) {
                throw new RuntimeException("hosts element not found as a child of service element");
            }
            List<String> hosts = new ArrayList<String>();
            for (Iterator<OMElement> hostIter = hostsEle.getChildrenWithLocalName("host");
                 hostIter.hasNext();) {
                OMElement hostEle = hostIter.next();
                String host = hostEle.getText();
                if (host.trim().length() == 0) {
                    throw new RuntimeException("host cannot be null");
                }
                hosts.add(host);
            }
            OMElement domainEle =
                    serviceEle.getFirstChildWithName(new QName(SynapseConstants.SYNAPSE_NAMESPACE,
                                                               "domain"));
            if (domainEle == null) {
                throw new RuntimeException("domain element not found in as a child of services");
            }
            String domain = domainEle.getText();
            if (domain.trim().length() == 0) {
                throw new RuntimeException("domain cannot be null");
            }
            for (String host : hosts) {
                if (hostDomainMap.containsKey(host)) {
                    throw new RuntimeException("host " + host + " has been already defined for " +
                                               "clustering domain " + hostDomainMap.get(host));
                }
                hostDomainMap.put(host, domain);
            }
        }
        if (hostDomainMap.isEmpty()) {
            throw new RuntimeException("No service elements defined under services");
        }

        LoadbalanceAlgorithm algorithm =
                LoadbalanceAlgorithmFactory.
                        createLoadbalanceAlgorithm(loadbalanceElement, null);

        ServiceDynamicLoadbalanceEndpoint loadbalanceEndpoint =
                new ServiceDynamicLoadbalanceEndpoint(hostDomainMap, algorithm);

        // set endpoint name
        OMAttribute name =
                epConfig.getAttribute(new QName(XMLConfigConstants.NULL_NAMESPACE, "name"));
        if (name != null) {
            loadbalanceEndpoint.setName(name.getAttributeValue());
        }

        // get the session for this endpoint
        OMElement sessionElement =
                epConfig.getFirstChildWithName(new QName(SynapseConstants.SYNAPSE_NAMESPACE, "session"));
        if (sessionElement != null) {

            OMElement sessionTimeout = sessionElement.getFirstChildWithName(
                    new QName(SynapseConstants.SYNAPSE_NAMESPACE, "sessionTimeout"));

            if (sessionTimeout != null) {
                try {
                    loadbalanceEndpoint.setSessionTimeout(Long.parseLong(
                            sessionTimeout.getText().trim()));
                } catch (NumberFormatException nfe) {
                    handleException("Invalid session timeout value : " + sessionTimeout.getText());
                }
            }

            String type = sessionElement.getAttributeValue(new QName("type"));

            if (type.equalsIgnoreCase("soap")) {
                Dispatcher soapDispatcher = new SoapSessionDispatcher();
                loadbalanceEndpoint.setDispatcher(soapDispatcher);

            } else if (type.equalsIgnoreCase("http")) {
                Dispatcher httpDispatcher = new HttpSessionDispatcher();
                loadbalanceEndpoint.setDispatcher(httpDispatcher);

            }

            loadbalanceEndpoint.setSessionAffinity(true);
        }
        loadbalanceEndpoint.setFailover(false);

        return loadbalanceEndpoint;
    }
}
