/*******************************************************************************
 * Copyright (c) 2005, 2006 Intel Corporation.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Andy Kaylor, Intel - Initial implementation
 *
 * $Id: AgentHandler.java,v 1.1 2006/01/24 18:35:19 akaylor Exp $
 *
 *******************************************************************************/ 

package SampleAgentHandler;

import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Enumeration;

import org.eclipse.hyades.internal.execution.local.common.ControlMessage;
import org.eclipse.hyades.internal.execution.local.common.CustomCommand;
import org.eclipse.hyades.internal.execution.local.control.Agent;
import org.eclipse.hyades.internal.execution.local.common.CommandElement;
import org.eclipse.hyades.internal.execution.local.control.AgentControllerUnavailableException;
import org.eclipse.hyades.internal.execution.local.control.AgentFactory;
import org.eclipse.hyades.internal.execution.local.control.AgentListener;
import org.eclipse.hyades.internal.execution.local.control.CommandHandler;
import org.eclipse.hyades.internal.execution.local.control.InactiveAgentException;
import org.eclipse.hyades.internal.execution.local.control.InactiveProcessException;
import org.eclipse.hyades.internal.execution.local.control.NoSuchApplicationException;
import org.eclipse.hyades.internal.execution.local.control.Node;
import org.eclipse.hyades.internal.execution.local.control.NodeFactory;
import org.eclipse.hyades.internal.execution.local.control.NotConnectedException;
import org.eclipse.hyades.internal.execution.local.control.ProcessActiveException;
import org.eclipse.hyades.internal.execution.local.control.ProcessFactory;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.swt.widgets.Display;
import org.eclipse.hyades.internal.execution.local.control.Process;
import org.eclipse.hyades.internal.execution.security.LoginFailedException;
import org.eclipse.hyades.internal.execution.security.SecureConnectionRequiredException;
import org.eclipse.hyades.internal.execution.security.UntrustedAgentControllerException;
import org.eclipse.hyades.trace.ui.HyadesConstants;
import org.eclipse.hyades.trace.ui.UIPlugin;

/**
 * @author akaylor
 *
 * To change the template for this generated type comment go to
 * Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
 */
public class AgentHandler
{
	/**
	 * @author akaylor
	 *
	 * To change the template for this generated type comment go to
	 * Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
	 */
	public class VTAgentListener implements AgentListener
	{

		/* (non-Javadoc)
		 * @see org.eclipse.hyades.internal.execution.local.control.AgentListener#agentActive(org.eclipse.hyades.internal.execution.local.control.Agent)
		 */
		public void agentActive(Agent agent)
		{
			// TODO Auto-generated method stub
			
		}

		/* (non-Javadoc)
		 * @see org.eclipse.hyades.internal.execution.local.control.AgentListener#agentInactive(org.eclipse.hyades.internal.execution.local.control.Agent)
		 */
		public void agentInactive(Agent agent)
		{
			// TODO Auto-generated method stub
			
		}

		/* (non-Javadoc)
		 * @see org.eclipse.hyades.internal.execution.local.control.AgentListener#error(org.eclipse.hyades.internal.execution.local.control.Agent, java.lang.String, java.lang.String)
		 */
		public void error(Agent agent, String errorId, String errorMessage)
		{
			// TODO Auto-generated method stub
			
		}

		/* (non-Javadoc)
		 * @see org.eclipse.hyades.internal.execution.local.control.AgentListener#handleCommand(org.eclipse.hyades.internal.execution.local.control.Agent, org.eclipse.hyades.internal.execution.local.common.CommandElement)
		 */
		public void handleCommand(Agent agent, CommandElement command)
		{
			int commandTag = (int)command.getTag();
			switch ( commandTag )
			{
				case (int) org.eclipse.hyades.internal.execution.local.common.Constants.RA_CUSTOM_COMMAND:
					CustomCommand customCommand = (CustomCommand)command;
					CustomRunnable mbHandler = new CustomRunnable( customCommand.getData());
					Display.getDefault().asyncExec(mbHandler);
					System.out.println( customCommand.getData() );
					break;
			}
		}

	}
	/**
	 * @author akaylor
	 *
	 * To change the template for this generated type comment go to
	 * Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
	 */
	public class CustomRunnable implements Runnable
	{
		private String m_message;

		CustomRunnable( String message )
		{
			m_message = message;
		}
	
		/* (non-Javadoc)
		 * @see java.lang.Runnable#run()
		 */
		public void run()
		{
			MessageDialog.openInformation(
				SampleAgentHandlerPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getShell(),
				"The agent says...",
				m_message);
		}
	}
	private Process m_agentProcess;
	private Agent    m_agent;
	private Node     m_node;
	private boolean  m_isConnected;
	
	public AgentHandler()
	{
		m_node         = null;
		m_agent        = null;
		m_agentProcess = null;
		m_isConnected  = false;
	}
	
	public boolean isConnected()
	{
		return m_isConnected;
	}
	
	public boolean connect()
	{
		if ( m_isConnected )
			return true;
			
		if ( m_node == null )
		{
			try
			{
				m_node = NodeFactory.createNode(InetAddress.getLocalHost().getHostName());
			}
			catch (UnknownHostException e1)
			{
				// TODO Auto-generated catch block
				e1.printStackTrace();
				return false;
			}
		}
		
		try
		{
			if ( m_node != null )
			{
				// Get the port number for the local connection
				IPreferenceStore store = UIPlugin.getDefault().getPreferenceStore();
				int fPortNumber = 10002; // Integer.parseInt(store.getString(HyadesConstants.LOCALHOST_PORT));
				
				// Connect to the local RAC
				m_node.connect(fPortNumber);
			}
		}
		catch (SecureConnectionRequiredException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		} 
		catch (UntrustedAgentControllerException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		} 
		catch (LoginFailedException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		} 
		catch (AgentControllerUnavailableException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}
		
		// If we didn't catch anything, the connect succeeded
		m_isConnected = true;
		return true;
	}
	
