package edu.harvard.mgh.lcs.servers.bridge;

import java.util.ArrayList;
import java.util.Iterator;

import org.apache.log4j.Logger;
import org.apache.mina.common.IoHandlerAdapter;
import org.apache.mina.common.IoSession;
import org.apache.mina.filter.LoggingFilter;
import org.apache.mina.filter.codec.ProtocolCodecFactory;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import edu.harvard.mgh.lcs.servers.bridge.dao.BridgeAccountDAO;
import edu.harvard.mgh.lcs.servers.bridge.processors.JabberMessageProcessor;

/**
 * @see edu.harvard.mgh.lcs.servers.bridge.JabberSessionHandler
 * @author Chris Allen csallen@partners.org
 */
public class JabberSessionHandlerImpl extends IoHandlerAdapter implements
		JabberSessionHandler {
	private Logger log;
	private BridgeAccountDAO bridgeAccountDAO;
	private JabberMessageProcessor jabbberMessageProcessor;
	private ProtocolCodecFactory protocolCodecFactory;
	
	private boolean loggedIn = false; 
	
	public JabberSessionHandlerImpl() {
		log = Logger.getLogger(JabberSessionHandlerImpl.class.getName());
	}
	
	/**
	 * @see edu.harvard.mgh.lcs.servers.bridge.JabberSessionHandler#getBridgeAcountDAO()
	 */
	public BridgeAccountDAO getBridgeAcountDAO() {
		return bridgeAccountDAO;
	}

	/**
	 * @see edu.harvard.mgh.lcs.servers.bridge.JabberSessionHandler#setBridgeAcountDAO(edu.harvard.mgh.lcs.servers.bridge.dao.BridgeAccountDAO)
	 */
	public void setBridgeAccountDAO(BridgeAccountDAO bridgeAccountDAO) {
		this.bridgeAccountDAO = bridgeAccountDAO;
	}

	/**
	 * @see edu.harvard.mgh.lcs.servers.bridge.JabberSessionHandler#getJabbberMessageProcessor()
	 */
	public JabberMessageProcessor getJabbberMessageProcessor() {
		return jabbberMessageProcessor;
	}
	
	/**
	 * @see edu.harvard.mgh.lcs.servers.bridge.JabberSessionHandler#getProtocolCodecFactory()
	 */
	public ProtocolCodecFactory getProtocolCodecFactory() {
		return protocolCodecFactory;
	}
	
	/**
	 * @see edu.harvard.mgh.lcs.servers.bridge.JabberSessionHandler#setProtocolCodecFactory(org.apache.mina.filter.codec.ProtocolCodecFactory)
	 */
	public void setProtocolCodecFactory(ProtocolCodecFactory protocolCodecFactory) {
		this.protocolCodecFactory = protocolCodecFactory;
	}
	
	/**
	 * @see edu.harvard.mgh.lcs.servers.bridge.JabberSessionHandler#setJabbberMessageProcessor(edu.harvard.mgh.lcs.servers.bridge.dao.JabbberMessageProcessor)
	 */
	public void setJabbberMessageProcessor(
			JabberMessageProcessor jabbberMessageProcessor) {
		this.jabbberMessageProcessor = jabbberMessageProcessor;
	}
	
	/**
	 * @see edu.harvard.mgh.lcs.servers.bridge.JabberSessionHandler#sessionCreated(org.apache.mina.common.IoSession)
	 */
	public void sessionCreated(IoSession session) throws Exception {
		session.getFilterChain().addLast("protocolFilter",
				new ProtocolCodecFilter(protocolCodecFactory));
		session.getFilterChain().addLast("logger", new LoggingFilter());
	}

	/**
	 * @see edu.harvard.mgh.lcs.servers.bridge.JabberSessionHandler#sessionOpened(org.apache.mina.common.IoSession)
	 */
	public void sessionOpened(IoSession session) {
		// start the authentication...
		login(session);
	}

	/**
	 * @see edu.harvard.mgh.lcs.servers.bridge.JabberSessionHandler#sessionClosed(org.apache.mina.common.IoSession)
	 */
	public void sessionClosed(IoSession session) {

	}

	/**
	 * @see edu.harvard.mgh.lcs.servers.bridge.JabberSessionHandler#messageReceived(org.apache.mina.common.IoSession,
	 *      java.lang.Object)
	 */
	public void messageReceived(IoSession session, Object message) {
		// server only sends ResultMessage. otherwise, we will have to identify
		// its type using instanceof operator.
		String rm = (String) message;
		log.debug("client got this from server: " + rm);
		handlereceived(session, message);
	}

	private void handlereceived(IoSession session, Object message) {
		
		if (!loggedIn) {
			if (message.toString().indexOf("<iq type=\"result\" to") != -1) {
				loggedIn = true;
			}
		}
		log.debug("====== logged in: " + loggedIn + " =======");
		if (loggedIn) {
			log.debug("====== Sending : " + message + " to the proxy. =======");
			String response = jabbberMessageProcessor.process(message);
			if (!response.equals("")) {
				session.write(response);
			}
		}
	}

	/**
	 * @see edu.harvard.mgh.lcs.servers.bridge.JabberSessionHandler#exceptionCaught(org.apache.mina.common.IoSession,
	 *      java.lang.Throwable)
	 */
	public void exceptionCaught(IoSession session, Throwable cause) {
		session.close();
	}

	private void login(IoSession session) {
		ArrayList<java.lang.String> msgs = new ArrayList<java.lang.String>(3);
		msgs
				.add("<?xml version=\"1.0\" ?><stream:stream to=\""
						+ bridgeAccountDAO.getJabberServerHostName()
						+ "\" xmlns=\"jabber:client\" xmlns:stream=\"http://etherx.jabber.org/streams\">\n");
		msgs
				.add("<iq type=\"get\"><query xmlns=\"jabber:iq:auth\"><username>"
						+ bridgeAccountDAO.getUsername()
						+ "</username></query></iq>\n");
		msgs
				.add("<iq type=\"set\"><query xmlns=\"jabber:iq:auth\"><username>"
						+ bridgeAccountDAO.getUsername()
						+ "</username><password>"
						+ bridgeAccountDAO.getPassword()
						+ "</password><resource>"
						+ bridgeAccountDAO.getResource()
						+ "</resource></query></iq>\n");
		msgs
				.add("<presence><status>Online</status><priority>5</priority></presence>");
		Iterator it = msgs.iterator();
		while (it.hasNext()) {
			String msg = (String) it.next();
			session.write(msg);
		}
	}
}
