package kraft.gateway;
import  kraft.TermInString;


// a socket-based gateway supporting multiple remote sites
//
// Author:	K.Y. Hui
// Date:	26 June 1998
// Version:	1.20
//		Changed to cater for single-quotation in Prolog term
//

import java.io.*;

public class GatewayTest
{
static boolean verbose=false;

public static void main(String[] argv)
	{
	String config_file=null;			//config file name
	String linda_host=null;				//linda host
	int linda_port=0;				//linda port
	String myname=null;				//my KRAFT name
	int myport=0;					//my socket port to use
//	boolean verbose=false;				//default verbose flag off
	SocketGateway gate;				//the socket gateway object that does the real job
	GatewayMap known_map=null;			//entries from config file

	//
	// process command line arguments
	//
	try	{
		int i=0;
		while (i<argv.length)
			{
			if (argv[i].equals("-c"))
				config_file=argv[++i];			//get config file
			else if (argv[i].equals("-lh"))
				linda_host=argv[++i];			//get host
			else if (argv[i].equals("-lp"))
				linda_port=Integer.parseInt(argv[++i]);	//get port no.
			else if (argv[i].equals("-mn"))
				myname=argv[++i];			//get myname
			else if (argv[i].equals("-mp"))
				myport=Integer.parseInt(argv[++i]);	//get my port to use
			else if (argv[i].equals("-v"))
				verbose=true;
			else throw new Exception();			//unknown parameter
			i++;
			}
		} catch (Exception e)
			{
			System.err.println("usage: java GatewayTest -c config_file -lh linda_host -lp linda_port -mn my_name -mp my_port");
			System.exit(0);
			}

	//
	// if config file name is specified, process it
	//
	if (config_file!=null)
		try	{
			BufferedReader file_reader;
			String raw_line,line;
			TermInString term;

			known_map=new GatewayMap();
			//
			// open config file and process content
			//
			file_reader=new BufferedReader(new FileReader(config_file));	//open config file
			while ((raw_line=file_reader.readLine())!=null)			//read 1 line
				{
				if ((line=filtered_prolog_string(raw_line))!=null)
					{
					//
					// create a Prolog term
					//
					try	{
						term=new TermInString(line);
						} catch (Exception e)
							{
							print_message("illegal line:"+raw_line);
							throw new Exception();
							}
	
					//
					// check for different configuration terms
					//
	
					//
					// myname/1
					//
					if (term.functor.equals("myname"))			//myname
						{
						if (term.arity!=1)
							{
							print_message("myname/1 malformed:"+raw_line);
							throw new Exception();
							}
						if (myname==null)				//only if not specified in command line
							myname=term.argument(1);		//get my name
						}
					//
					// myport/1
					//
					else if (term.functor.equals("myport"))
						{
						if (term.arity!=1)
							{
							print_message("myport/1 malformed:"+raw_line);
							throw new Exception();
							}
						if (myport==0)					//only if not specified in command line
							myport=Integer.parseInt(new TermInString(term.argument(1)).functor);	//get port as int
						}
					//
					// linda_server/2
					//
					else if (term.functor.equals("linda_server"))
						{
						if (term.arity!=2)
							{
							print_message("linda_server/2 malformed:"+raw_line);
							throw new Exception();
							}
						if (linda_host==null)					//if not specified in command line
							linda_host=new TermInString(term.argument(1)).functor;			//get host string
						if (linda_port==0)					//if not specified in command line
							linda_port=Integer.parseInt(new TermInString(term.argument(2)).functor);	//get port as int
						}
					//
					// route/2
					//
					else if (term.functor.equals("route"))
						{
						String site,host;
						int port;

						if (term.arity!=3)
							{
							print_message("route/3 malformed:"+raw_line);
							throw new Exception();
							}
						print_message("trying to add:"+term.term);
						site=new TermInString(term.argument(1)).functor;
						host=new TermInString(term.argument(2)).functor;
						port=Integer.parseInt(new TermInString(term.argument(3)).functor);
						known_map.add_gateway(site,host,port);			//add to map
						}
					}
				}
			file_reader.close();						//close config file
			} catch (FileNotFoundException e)
				{
				System.err.println("config file not found");
				System.exit(1);
				}
			catch (IOException e)
				{
				System.err.println("config file I/O error");
				System.exit(2);
				}
			catch (Exception e)
				{
				System.err.println("error in parsing config file:"+config_file);
				System.exit(3);
				}

	if (linda_host==null || linda_port==0 || myname==null || myport==0)
		{
		System.err.println("ERROR: not enough parameter specified");
		System.exit(4);
		}

	print_message("Socket-based Linda gateway");
	print_message("--------------------------");
	print_message("linda host:"+linda_host);
	print_message("linda port:"+linda_port);
	print_message("my name:"+myname);
	print_message("my port:"+myport);

	//
	// ready to start gateway
	//
	try	{
		gate=new SocketGateway(linda_host,linda_port,myname,myport,known_map,verbose);
		gate.work();
		} catch (Exception e)
			{
			print_message("ERROR in creating/running gateway");
			}
	}


//
// filter out comments and useless char in a string
// returning a potential Prolog string
//
private static String filtered_prolog_string(String s)
	{
	int i=0;
	boolean single_quote=false;
	boolean double_quote=false;

	try	{
		if (s.charAt(i)=='%')
			return(null);			//it is a comment
		while (i<s.length())
			{
			switch (s.charAt(i))
				{
				case '.':	if (!single_quote && !double_quote)		//end of prolog clause
							return(s.substring(0,i));		//return substring without the '.'
				case '\\':	i++;		//escape char
						break;
				case '\'':	single_quote=!single_quote;
						break;
				case '"':	if (!single_quote)
							double_quote=!double_quote;
						break;
				default:	break;
				}
			i++;
			}
		return(null);			//reach the end without hitting a '.'
		} catch (Exception e)
			{
			return(null);
			}
	}


//
// print message depending on verbose flag
//
private static void print_message(String s)
	{
	if (verbose)
		System.out.println(s);
	}
}

