package com.rndchina.aisin.chat.handler;

import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.logging.MdcInjectionFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.rndchina.aisin.chat.model.ChatCommand;

public class MinaServerHandler2 extends IoHandlerAdapter {
	private final static Logger LOGGER = LoggerFactory
			.getLogger(MinaServerHandler2.class);

	// 当前所有用户的session
	private final Set<IoSession> sessions = Collections
			.synchronizedSet(new HashSet<IoSession>());
	// 当前所有用户
	private final Set<String> users = Collections
			.synchronizedSet(new HashSet<String>());

	private final Map<String, IoSession> currentLoginUsers = Collections
			.synchronizedMap(new HashMap<String, IoSession>());

	@Override
	public void exceptionCaught(IoSession session, Throwable cause) {
		LOGGER.warn("Unexpected exception.", cause);
		// Close connection when unexpected exception is caught.
		// session.close(true);
	}

	@Override
	public void messageReceived(IoSession session, Object message) {
		Logger log = LoggerFactory.getLogger(MinaServerHandler2.class);
		log.info("received: <<<< " + message);
		String theMessage = (String) message;
		String[] result = theMessage.split(" ", 2);
		String theCommand = result[0];

		try {

			ChatCommand command = ChatCommand.valueOf(theCommand);

			String user = (String) session.getAttribute("user");

			switch (command.toInt()) {

			case ChatCommand.QUIT:// 推出
				session.write("QUIT OK");
				session.close(true);
				break;
			case ChatCommand.LOGIN:// 登录
				if (user != null) {// 重复登录
					session.write("LOGIN ERROR user " + user
							+ " already logged in.");
					return;
				}

				if (result.length == 2) {
					user = result[1];
				} else {
					session.write("LOGIN ERROR invalid login command.");
					return;
				}

				// check if the username is already used
				if (users.contains(user)) {
					session.write("LOGIN ERROR the name " + user
							+ " is already used.");
					return;
				}

				// Allow all users
				users.add(user);
				sessions.add(session);
				session.setAttribute("user", user);

				currentLoginUsers.put(user, session);

				MdcInjectionFilter.setProperty(session, "user", user);

				session.write("LOGIN OK");
				broadcast("The user " + user + " has joined the chat session.");
				break;

			case ChatCommand.BROADCAST:

				if (result.length == 2) {
					broadcast(user + ": " + result[1]);
				}
				break;
			default:
				LOGGER.info("Unhandled command: " + command);
				break;
			}

		} catch (IllegalArgumentException e) {
			LOGGER.debug("Illegal argument", e);
		}
	}

	public void broadcast(String message) {
		synchronized (sessions) {
			for (IoSession session : sessions) {
				if (session.isConnected()) {
					session.write("BROADCAST OK " + message);
				}
			}
		}
	}

	@Override
	public void sessionClosed(IoSession session) throws Exception {
		String user = (String) session.getAttribute("user");
		users.remove(user);
		sessions.remove(session);
		currentLoginUsers.remove(user);

		broadcast("The user " + user + " has left the chat session.");
	}

	public boolean isChatUser(String name) {
		return users.contains(name);
	}

	public int getNumberOfUsers() {
		return users.size();
	}

	public void kick(String name) {
		synchronized (sessions) {
			for (IoSession session : sessions) {
				if (name.equals(session.getAttribute("user"))) {
					session.close(true);
					break;
				}
			}
		}
	}

}
