package cz.vavru.test.dwr.service;

import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.logging.Logger;

import org.directwebremoting.ScriptSession;
import org.directwebremoting.WebContext;
import org.directwebremoting.WebContextFactory;
import org.directwebremoting.proxy.dwr.Util;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cz.vavru.test.dwr.dao.MessageDao;
import cz.vavru.test.dwr.dao.UserDao;
import cz.vavru.test.dwr.domain.Message;
import cz.vavru.test.dwr.domain.User;
import cz.vavru.test.dwr.service.exception.ChatServiceException;
import cz.vavru.test.dwr.util.DwrWebContextUtil;

/**
 * 
 * @author vlastimil@vavru.cz (http://vavru.cz)
 * 
 */

@Service
public class ChatServiceImpl implements ChatService {
	private static Logger logger = Logger.getLogger(ChatServiceImpl.class.getName());
	private UserDao userDao;
	private MessageDao messageDao;
	public static final String CHAT_USER_SES_ATTR = "CHAT_USER";
	public static final String SCRIPT_CHAT_USER_SES_ATTR = "SCRIPT_CHAT_USER";

	public void setUserDao(UserDao userDao) {
		this.userDao = userDao;
	}

	public void setMessageDao(MessageDao messageDao) {
		this.messageDao = messageDao;
	}

	public User getCurrentUser() throws ChatServiceException {
		WebContext webCtx = WebContextFactory.get();
		User user = (User) webCtx.getHttpServletRequest().getSession(true).getAttribute(
				CHAT_USER_SES_ATTR);

		if (user != null) {
			// put user information in script session context
			webCtx.getScriptSession().setAttribute(SCRIPT_CHAT_USER_SES_ATTR, user);
		}

		return user;
	}

	@Transactional(readOnly = true)
	public List<User> getOnlineUsers() throws ChatServiceException {
		return userDao.getOnlineUsers();
	}

	@Transactional
	public void addMessage(Message message) throws ChatServiceException {
		WebContext webCtx = WebContextFactory.get();
		User currentUser = (User) webCtx.getHttpServletRequest().getSession(true).getAttribute(
				CHAT_USER_SES_ATTR);

		message.setSender(currentUser);
		message.setDate(new Date());

		messageDao.insertMessage(message);

		// let the other guys know that new message arrived
		DwrWebContextUtil dwrUtil = new DwrWebContextUtil(WebContextFactory.get());
		Collection<ScriptSession> scriptSessions = dwrUtil
				.getScriptSessionsToNotifyAboutNewMessage(message);

		logger.info("Sending info about new message to " + scriptSessions.size() + " users");

		Util util = new Util(scriptSessions);
		util.addFunctionCall("addMessage", message);
	}

	@Transactional(readOnly = true)
	public List<Message> getMessages() throws ChatServiceException {
		WebContext webCtx = WebContextFactory.get();
		User currentUser = (User) webCtx.getHttpServletRequest().getSession(true).getAttribute(
				CHAT_USER_SES_ATTR);
		if (currentUser == null) {
			throw new ChatServiceException("User not found in session");
		}

		return messageDao.getMessages(currentUser.getUserId());
	}

	@Transactional
	public User login(String nick) throws ChatServiceException {

		User user = userDao.getUserByNick(nick);
		if (user == null) {
			user = new User();
			user.setNick(nick);
			user.setOnline(true);

			userDao.insertUser(user);
		} else {
			// update online status
			user.setOnline(true);
			userDao.updateUserOnlineStatus(user);
		}

		// put user information in session context
		WebContext webCtx = WebContextFactory.get();
		webCtx.getHttpServletRequest().getSession(true).setAttribute(CHAT_USER_SES_ATTR, user);

		// let other users know that the guy log in
		DwrWebContextUtil dwrUtil = new DwrWebContextUtil(WebContextFactory.get());

		Collection<ScriptSession> scriptSessions = dwrUtil.getAllCurrentPageScriptSessions();

		Util util = new Util(scriptSessions);
		util.addFunctionCall("addUser", user);

		logger.info("Sending info about user login to " + scriptSessions.size() + " users");

		return user;
	}
	
	@Transactional
	public boolean logout() throws ChatServiceException {
		WebContext webCtx = WebContextFactory.get();
		User currentUser = (User) webCtx.getHttpServletRequest().getSession(true).getAttribute(
				CHAT_USER_SES_ATTR);

		if (currentUser != null) {
			// update online status
			currentUser.setOnline(false);
			userDao.updateUserOnlineStatus(currentUser);

			// clear session attribute
			webCtx.getHttpServletRequest().getSession().removeAttribute(CHAT_USER_SES_ATTR);

			// let other users know that the guy log out
			DwrWebContextUtil dwrUtil = new DwrWebContextUtil(WebContextFactory.get());

			Collection<ScriptSession> scriptSessions = dwrUtil.getAllCurrentPageScriptSessions();
			Util util = new Util(scriptSessions);
			util.addFunctionCall("removeUser", currentUser);

			logger.info("Sending info about user logout to " + scriptSessions.size() + " users");

			return true;
		}

		return false;
	}
}
