//----------------------------BEGIN LICENSE----------------------------
/* 
 * Willow : the Open Source WorkFlow Project
 * Distributable under GNU LGPL license by gun.org
 *
 * Copyright (C) 2004-2010 huihoo.org 
 * Copyright (C) 2004-2010  ZosaTapo <dertyang@hotmail.com> 
 * 
 * ====================================================================
 * Project Homepage : http://www.huihoo.org/willow
 * Source Forge     : http://sourceforge.net/projects/huihoo
 * Mailing list     : willow@lists.sourceforge.net 
 */
//----------------------------END  LICENSE----------------------------

package org.huihoo.willow.desktop;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.rmi.MarshalledObject;
import java.rmi.RemoteException;
import java.util.Hashtable;

import org.huihoo.willow.Globals;
import org.huihoo.willow.Manager;
import org.huihoo.willow.RealmDatabase;
import org.huihoo.workflow.desktop.CommunicationException;
import org.huihoo.workflow.desktop.WorkflowDesktop;
import org.huihoo.workflow.server.WorkflowSession;
import org.huihoo.workflow.usermodel.WorkflowParticipant;

public class DesktopImplUtils
{
	public static DesktopService getDesktopService(String host, int port, Hashtable myProps)
		throws CommunicationException
	{
		String hostKey = getDesktopKey(host, port);

		Socket socket = null;
		try
		{
			InetAddress localAddr = null;
			int localPort = 0;
			String localAddrStr = (String) myProps.get(WorkflowDesktop.DESKTOP_IIOP_ADDRESS);
			String localPortStr = (String) myProps.get(WorkflowDesktop.DESKTOP_IIOP_PORT);
			if (localAddrStr != null)
			{
				localAddr = InetAddress.getByName(localAddrStr);
			}
			if (localPortStr != null)
			{
				localPort = Integer.parseInt(localPortStr);
			}
			socket = new Socket(host, port, localAddr, localPort);
		}
		catch (IOException e)
		{
			CommunicationException ex = new CommunicationException("Failed to connect to desktop service" + hostKey);
			ex.setRootCause(e);
			throw ex;
		}

		try
		{
			//Get stub from naming server

			BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
			ObjectInputStream in = new ObjectInputStream(bis);
			MarshalledObject stub = (MarshalledObject) in.readObject();
			DesktopService serviceDesktop = (DesktopService) stub.get();
			try
			{
				socket.close();
			}
			catch (Exception ex)
			{
				;
			}

			return serviceDesktop;
		}
		catch (Exception e1)
		{
			CommunicationException ex = new CommunicationException("Failed to connect to desktop service" + hostKey);
			ex.setRootCause(e1);
			throw ex;
		}
	}

	public static DesktopService getDesktopService(String privoderURL, Hashtable myProps) throws CommunicationException
	{
		if (privoderURL == null)
		{
			privoderURL = WorkflowDesktop.REMOTE_DESKTOP_PROTOCOL + "://localhost:" + Globals.DESKTOP_SERVICE_PORT;
		}

		String server = getURLServer(privoderURL);
		if (server != null)
		{
			int port = Globals.DESKTOP_SERVICE_PORT;
			String host = null;

			int colon = server.indexOf(':');
			if (colon < 0)
			{
				host = server;
			}
			else
			{
				host = server.substring(0, colon).trim();
				try
				{
					port = Integer.parseInt(server.substring(colon + 1).trim());
				}
				catch (Exception ex)
				{
					// Use default;
				}

			} //~end if (colon < 0)

			return getDesktopService(host, port, myProps);
		}

		return null;
	}

	public static String getURLService(String str)
	{
		String URLScheme = getURLScheme(str);
	
		if (WorkflowDesktop.LOCAL_DESKTOP_PROTOCOL.equals(URLScheme))
		{
			String schemePrefix = URLScheme + ":";
			int schemeLength = 0;
			if (str.startsWith(schemePrefix))
			{
				schemeLength = schemePrefix.length();
			}

			if (schemeLength > 0)
			{
				str = str.substring(schemeLength);
				if (str.length() > 0)
				{
					while (str.charAt(0) == '/')
					{
						if (str.length() == 1)
						{
							return null;
						}
						str = str.substring(1);

					} //~end if (str.length() > 0)

					int pos = str.indexOf("/");
					if (pos > 0)
					{
						str = str.substring(0, pos);
					}

					return str;

				} //~end if (str.length() > 0)

			} //~end if(schemeLength > 0)

		} //~end if(WorkflowDesktop.LOCAL_DESKTOP_PROTOCOL.equals(URLScheme))

		return null;
	}

	public static String getURLServer(String str)
	{
		String URLScheme = getURLScheme(str);

		if (WorkflowDesktop.REMOTE_DESKTOP_PROTOCOL.equals(URLScheme))
		{
			String schemePrefix = URLScheme + ":";
			int schemeLength = 0;
			if (str.startsWith(schemePrefix))
			{
				schemeLength = schemePrefix.length();
			}

			if (schemeLength > 0)
			{
				str = str.substring(schemeLength);
				if (str.length() > 0)
				{
					while (str.charAt(0) == '/')
					{
						if (str.length() == 1)
						{
							return null;
						}
						str = str.substring(1);

					} //~end if (str.length() > 0)

					int pos = str.indexOf("/");
					if (pos > 0)
					{
						str = str.substring(0, pos);
					}

					return str;

				} //~end if (str.length() > 0)

			} //~end if(schemeLength > 0)

		} //~end if(WorkflowDesktop.REMOTE_DESKTOP_PROTOCOL.equals(URLScheme))

		return null;
	}

	public static String getURLScheme(String str)
	{	
		if(str == null)
		{
			return null;
		}
		
		int colon_posn = str.indexOf(':');
		int slash_posn = str.indexOf('/');

		if (colon_posn > 0 && (slash_posn == -1 || colon_posn < slash_posn))
		{
			return str.substring(0, colon_posn);
		}
		return null;
	}

	public static String getDesktopKey(String host, int port)
	{
		return ""+host + ":" + port;
	}

	public static WorkflowSession authenticate(
		Manager manager,
		RealmDatabase realmDatabase,
		String username,
		String password)
		throws RemoteException
	{
		if(manager == null || realmDatabase == null)
		{
			throw new IllegalArgumentException();
		}
		
		WorkflowParticipant participant = realmDatabase.authenticate(username, password);
		if (participant == null)
		{
			throw new RemoteException("login Desktop Service unsuccessfully.username=" + username + ",password=" + password);
		}

		WorkflowSession session = manager.createSession();
		session.setParticipant(participant);

		return session;
	}
}
