/*
 * 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.axis2.engine;

import org.apache.axis2.AxisFault;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.description.AxisService;
import org.apache.axis2.description.TransportInDescription;
import org.apache.axis2.description.TransportOutDescription;
import org.apache.axis2.i18n.Messages;
import org.apache.axis2.transport.TransportListener;
import org.apache.axis2.transport.TransportSender;
import org.apache.axis2.util.OnDemandLogger;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

public class ListenerManager {

    private static final OnDemandLogger log = new OnDemandLogger(ListenerManager.class);

    protected ListenerManagerShutdownThread shutdownHookThread = null;

    private ConfigurationContext configctx;
    private HashMap<String, TransportListener> startedTransports =
            new HashMap<String, TransportListener>();

    /**
     * We're stopped at first. This is the flag to check whether the listener manager is
     * started or not
     */
    private boolean stopped = true;

    /**
     * need to preserve the default behavior of requiring a shutdown hook, at the same time
     * providing the flexibility to not to add the shutdown hook
     */
    private boolean shutdownHookRequired = true;

    /**
     * Initializes the listener manager and the defined transports in the
     * <code>AxisConfiguration</code>
     *
     * @param configCtx used for the initialization
     */
    public void init(ConfigurationContext configCtx) {

        if (this.configctx != null) {
            log.warn("ConfigurationContext provided for the ListenerManager " +
                    "initialization is null. ListenerManager will not be initialized");
            return;
        }

        configCtx.setTransportManager(this);
        this.configctx = configCtx;

        // initialize all the transport listeners
        for (TransportInDescription transportIn :
                configctx.getAxisConfiguration().getTransportsIn().values()) {
            
            try {
                TransportListener listener = transportIn.getReceiver();
                if (listener != null && startedTransports.get(transportIn.getName()) == null) {
                    listener.init(configctx, transportIn);
                }
            } catch (Exception e) {
                log.error("Couldn't initialize the "
                        + transportIn.getName() + "transport listener", e);
            }
        }
    }

    /**
     * Returns the ConfigurationContext used for the initalization of the listener manager. It
     * should be the current ConfigurationContext in use in most of the time.
     *
     * @return the ConfigurationContext used for the ListenerManager initialization
     */
    public ConfigurationContext getConfigctx() {
        return configctx;
    }

    /**
     * To get an EPR for a given service
     *
     * @param serviceName   the name of the service
     * @param opName        the operation name
     * @param transportName the name of the transport, or null.
     * @return String
     */
    public synchronized EndpointReference getEPRforService(String serviceName, String opName,
                                                           String transportName) throws AxisFault {
        if (transportName == null || "".equals(transportName)) {
            AxisService service = configctx.getAxisConfiguration().getService(serviceName);
            if (service == null) {
                throw new AxisFault(Messages.getMessage("servicenotfoundinthesystem", serviceName));
            }
            if (service.isEnableAllTransports()) {
                Iterator<TransportListener> itr_st = startedTransports.values().iterator();
                while (itr_st.hasNext()) {
                    TransportListener transportListener = itr_st.next();
                    EndpointReference[] epRsForService =
                            transportListener.getEPRsForService(serviceName, null);
                    if (epRsForService != null) {
                        return epRsForService[0];
                    }
                }

                // if nothing can be found return null
                return null;

            } else {
                List<String> exposeTransport = service.getExposedTransports();
                TransportListener listener = startedTransports.get(exposeTransport.get(0));

                EndpointReference[] eprsForService;
                eprsForService = listener.getEPRsForService(serviceName, null);
                return eprsForService != null ? eprsForService[0] : null;
            }

        } else {
            TransportInDescription trsIN = configctx.getAxisConfiguration()
                    .getTransportIn(transportName);
            TransportListener listener = trsIN.getReceiver();
            EndpointReference[] eprsForService;
            eprsForService = listener.getEPRsForService(serviceName, null);
            return eprsForService != null ? eprsForService[0] : null;
        }
    }

    /** To start all the transports */
    public synchronized void start() {
        if (!stopped) {
            log.error("Couldn't start ListenerManager, it seems to be already started!");
            return;
        }

        if (configctx == null) {
            log.error("Can't start uninitialized ListenerManager!");
            return;
        }

        for (Object o : configctx.getAxisConfiguration().getTransportsIn().values()) {
            try {
                TransportInDescription transportIn = (TransportInDescription)o;
                TransportListener listener = transportIn.getReceiver();
                if (listener != null && startedTransports.get(transportIn.getName()) == null) {
                    listener.start();
                    startedTransports.put(transportIn.getName(), listener);
                }
            } catch (Exception e) {
                log.info(e.getMessage(), e);
            }
        }

        if (shutdownHookThread == null && isShutdownHookRequired()) {
            shutdownHookThread = new ListenerManagerShutdownThread(this);
            Runtime.getRuntime().addShutdownHook(shutdownHookThread);
        }
        
        stopped = false;
    }

    public synchronized void startSystem(ConfigurationContext configurationContext) {
        init(configurationContext);
        start();
    }

    /** Stop all the transports and notify modules of shutdown. */
    public synchronized void stop() throws AxisFault {
        if (stopped) {
            return;
        }

        // Remove the shutdown hook
        if (shutdownHookThread != null && shutdownHookThread.getState() != Thread.State.RUNNABLE) {
        	Runtime.getRuntime().removeShutdownHook(shutdownHookThread);
            shutdownHookThread = null;
        }

        for (Object o : startedTransports.values()) {
            TransportListener transportListener = (TransportListener)o;
            transportListener.stop();
        }

        // Stop the transport senders
        if(log.isDebugEnabled()){
            log.debug("Start invoke transport sender shutdown.");
        }
        HashMap<String, TransportOutDescription> outTransports =
                configctx.getAxisConfiguration().getTransportsOut();
        if (outTransports.size() > 0) {
            Iterator<TransportOutDescription> trsItr = outTransports.values().iterator();
            while (trsItr.hasNext()) {
                TransportOutDescription outDescription = trsItr.next();
                TransportSender sender = outDescription.getSender();
                if (sender != null) {
                    sender.stop();
                }
            }
        }
        if(log.isDebugEnabled()){
            log.debug("End Invoke transport sender shutdown.");
        }
        /*Shutdown modules and Services */
        if(log.isDebugEnabled()){
            log.debug("Start Invoke modules and services shutdown.");
        }
        configctx.shutdownModulesAndServices();
        if(log.isDebugEnabled()){
            log.debug("End Invoke modules and services shutdown.");
        }
        stopped = true;
    }

    /**
     * Adds the listener described in the provided <code>TransportInDescription</code>. Further
     * if the listener represented by the TransportInDescription has already been initialized and
     * started the boolean <code>started</code> input parameter has to be provided as
     * <code>true</code>.</p>
     *
     * <p>It is not possible to add a listener which is already initialized but not started to the
     * listener manager, even though the above is a condition that has to be satisfied there is no
     * means of enforcing that, becuase the {@link org.apache.axis2.transport.TransportListener}
     * API doesn't provide a mechanism to test whether it is initialized or started.</p>
     *
     * <p>If the caller is using an already intialized listener, then it is the responsability of
     * the caller to start the listener before adding it to the listener manager and pass the
     * <code>started</code> parameter value as <code>true</code>.
     *
     * @param trsIn Transport in description (which contains Transport Listener) to be added
     * @param started whether the transport Listener that is being added is already started or not
     * @throws AxisFault will throw AxisFault if something goes wrong
     */
    public synchronized void addListener(TransportInDescription trsIn,
                                         boolean started) throws AxisFault {
        configctx.getAxisConfiguration().addTransportIn(trsIn);
        TransportListener transportListener = trsIn.getReceiver();
        if (transportListener != null) {
            if (!started) {
                transportListener.init(configctx, trsIn);
                transportListener.start();
                if (shutdownHookThread == null && isShutdownHookRequired()) {
                    shutdownHookThread = new ListenerManagerShutdownThread(this);
                    Runtime.getRuntime().addShutdownHook(shutdownHookThread);
                }
                stopped = false;
            }
            startedTransports.put(trsIn.getName(), transportListener);
        }
    }

    public synchronized boolean isListenerRunning(String transportName) {
        return startedTransports.get(transportName) != null;
    }

    public boolean isStopped() {
        return stopped;
    }

    public void destroy() throws AxisFault {
        stop();
        this.configctx.setTransportManager(null);
        // need to destory all the transports not only the started ones
        // most of the transports create the worker pool at the init method.
        TransportInDescription transportInDescription;
        for (Object o : configctx.getAxisConfiguration().getAxisConfiguration().getTransportsIn().values()) {
            transportInDescription = (TransportInDescription) o;
            TransportListener transportListener = transportInDescription.getReceiver();
            transportListener.destroy();
        }

        this.startedTransports.clear();
        this.configctx = null;
    }

    public boolean isShutdownHookRequired() {
        return shutdownHookRequired;
    }

    public void setShutdownHookRequired(boolean shutdownHookRequired) {
        this.shutdownHookRequired = shutdownHookRequired;
    }

    static class ListenerManagerShutdownThread extends Thread {
        ListenerManager listenerManager;

        public ListenerManagerShutdownThread(ListenerManager listenerManager) {
            super();
            this.listenerManager = listenerManager;
        }

        public void run() {
            try {
                if (!listenerManager.stopped) {
                    listenerManager.stop();
                }
            } catch (AxisFault axisFault) {
                log.error(axisFault.getMessage(), axisFault);
            }
        }
    }
}
