/*
 * Created on 2004-9-4
 *
 * To change the template for this generated file go to
 * Window - Preferences - Java - Code Generation - Code and Comments
 */
package org.huihoo.willow.client;

import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.huihoo.willow.naming.WillowContext;
import org.huihoo.willow.naming.ContextFactory;
import org.huihoo.willow.session.SessionManager;

import workflow.WorkflowException;
import workflow.client.WorkflowClient;
import workflow.store.RealmDatabase;
import workflow.store.UserDatabase;
import workflow.wfmc.pm.Participant;
import workflow.services.WorkflowService;
import workflow.services.WorkflowSession;

/**
 * @author reic
 *
 * To change the template for this generated type comment go to
 * Window - Preferences - Java - Code Generation - Code and Comments
 */
public class WorkflowClientImpl implements WorkflowClient
{
	private static Log log = LogFactory.getLog(WorkflowClientImpl.class);

	protected Hashtable env;

	protected WorkflowSession session;

	//-----------------------------------------------------------constructor
	public WorkflowClientImpl(Hashtable environment) throws WorkflowException
	{
		init(environment);
	}

	public WorkflowSession getSession() throws WorkflowException
	{
		return session;
	}

	public void disconnect() throws WorkflowException
	{
		session.invalidate();
	}

	public WorkflowService findService(String service_name) throws WorkflowException
	{
		Participant participant=session.getParticipant();
		String userid=participant.getUUID();
		String password=participant.getPassword();
	  
		WillowContext context = ContextFactory.getWillowContext();	
		WorkflowService workflowService = context.lookup(service_name);
				
		if (workflowService != null)
		{
			if (!authenticate(workflowService, userid, password))
			{
				throw new WorkflowException(
					"login workflow service unsuccessfully.userid="
						+ userid
						+ ",password="
						+ password);
			}
		}
		
		return workflowService;
	}

	public WorkflowService[] findServices() throws WorkflowException
	{
		WillowContext context=ContextFactory.getWillowContext();				
		Participant participant=session.getParticipant();
		String userid=participant.getUUID();
		String password=participant.getPassword();
				
		Vector vector = new Vector(0);		
		Enumeration enum=context.list();
		while(enum.hasMoreElements())
		{
			WorkflowService workflowService=(WorkflowService)enum.nextElement();
			if(authenticate(workflowService,userid,password))
			{
				vector.add(workflowService);
			}
		}
		int size=vector.size();
		WorkflowService[] result=new WorkflowService[size];
		for(int i=0;i<size;++i)
		{
			result[i]=(WorkflowService)vector.elementAt(i);
		}
		return result;
	}

	private void init(Hashtable refEnv) throws WorkflowException
	{
		if (refEnv == null)
		{
			refEnv = new Hashtable();
		}

		this.env = (Hashtable) refEnv.clone();

		String username = (String) env.get(WorkflowClient.SECURITY_PRINCIPAL);
		String password = (String) env.get(WorkflowClient.SECURITY_CREDENTIALS);

		WillowContext context = ContextFactory.getWillowContext();
		SessionManager manager = null;
		RealmDatabase realmDatabase = null;
		Participant participant = null;

		manager = (SessionManager) context.getGlobalSessionManager();
		realmDatabase = (RealmDatabase) context.getGlobalRealmDatabase();
		participant = realmDatabase.authenticate(username, password);

		if (participant == null)
		{
			throw new WorkflowException(
				"login workflow engine unsuccessfully.username=" + username + ",password=" + password);
		}

		this.session = manager.createSession();
		this.session.setParticipant(participant);	
	}
	
	private boolean authenticate(
		WorkflowService workflowService,
		String userid,
		String password)
		throws WorkflowException
	{		
		UserDatabase userDatabase = workflowService.getUserDatabase();
		Participant user = userDatabase.findParticipant(userid);

		if (user != null && user.getPassword().equals(password))
		{
			return true;
		}

		return false;
	}
}