	public boolean findAgent()
	{
		if ( !m_isConnected )
			return false;
			
		// Get a list of the processes the RAC knows about
		try
		{
			Enumeration processList = m_node.listProcesses();
			while( processList.hasMoreElements() )
			{
				Process process = (Process) processList.nextElement();
				Enumeration agents = process.listAgents();
		
				while ( agents.hasMoreElements() )
				{
					Agent agent = (Agent) agents.nextElement();
					if ( ( agent.getName().equals("CommandDump") ) &&
						 ( agent.getType().equals("VTTest") ) )
					{
						m_agent = agent;
						m_agentProcess = process;
						return true;
					}
				}			
			}
		}
		catch (NotConnectedException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return false;
	}

	public boolean startMonitoring()
	{
		// If we found an agent, attach to it
		if ( m_isConnected && (m_agent != null) )
		{
			try
			{
				if ( m_agent.isActive() ) 
				{
					VTDataProcessor dataProcessor = new VTDataProcessor();

					VTAgentListener  agentListener = new VTAgentListener();
					m_agent.addAgentListener( agentListener );				
					m_agent.attach();
					m_agent.startMonitoring( dataProcessor );
				}
				else
				{
					m_agent.addAgentListener( new AgentListener() {

						public void agentActive(Agent agent) {
							try
							{
								VTDataProcessor dataProcessor = new VTDataProcessor();

								VTAgentListener  agentListener = new VTAgentListener();
								agent.addAgentListener( agentListener );				
								agent.attach();
								agent.startMonitoring( dataProcessor );
							}
							catch (InactiveAgentException e)
							{
								// TODO Auto-generated catch block
								e.printStackTrace();
							}
							catch (InactiveProcessException e)
							{
								// TODO Auto-generated catch block
								e.printStackTrace();
							}
						}

						public void agentInactive(Agent arg0) {
							// TODO Auto-generated method stub
							
						}

						public void error(Agent arg0, String arg1, String arg2) {
							// TODO Auto-generated method stub
							
						}

						public void handleCommand(Agent arg0, CommandElement arg1) {
							// TODO Auto-generated method stub
							
						}} );
				}
				
				return true;
			}
			catch (InactiveAgentException e)
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			catch (InactiveProcessException e)
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		return false;
	}
	
	public boolean sayHello()
	{
		if ( !m_isConnected || (m_agent == null) )
			return false;
			
		ControlMessage message=new ControlMessage();

		CustomCommand  command = new CustomCommand();
		command.setAgentName( m_agent.getName() );
		try
		{
			command.setProcessId( Long.parseLong(m_agent.getProcess().getProcessId()) );
		}
		catch (NumberFormatException e1)
		{
			// TODO Auto-generated catch block
			e1.printStackTrace();
			return false;
		}
		catch (InactiveProcessException e1)
		{
			// TODO Auto-generated catch block
			e1.printStackTrace();
			return false;
		}
		command.setData( "Hello Agent" );
		message.appendCommand( command );
		
		try
		{
			CommandHandler myResponseHandler = new CommandHandler() 
				{
					public void incommingCommand(Node node, CommandElement command)
					{  
						int commandTag = (int)command.getTag();
						switch ( commandTag )
						{
							case (int) org.eclipse.hyades.internal.execution.local.common.Constants.RA_CUSTOM_COMMAND:
								CustomCommand customCommand = (CustomCommand)command;
								CustomRunnable mbHandler = new CustomRunnable( customCommand.getData());
								Display.getDefault().asyncExec(mbHandler);
								System.out.println( customCommand.getData() );
								break;
						}
					}
				};
			m_node.getConnection().sendMessage(message, myResponseHandler);
		}
		catch (IOException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}
		
		return true;
	}

	/**
	 * @return
	 */
	public boolean launchAgent()
	{
		if ( !m_isConnected )
			return false;
			
		Process p = ProcessFactory.createProcess( m_node, "VTDumpAgent");
		
		Agent a = AgentFactory.createAgent( p, "DumpAgent", "RACTest" );
		
		try
		{
			p.launch();
			m_agentProcess = p;
			
			Enumeration agents = p.listAgents();
			while ( agents.hasMoreElements() )
			{
				Agent agent = (Agent) agents.nextElement();
				if ( ( agent.getName().equals("DumpAgent") ) &&
					 ( agent.getType().equals("RACTest") ) )
				{
					m_agent = agent;
					return true;
				}
			}			
		}
		catch (ProcessActiveException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}
		catch (NotConnectedException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}
		catch (NoSuchApplicationException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}
			
		return false;
	}

	/**
	 * @return
	 */
	public boolean stopMonitoring()
	{
		try
		{
			m_agent.stopMonitoring();
			m_agent.detach();
		}
		catch (InactiveAgentException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}
		catch (InactiveProcessException e1)
		{
			// TODO Auto-generated catch block
			e1.printStackTrace();
			return false;
		}
		
		return true;
	}

	/**
	 * @return
	 */
	public boolean disconnect()
	{
		m_agent = null;
		m_node = null;
		m_isConnected = false;
		
		return true;
	}

	/**
	 * 
	 */
	public void killAgent()
	{
		try
		{
			m_node.killProcess( m_agentProcess );
			m_agentProcess = null;
		}
		catch (InactiveProcessException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		catch (NotConnectedException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
