package ws.prova.jade;

/*
 * Copyright (C) 2002-2004 Jacek Gomoluch</a>
 * Copyright (C) 2002-2007 <a href="mailto:a.kozlenkov@city.ac.uk">Alex Kozlenkov</a>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

import jade.core.Profile;
import jade.core.ProfileImpl;
import jade.core.Runtime;
import jade.core.Specifier;
import jade.wrapper.AgentContainer;
import jade.wrapper.AgentController;
import ws.prova.RMessage;
import ws.prova.reagent;

/**
 * JADE exchange module
 * wraps up the Jade platform and Jade agents in a
 * single class which allows message exchange
 * via http-mtp and iiop-mtp (only http-mtp is now working).
 * <p/>
 * <p>Title: Prova</p>
 * <p>Description: JADE message exchange module </p>
 * <p>Copyright: Copyright (C) 2002-2007</p>
 * <p>Company: City University, London, United Kingdom</p>
 *
 * @author Jacek Gomoluch
 * @author Alex Kozlenkov
 * @version 2.0 <25 March 2007>
 */
public class jade_exchange {

	private reagent prova;
	private AgentController myAgent;

	private Runtime rt;
	private Profile pMain;
	private AgentContainer mc;
	private AgentContainer ac;

	/**
	 * This constructor starts a whole jade platform at port 'port'.
	 * It creates an agent. NOTE: The port is just a logical port.
	 *
	 * @param machine   String
	 * @param http_port externally visible port (we normally use 7778)
	 * @param port      int
	 * @param agent     String
	 * @param _prova    reagent
	 */
	public jade_exchange(String machine, String http_port, int port, String agent, /*String password,*/ reagent _prova) {
		prova = _prova;
		try {
			// Get a hold on JADE runtime
			rt = Runtime.instance();
			// Exit the JVM when there are no more containers around
			rt.setCloseVM(true);
			String address = machine + ':' + http_port;
			if (JADEPlatformTest.isRMIRunning(machine, "1101") == null
					&& JADEPlatformTest.isJADERunning(machine, "1101") == null) {
				// JADE platform already running
				// Try to attach to an existing platform
				Profile pAgent = new ProfileImpl(false);
				pAgent.setParameter("port", Integer.toString(port));
				pAgent.setParameter("local-port", Integer.toString(port));
//				pAgent.setParameter("container","false");
				ac = rt.createAgentContainer(pAgent);
				// add http-mtp
				jade.util.leap.List l = pAgent.getSpecifiers(Profile.MTPS);
				Specifier s = new Specifier();
				s.setClassName("jade.mtp.http.MessageTransportProtocol");
//				l.remove(0); // delete the Corba IIOP
				s.setArgs(new Object[]{new String("http://" + address + "/acc")});
				l.add(0, s); // insert HTTP MTP
				// list all supported protocols
				for (int i = 0; i < l.size(); i++) {
					System.out.println("Supported protocol " + (i + 1) + ": " +
							l.get(i));
				}
//				System.out.println("Launching the rma agent on the main container ...");
//				AgentController rma = ac.createNewAgent("rma", "jade.tools.rma.rma", new Object[0]);
//				rma.start();
				// create an agent
				myAgent = ac.createNewAgent(agent,
						CustomAgent.class.getName(), new Object[]{
							prova
						});
				myAgent.start();
			} else {
				// Launch a complete platform, create a default Profile
				pMain = new ProfileImpl(null, port, null);

				//add http-mtp
				jade.util.leap.List l = pMain.getSpecifiers(Profile.MTPS);
				if (l.size() == 0) {
					Specifier s = new Specifier();
					s.setClassName("jade.mtp.http.MessageTransportProtocol");
//					l.remove(0); // delete the Corba IIOP
					s.setArgs(new Object[]{new String("http://" + address + "/acc")});
					l.add(0, s); // insert HTTP MTP
				}
				// list all supported protocols
				for (int i = 0; i < l.size(); i++) {
					System.out.println("Supported protocol " + (i + 1) + ": " +
							l.get(i));
				}
				System.out.println("Launching a whole in-process platform..." +
						pMain);
				try {
					mc = rt.createMainContainer(pMain);
				} catch (Throwable t) {
					System.out.println("Problem");
				}
				// create an agent
				myAgent = mc.createNewAgent(agent,
						CustomAgent.class.getName(), new Object[]{
							prova
						});
				myAgent.start();
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

	/**
	 * This constructor assumes that a platform is already running.
	 * It just starts an agent
	 *
	 * @param agent  String
	 * @param _prova reagent
	 */
	public jade_exchange(String agent, /*String password,*/ reagent _prova) {
		prova = _prova;
		try {
			myAgent = mc.createNewAgent(agent, CustomAgent.class.getName(), new Object[]{prova});
			myAgent.start();
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

	/**
	 * Shutdown the platform
	 */
	public void shutdown() {
		Runtime.instance().shutDown();
	}

	/**
	 * Send an RMessage to an agent ('name') at location 'address'
	 *
	 * @param name    String
	 * @param address String
	 * @param rmsg    RMessage
	 */
	public synchronized void send(String name, String address, RMessage rmsg) {

		try {

			// put into the O2A queue of the agent
			myAgent.putO2AObject(new Object[]{name, address, rmsg, this}, AgentController.ASYNC);
			synchronized (this) {
				try {
					this.wait();
				} catch (Exception e) {
				}
			}

		} catch (Exception e) {
			System.err.println("send: " + e);
			e.printStackTrace();
		}

	}

/*
    public static void main(String args[]) {

        reagent _prova = new reagent();

        // create a platform and an agent
        // 1099 is just the logical port (the actual port is 7778)
        jade_exchange je1 = new jade_exchange( 1099, "agent1", _prova );

        // create an agent, but no platform
        jade_exchange je2 = new jade_exchange( "agent2", _prova );

        try{

		    // Wait for 5 seconds
	   	    Thread.sleep(5000);

		} catch (Exception e) {
          System.err.println("send: "+e);
          e.printStackTrace();
        }

        // send a RMessage from agent1 to agent2
        RMessage rmessage = new RMessage("Test");
        je1.send("agent2@mercury:1099/JADE",null,rmessage);

    }
*/
}


/*
JADE notes:

(1)
 HTTP protocol was compiled with keepalive always false
 see MessageTransportProtocol
 numKA = 0;

This has avoided reconnection problems
*/
