/*
 * Created on 26 oct. 2005
 *
 */
package archean.util;

import java.io.IOException;
import java.net.SocketAddress;

import org.apache.mina.common.ByteBuffer;
import org.apache.mina.common.CloseFuture;
import org.apache.mina.common.ConnectFuture;
import org.apache.mina.common.IdleStatus;
import org.apache.mina.common.IoConnector;
import org.apache.mina.common.IoFilterAdapter;
import org.apache.mina.common.IoFilterChain;
import org.apache.mina.common.IoHandler;
import org.apache.mina.common.IoSession;
import org.apache.mina.common.IoFilter.NextFilter;
import org.apache.mina.common.IoFilter.WriteRequest;
import org.apache.mina.util.SessionLog;

/**
 * A simple auto reconnection filter. Retry to reconnect a closed session until
 * it's connected. A delay between the reconnection is avaible as parameter.
 * 
 * @author Julien Vermillard - Archean
 * 
 */
public class ReconnectionFilter extends IoFilterAdapter {

	/**
	 * @param delay
	 *            delay in mili-seconds between 2 reconnections
	 * @param connector
	 *            the IoConnector for reconnect
	 * @param protocol
	 *            handler provided to use for the connection
	 */
	public ReconnectionFilter(int delay, IoConnector connector, IoHandler handler, SocketAddress address,
			SocketAddress localAddress) {
		this.delay = delay;
		this.connector = connector;
		this.handler = handler;
		this.address = address;
		this.localAddress = localAddress;

	}

	private int delay;

	private IoConnector connector;

	private IoHandler handler;

	private SocketAddress address;

	private SocketAddress localAddress;

	public void sessionClosed(NextFilter nextFilter, IoSession session) {
		// fire a connection retrying Thread
		ConnectionThread connectionThread = new ConnectionThread();
		connectionThread.start();
		nextFilter.sessionClosed(session);
	}


	private class ConnectionThread extends Thread {
		private ConnectionThread() {
			super();
		}

		public void run() {
			for (;;) {
				ConnectFuture future = connector.connect(address, localAddress, handler);
				future.join();
				if(future.isConnected())
					return;
				synchronized (this) {
					try {
						sleep(delay);
					} catch (InterruptedException e) {
					}
				}
			}
		}
	}
}
