/*
 * 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.log4j.net;

import org.apache.log4j.plugins.Plugin;
import org.apache.log4j.plugins.Receiver;
import org.apache.log4j.spi.LoggerRepository;

import java.io.IOException;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * SocketHubReceiver receives a remote logging event on a configured
 * socket and "posts" it to a LoggerRepository as if the event was
 * generated locally. This class is designed to receive events from
 * the SocketHubAppender class (or classes that send compatible events).
 * <p>
 * <p>Once the event has been "posted", it will be handled by the
 * appenders currently configured in the LoggerRespository.
 *
 * @author Mark Womack
 * @author Ceki G&uuml;lc&uuml;
 * @author Paul Smith (psmith@apache.org)
 */
public class SocketHubReceiver
    extends Receiver implements SocketNodeEventListener, PortBased {

    /**
     * Default reconnection delay.
     */
    static final int DEFAULT_RECONNECTION_DELAY = 30000;

    /**
     * Host.
     */
    protected String host;

    /**
     * Port.
     */
    protected int port;
    /**
     * Reconnection delay.
     */
    protected int reconnectionDelay = DEFAULT_RECONNECTION_DELAY;

    /**
     * The MulticastDNS zone advertised by a SocketHubReceiver
     */
    public static final String ZONE = "_log4j_obj_tcpconnect_receiver.local.";

    /**
     * Active.
     */
    protected boolean active = false;

    /**
     * Connector.
     */
    protected Connector connector;

    /**
     * Socket.
     */
    protected SocketNode13 socketNode;

    /**
     * Listener list.
     */
    private final List listenerList = Collections.synchronizedList(new ArrayList());

    private boolean advertiseViaMulticastDNS;
    private ZeroConfSupport zeroConf;

    /**
     * Create new instance.
     */
    public SocketHubReceiver() {
        super();
    }

    /**
     * Create new instance.
     *
     * @param h host
     * @param p port
     */
    public SocketHubReceiver(final String h,
                             final int p) {
        super();
        host = h;
        port = p;
    }

    /**
     * Create new instance.
     *
     * @param h    host
     * @param p    port
     * @param repo logger repository
     */
    public SocketHubReceiver(final String h,
                             final int p,
                             final LoggerRepository repo) {
        super();
        host = h;
        port = p;
        repository = repo;
    }

    /**
     * Adds a SocketNodeEventListener to this receiver to be notified
     * of SocketNode events.
     *
     * @param l listener
     */
    public void addSocketNodeEventListener(final SocketNodeEventListener l) {
        listenerList.add(l);
    }

    /**
     * Removes a specific SocketNodeEventListener from this instance
     * so that it will no  longer be notified of SocketNode events.
     *
     * @param l listener
     */
    public void removeSocketNodeEventListener(
        final SocketNodeEventListener l) {
        listenerList.remove(l);
    }

    /**
     * Get the remote host to connect to for logging events.
     *
     * @return host
     */
    public String getHost() {
        return host;
    }

    /**
     * Configures the Host property, this will require activateOptions
     * to be called for this to take effect.
     *
     * @param remoteHost address of remote host.
     */
    public void setHost(final String remoteHost) {
        this.host = remoteHost;
    }

    /**
     * Set the remote host to connect to for logging events.
     * Equivalent to setHost.
     *
     * @param remoteHost address of remote host.
     */
    public void setPort(final String remoteHost) {
        host = remoteHost;
    }

    /**
     * Get the remote port to connect to for logging events.
     *
     * @return port
     */
    public int getPort() {
        return port;
    }

    /**
     * Set the remote port to connect to for logging events.
     *
     * @param p port
     */
    public void setPort(final int p) {
        this.port = p;
    }

    /**
     * The <b>ReconnectionDelay</b> option takes a positive integer
     * representing the number of milliseconds to wait between each
     * failed connection attempt to the server. The default value of
     * this option is 30000 which corresponds to 30 seconds.
     * <p>
     * <p>Setting this option to zero turns off reconnection
     * capability.
     *
     * @param delay milliseconds to wait or zero to not reconnect.
     */
    public void setReconnectionDelay(final int delay) {
        int oldValue = this.reconnectionDelay;
        this.reconnectionDelay = delay;
        firePropertyChange("reconnectionDelay", oldValue, this.reconnectionDelay);
    }

    /**
     * Returns value of the <b>ReconnectionDelay</b> option.
     *
     * @return value of reconnection delay option.
     */
    public int getReconnectionDelay() {
        return reconnectionDelay;
    }

    /**
     * Returns true if the receiver is the same class and they are
     * configured for the same properties, and super class also considers
     * them to be equivalent. This is used by PluginRegistry when determining
     * if the a similarly configured receiver is being started.
     *
     * @param testPlugin The plugin to test equivalency against.
     * @return boolean True if the testPlugin is equivalent to this plugin.
     */
    public boolean isEquivalent(final Plugin testPlugin) {
        if (testPlugin != null && testPlugin instanceof SocketHubReceiver) {
            SocketHubReceiver sReceiver = (SocketHubReceiver) testPlugin;

            return (port == sReceiver.getPort()
                && host.equals(sReceiver.getHost())
                && reconnectionDelay == sReceiver.getReconnectionDelay()
                && super.isEquivalent(testPlugin));
        }
        return false;
    }

    /**
     * Sets the flag to indicate if receiver is active or not.
     *
     * @param b new value
     */
    protected synchronized void setActive(final boolean b) {
        active = b;
    }

    /**
     * Starts the SocketReceiver with the current options.
     */
    public void activateOptions() {
        if (!isActive()) {
            setActive(true);
            if (advertiseViaMulticastDNS) {
                zeroConf = new ZeroConfSupport(ZONE, port, getName());
                zeroConf.advertise();
            }

            fireConnector(false);
        }
    }

    /**
     * Called when the receiver should be stopped. Closes the socket
     */
    public synchronized void shutdown() {
        // mark this as no longer running
        active = false;

        // close the socket
        try {
            if (socketNode != null) {
                socketNode.close();
                socketNode = null;
            }
        } catch (Exception e) {
            getLogger().info("Excpetion closing socket", e);
            // ignore for now
        }

        // stop the connector
        if (connector != null) {
            connector.interrupted = true;
            connector = null;  // allow gc
        }
        if (advertiseViaMulticastDNS) {
            zeroConf.unadvertise();
        }
    }

    /**
     * Listen for a socketClosedEvent from the SocketNode. Reopen the
     * socket if this receiver is still active.
     *
     * @param e exception not used.
     */
    public void socketClosedEvent(final Exception e) {
        // if it is a non-normal closed event
        // we clear the connector object here
        // so that it actually does reconnect if the
        // remote socket dies.
        if (e != null) {
            connector = null;
            fireConnector(true);
        }
    }

    /**
     * Fire connectors.
     *
     * @param isReconnect true if reconnect.
     */
    private synchronized void fireConnector(final boolean isReconnect) {
        if (active && connector == null) {
            getLogger().debug("Starting a new connector thread.");
            connector = new Connector(isReconnect);
            connector.setDaemon(true);
            connector.setPriority(Thread.MIN_PRIORITY);
            connector.start();
        }
    }

    /**
     * Set socket.
     *
     * @param newSocket new value for socket.
     */
    private synchronized void setSocket(final Socket newSocket) {
        connector = null;
        socketNode = new SocketNode13(newSocket, this);
        socketNode.addSocketNodeEventListener(this);

        synchronized (listenerList) {
            for (Object aListenerList : listenerList) {
                SocketNodeEventListener listener =
                    (SocketNodeEventListener) aListenerList;
                socketNode.addSocketNodeEventListener(listener);
            }
        }
        new Thread(socketNode).start();
    }

    public void setAdvertiseViaMulticastDNS(boolean advertiseViaMulticastDNS) {
        this.advertiseViaMulticastDNS = advertiseViaMulticastDNS;
    }

    public boolean isAdvertiseViaMulticastDNS() {
        return advertiseViaMulticastDNS;
    }

    /**
     * The Connector will reconnect when the server becomes available
     * again.  It does this by attempting to open a new connection every
     * <code>reconnectionDelay</code> milliseconds.
     * <p>
     * <p>It stops trying whenever a connection is established. It will
     * restart to try reconnect to the server when previpously open
     * connection is droppped.
     *
     * @author Ceki G&uuml;lc&uuml;
     */
    private final class Connector extends Thread {

        /**
         * Interruption status.
         */
        boolean interrupted = false;
        /**
         * If true, then delay on next iteration.
         */
        boolean doDelay;

        /**
         * Create new instance.
         *
         * @param isReconnect true if reconnecting.
         */
        public Connector(final boolean isReconnect) {
            super();
            doDelay = isReconnect;
        }

        /**
         * Attempt to connect until interrupted.
         */
        public void run() {
            while (!interrupted) {
                try {
                    if (doDelay) {
                        getLogger().debug("waiting for " + reconnectionDelay
                            + " milliseconds before reconnecting.");
                        sleep(reconnectionDelay);
                    }
                    doDelay = true;
                    getLogger().debug("Attempting connection to " + host);
                    Socket s = new Socket(host, port);
                    setSocket(s);
                    getLogger().debug(
                        "Connection established. Exiting connector thread.");
                    break;
                } catch (InterruptedException e) {
                    getLogger().debug("Connector interrupted. Leaving loop.");
                    return;
                } catch (java.net.ConnectException e) {
                    getLogger().debug("Remote host {} refused connection.", host);
                } catch (IOException e) {
                    getLogger().debug("Could not connect to {}. Exception is {}.",
                        host, e);
                }
            }
        }
    }

    /**
     * This method does nothing.
     *
     * @param remoteInfo remote info.
     */
    public void socketOpened(final String remoteInfo) {

        // This method does nothing.
    }
}
