package edu.ucsb.cs.nws.nwsprotocol;

import java.io.*;
import java.net.*;


/**
 * The NwsProxy class implements the protocol specific to NWS
 * Proxy -- forecasting requests.
 */


// TRB 8/2004
public class NwsProxy extends NwsHost {


  protected static final int GET_FORECASTS = NwsMessage.PROXY_FIRST_MESSAGE;
  protected static final int GOT_FORECASTS = GET_FORECASTS + 1;
  protected static final int PROXY_FAILED = NwsMessage.PROXY_LAST_MESSAGE;


  /** See the constructor for NwsHost. */
  	public NwsProxy(String hostName, int hostPort, boolean keepOpen)
	{
    		super(hostName, hostPort, keepOpen);
  	}


  /** See the constructor for NwsHost. */
  	public NwsProxy(String hostName, int hostPort)
	{
    		super(hostName, hostPort);
  	}


  /** See the constructor for NwsHost. */
  	public NwsProxy(Socket s) {
    		super(s);
  	}



  /**
   * Requests that the proxy generate a series of forecast collections
   */
  	public NwsForecastAPI.ForecastCollection[]
  	getAllForecasts(String resource, String opts, String[] hosts) throws Exception
	{
		byte[][] allBytes = {null, null};
		int i;
		NwsForecastAPI.ForecastCollection[] returnValue;


		if(resource == null) {
			System.err.println("NwsProxy.getAllForecasts: null " +
					   "resource parameter");
			return null;
		}
		if(hosts == null) {
			System.err.println("NwsProxy.getAllForecasts: null " +
					   "hosts parameter");
			return null;
		}

		/* Build the data payload - first the resource and a NULL,
		   then the options and a NULL, and finally each host
		   separated by a null.
		*/
		allBytes[0] = new CString(resource).toBytes();

		if(opts != null) {
			allBytes[1] = new CString(opts).toBytes();
		}
		else {
			allBytes[1] = new CString(1,"\0").toBytes();
		}
		allBytes[0] = NwsMessage.concatenateBytes(allBytes);

		for(i=0;i<hosts.length;i++) {
			allBytes[1] = new CString(hosts[i]).toBytes();
			allBytes[0] = NwsMessage.concatenateBytes(allBytes);
		}

	
		messagePrelude();
		NwsMessage.send(connection, GET_FORECASTS, allBytes[0]);
		returnValue = (NwsForecastAPI.ForecastCollection [])NwsMessage.receive(connection, this);
		messagePostlude();
		return returnValue;
  	}


  /** See NwsMessage. */
  public Object receive(int message,
                        DataInputStream stream,
                        int dataLength) throws Exception {
    if(message == GOT_FORECASTS) {
	NwsForecastAPI.ForecastCollection[] coll = 
		new NwsForecastAPI.ForecastCollection[stream.readInt()];
	for(int i = 0;i<coll.length;i++) {
		coll[i] = new NwsForecastAPI.ForecastCollection(stream);
	}
      	return coll;
    }
    else {
      return super.receive(message, stream, dataLength);
    }
  }


  /**
   * The main() method for this class is a small test program that takes a
   */
  public static void main(String[] args) {
	String[] hosts = {"carbon.cs.ucsb.edu","crow.cs.ucsb.edu"};
	final int MAE_FORECAST =
		NwsForecastAPI.ForecastCollection.MAE_FORECAST;
    	final int MSE_FORECAST = NwsForecastAPI.ForecastCollection.MSE_FORECAST;

	if(args.length < 2) {
		System.err.print("Usage: NwsProxy <proxyhost> <resource>");
		System.err.println(" <host1> <host2> ... <hostn>");
		System.exit(0);
	}
	if(args.length > 2) {
		hosts = new String[args.length - 2];
		for(int i=2;i<args.length;i++) {
			hosts[i-2] = new String(args[i]);
		}
	}
    try {
      NwsProxy proxy = new NwsProxy(args[0], 8888);
      NwsForecastAPI.ForecastCollection[] forecasts =
        proxy.getAllForecasts(args[1], null,hosts);

	if(forecasts == null) {
		System.out.println("No results returned.");
		System.exit(0);
	}

	System.out.println("Returning " + forecasts.length + " results");
      	for(int i = 0; i < forecasts.length; i++) {
        	NwsForecastAPI.ForecastCollection forecast = forecasts[i];
        	System.out.println(
          		(int)forecast.measurement.timeStamp + " " +
          		forecast.measurement.measurement + " " +
          		forecast.forecasts[MSE_FORECAST].forecast + " " +
          		forecast.forecasts[MSE_FORECAST].error + " "); /* +
          		methods[forecast.forecasts[MSE_FORECAST].methodUsed].replace(' ', '_'));*/
      		}
    	} catch(Exception x) { 
		System.err.println(x.toString()); 
		x.printStackTrace();
    	}
  }


}
