/*
 * Copyright PMEase (c) 2005-2008,
 * Date: Dec 19, 2008
 * Time: 8:46:10 AM
 * All rights reserved.
 * 
 * Revision: $Id$
 */

package com.pmease.quickbuild.plugin.notifier.msn;

import java.util.Map;
import java.util.Set;

import net.sf.jml.Email;
import net.sf.jml.MsnMessenger;
import net.sf.jml.MsnUserStatus;
import net.sf.jml.event.MsnAdapter;
import net.sf.jml.impl.MsnMessengerFactory;

import org.apache.commons.lang.Validate;

import com.pmease.quickbuild.Context;
import com.pmease.quickbuild.Quickbuild;
import com.pmease.quickbuild.QuickbuildException;
import com.pmease.quickbuild.ScriptEngine;
import com.pmease.quickbuild.entitymanager.AlarmManager;
import com.pmease.quickbuild.event.NodeAlertEvent;
import com.pmease.quickbuild.extensionpoint.SimpleNotifier;
import com.pmease.quickbuild.model.Alert;
import com.pmease.quickbuild.model.Build;
import com.pmease.quickbuild.model.User;
import com.pmease.quickbuild.util.Single;
import com.pmease.quickbuild.util.VelocityUtils;

public class MsnNotifier extends SimpleNotifier {
	
	private MsnPlugin plugin;
	
	public MsnNotifier(MsnPlugin plugin) {
		this.plugin = plugin;
	}
	
	private MsnSetting getSetting() {
		return (MsnSetting) plugin.getSetting(true);
	}

	@Override
	public String getName() {
		return "MSN Messenger";
	}

	@Override
	public void notify(Set<User> users, Build build) {
		Context.push(build);
		try {
			MsnNotificationTemplate template = (MsnNotificationTemplate) plugin.findConfigurationSetting(
					Context.getConfiguration(), true);
			if (template == null) {
				ScriptEngine scriptManager = Quickbuild.getInstance(ScriptEngine.class);
				template = (MsnNotificationTemplate) scriptManager.installInterpolator(
						new MsnNotificationTemplate());
			}
			
			if (!users.isEmpty()) {
				String message = VelocityUtils.evalTemplate(template.getContent(), 
						Context.buildEvalContext(template, null));
				
				notify(users, message);
			}
		} finally {
			Context.pop();
		}
	}
	
	private void notify(Set<User> users, String message) {
		if (!users.isEmpty()) {
			synchronized (this) {
				MsnMessenger messenger = MsnMessengerFactory.createMsnMessenger(
						getSetting().getSenderAccount(), getSetting().getSenderPassword()); 
				messenger.getOwner().setInitStatus(MsnUserStatus.ONLINE);
				final Single<Boolean> loginFlag = new Single<Boolean>(false);
				messenger.addListener(new MsnAdapter() {

					@Override
					public void exceptionCaught(MsnMessenger messenger, Throwable throwable) {
						Context.getLogger().error("Error while contacting MSN messenger.", throwable);
						
						synchronized(loginFlag) {
							loginFlag.notify();
						}
					}

					@Override
					public void ownerStatusChanged(MsnMessenger messenger) {
						if (messenger.getOwner().getStatus() == MsnUserStatus.ONLINE) {
							synchronized(loginFlag) {
								loginFlag.setValue(true);
								loginFlag.notify();
							}
						}
					}
					
				});
				
				Context.getLogger().info("Login to MSN messenger...");
				messenger.login();
				synchronized(loginFlag) {
					try {
						loginFlag.wait(10000);
					} catch (InterruptedException e) {
					}
				}
				
				if (!loginFlag.getValue())
					throw new QuickbuildException("Can not login to MSN messenger.");
				
				try {
					for (User user : users) {
						MsnUserSetting userSetting = (MsnUserSetting) plugin.getUserSetting(user, true);
						Validate.notNull(userSetting);
						if (userSetting.getMsnAccount() == null) {
							Context.getLogger().warn("Can not send MSN messenger notification to user '" 
									+ user.getName() + "': MSN messenger account not specified.");
						} else {
							Email email = Email.parseStr(userSetting.getMsnAccount());
							if (email == null) {
								Context.getLogger().error("Can not send MSN messenger notification to user '" 
										+ user.getName() + "': MSN messenger account is invalid.");
							} else {
								// do not wait per message sending as it might be taking a 
								// very long time to send to many users.
								Context.getLogger().debug("Sending MSN message to '" + email + "'...");
								messenger.sendText(Email.parseStr(userSetting.getMsnAccount()), 
										message);
							}
						}
					}
					try {
						// sleep a while to allow messages to be sent.
						Thread.sleep(5000);
					} catch (InterruptedException e) {
					}
				} finally {
					Context.getLogger().info("Logout from MSN messenger.");
					messenger.logout();
				}
			}
		}
	}

	@Override
	public void notify(NodeAlertEvent event) {
		if (event.getAlerts().isEmpty())
			return;
		
		Map<String, Set<User>> map = AlarmManager.instance.getNotifierUsers(this);
		if (map.isEmpty())
			return;
		
		Set<User> users = map.get(getName());
		if (users.isEmpty())
			return;
		
		for (Alert each : event.getAlerts()) {
			notify(users, each.toString());
		}
	}
	
//	@Override
//	public void notify(Set<User> users, Alert alert) {
//		notify(users, alert.toString());
//	}
}
