//Title:       StageAgent
//Version:	   1.7
//Author:      Stuart Lowry & Scott Palmateer
//Company:     Science Applications International Corporation
//Description: OAA Wrapper for using the light weight web server "AdvantaServer"

//package saic.oaa2;
import com.sri.oaa2.com.*;
import com.sri.oaa2.lib.*;
import com.sri.oaa2.icl.*;
import java.util.*;
import java.io.*;

public class StageAgent
{
	static String oaaName = "oaa_StageAgent";
	static String oaaSolvables = "[stage(Stagername,File,Ref),unstage(Stagername,Ref,File),shutdown(X)]";
	static String Version = "1.5";
	int httpport = 4444;

	String stageDir = "/tmp";
	String userName = System.getProperty("user.name");
	// This is the name where the AdvantaServer is running.
	//String httphost = System.getProperty("system.name");
	String httphost = "localhost";
	DataStore store;
	Hashtable stagedFiles = new Hashtable();

	public StageAgent(String[] args)
	{
		try  
		{
			Init(args);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void Init(String[] args) throws Exception
	{
		LibOaa oaa = new LibOaa(new LibCom(new LibComTcpProtocol(),args));
		System.out.println("StageAgent starting...");
		if (!oaa.getComLib().comConnect("parent",IclUtils.icl("tcp(A,B)"),
			(IclList)IclUtils.icl("[]")))
		{
			System.out.println("Could not connect to facilitator");
			return;
		}
		if (!oaa.oaaRegister("parent", oaaName, 
			IclUtils.icl(oaaSolvables), (IclList)IclUtils.icl("[]")))
		{
				System.out.println("Could not register");
				return;
		}
		oaa.oaaRegisterCallback("oaa_AppDoEvent",
			new OAAEventListener() {
				public boolean doOAAEvent(IclTerm goal, IclList params, IclList answers) {
					return oaaAppDoEvent(goal, params, answers);
			}
		});

		// make the StageDir if necessary
		try {
			new File(stageDir).mkdir();
		} catch (Throwable t) {
			System.out.println("warning: mkdir of : "+stageDir+" failed. It probably alredy exists.");
		}

		// create data store
		store = new DataStore(userName,stageDir);

		// set up the companion HTTP server
		AdvantaServer httpserver = new AdvantaServer(httpport, store);
		httpserver.start();

		oaa.oaaReady(true);
	}


	public boolean oaaAppDoEvent(IclTerm goal, IclList param, IclList answers)
	{
		boolean result = true;
		if (goal.iclStr().toString().equals("stage"))
		{
			System.out.println("got a stage request");
			result = goStageFile(goal,answers);
			return result;
		} else
		if (goal.iclStr().toString().equals("unstage"))
		{
			System.out.println("got a unstage request");
			result = goUnstageFile(goal,answers);
			return result;
		} else
		if (goal.iclStr().toString().equals("shutdown"))
		{
			System.out.println("cleaning up tmp files on exit...");
			System.exit(0);
		}

	return false;
	}

	/**
	* Unstage a file, given a host name, and a reference, Return a filename that
	* is the unstaged file. 
	*
	**/

	private boolean goUnstageFile(IclTerm goal, IclList answers)
	{
		String func = goal.iclStr().toString();
		IclTerm stager = goal.iclNthTerm(1);
		IclTerm ref = goal.iclNthTerm(2);
		boolean result = false;
		IclString tmp = new IclString(ref.toString());
		tmp.iclStRemoveQuotes();
		String bareref = tmp.toString();
		int x = bareref.indexOf("=");
		bareref = bareref.substring(x+1);
		String filename = store.getFile(bareref);
		if (filename != null) {
			String res = func +"('" + userName +"','" + tmp.toString() + "','" + filename + "')";
			IclTerm temp = IclUtils.icl(res);
			answers.iclAddToList(temp, true);
			result = true;
		}
		return result;
	}

	/**
	* This method takes a file, and stages it (makes it ready for retrieval via HTTP),
	* and returns a URL reference with which the contents of the staged file can
	* be retrieved.
	*
	**/
	private boolean goStageFile(IclTerm goal, IclList answers)
	{
		String func = goal.iclStr().toString();
		IclTerm stager = goal.iclNthTerm(1);
		IclTerm filename = goal.iclNthTerm(2);
		IclTerm refparam = goal.iclNthTerm(3);
		String stFilename = null;
		boolean result = false;

		IclString tmp = new IclString(filename.toString());
		tmp.iclStRemoveQuotes();
		stFilename = tmp.toString();

		File f = new File(tmp.toString());

		if (!f.exists() || !f.isFile() || !f.canRead()){
			System.out.println("cannot stage file:" + filename.toString());
			result = false;
		} else
		if (IclUtils.iclIsList(refparam)) 
		{
			for (int i=0; i < refparam.iclNumTerms(); i++)
			{
				String bareref = store.putFile(stFilename);
				String ref = "http://" + httphost + ":" + httpport + "/get?ref="+bareref;
				String res = func + "('" + userName + "','" + stFilename + "','"+ ref + "')";
				IclTerm temp = IclUtils.icl(res);
				answers.iclAddToList(temp,true);
			}
		result = true;
	} else
	{
			String bareref = store.putFile(stFilename);
			String ref = "http://" + httphost + ":" + httpport + "/get?ref="+bareref;
			String res = func + "('" + userName + "','" + stFilename + "','"+ ref + "')";
			IclTerm temp = IclUtils.icl(res);
			answers.iclAddToList(temp,true);
			result = true;
	}
	return result;
	}
	
	public static void main(String[] args)
	{
		new StageAgent(args);
	}

}

