/*
 * 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.ode.jbi;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.jbi.messaging.DeliveryChannel;
import javax.jbi.messaging.MessageExchange;
import javax.jbi.messaging.MessagingException;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * Receiver pulls messages from the NMS and submits them to ODE for further processing.
 */
public class Receiver implements Runnable {
    private static final Logger __log = LoggerFactory.getLogger(Receiver.class);

    // default time to wait for MessageExchanges, in seconds
    private static final long ACCEPT_TIMEOUT = 1L;

    // default time to wait for the ExecutorService to shut down, in seconds
    private static final long THREADPOOL_SHUTDOWN_TIMEOUT = 10L;

    // default number of threads in the thread pool
    private static final int THREADPOOL_SIZE = 8;

    private OdeContext _odeContext = null;

    private DeliveryChannel _channel = null;

    /** Receiver-Running Flag. */
    private AtomicBoolean _isRunning = new AtomicBoolean(false);

    /** Receiver-Started Flag. */
    private AtomicBoolean _isStarted = new AtomicBoolean(false);

    private Thread _thread;

    // thread pool for dispatching received messages
    private ExecutorService _executorService;

    /**
     * Constructor for creating instance of this class.
     *
     * @param context
     *            for receiving environment parameters.
     */
    public Receiver(OdeContext context) {
        _odeContext = context;
        _thread = new Thread(this);
        _executorService = Executors.newFixedThreadPool(THREADPOOL_SIZE);
    }

    /**
     * Start the receiver thread.
     */
    public void start() {
        if (_isStarted.compareAndSet(false, true)) {
            _isRunning.set(true);
            _thread.start();
        } else
            throw new IllegalStateException("Receiver cannot be restarted.");
    }

    /**
     * This is called to gracefully stop the Receiver thread. After shutting down the thread pool we wait for a maximum
     * of 10 seconds before forcefully canceling in-flight threads.
     */
    public void cease() {

        if (!_isStarted.get())
            return;

        __log.info("Receiver is ceasing.");

        if (_isRunning.compareAndSet(true, false)) {
            try {
                // This should not take more ACCEPT_TIMEOUT seconds, we
                // give it three times as much time.
                _thread.join(3 * TimeUnit.SECONDS.toMillis(ACCEPT_TIMEOUT));

                // Odd, we should not be alive at this point.
                if (_thread.isAlive()) {
                    __log.warn("Receiver thread is not dying gracefully; interrupting.");
                    _thread.interrupt();
                }

                // Try joining again.
                _thread.join(3 * TimeUnit.SECONDS.toMillis(ACCEPT_TIMEOUT));

                // If it's not dead yet, we got a problem we can't deal with.
                if (_thread.isAlive()) {
                    __log.error("Receiver thread is not dying gracefully despite our insistence!.");
                }

                // In any case, next step is to shutdown the thread pool
                _executorService.shutdown();

                // make sure no outstanding threads are hanging around
                if (!_executorService.awaitTermination(THREADPOOL_SHUTDOWN_TIMEOUT, TimeUnit.SECONDS)) {
                    __log.warn("Problem shutting down ExecutorService - trying harder.");
                    List<Runnable> outstanding = _executorService.shutdownNow();
                    if (outstanding != null && !outstanding.isEmpty()) {
                        __log.warn("Cancelled " + outstanding.size() + " in-flight threads.");
                    }
                }
            } catch (InterruptedException ie) {
                __log.warn("Interrupted during cease(): ", ie);
            }

            // just to be sure..
            _executorService.shutdown();
            __log.info("Receiver ceased.");

            _executorService = null;
            _thread = null;
            _odeContext = null;
            _channel = null;
        }
    }

    /**
     * We periodically poll for input messages, blocking for 1 sec on the accept() call to receive messages. Depending
     * on runFlag status we either try to again poll again or exit.
     */
    public void run() {
        __log.info("Receiver is executing.");

        try {
            _channel = _odeContext.getContext().getDeliveryChannel();
            if (_channel == null) {
                __log.error("No Channel!");
                return;
            }
        } catch (MessagingException ex) {
            __log.error("Error getting channel! ", ex);
            return;
        }

        while (_isRunning.get()) {
            final MessageExchange messageExchange;
            try {
                messageExchange = _channel.accept(TimeUnit.SECONDS.toMillis(ACCEPT_TIMEOUT));
                if (messageExchange != null) {
                    if (__log.isTraceEnabled()) {
                        __log.trace("Got JBI message for endpoint: " + messageExchange.getEndpoint().getEndpointName());
                    }

                    // Even if we got a message exchange, we only run it
                    // if we have not been told to cease.
                    if (_isRunning.get()) {
                        if (__log.isTraceEnabled()) {
                            __log.trace("Scheduling execution of " + messageExchange.getExchangeId());
                        }
                        _executorService.submit(new Runnable() {
                            public void run() {
                                try {
                                    _odeContext._jbiMessageExchangeProcessor.onJbiMessageExchange(messageExchange);
                                } catch (Throwable t) {
                                    __log.error("Error processing JBI message.", t);
                                }
                            }
                        });
                    } else {
                        __log.warn("Skipping processing of message exchange " + messageExchange.getExchangeId()
                                + "; component no longer active.");
                    }
                }
            } catch (MessagingException mex) {
                if (_isRunning.get())
                    __log.warn("Receiver exiting due to MessagingException:", mex);
                else
                    __log.info("Receiver finished.");
                break;
            } catch (Exception ex) {
                if (!_isRunning.get()) {
                    __log.info("Receiver finished.");
                    break;
                }
                __log.warn("Caught unexpected Exception: ", ex);
                return;
            }
        }

        __log.info("Receiver finished.");
    }
}
