package beacon;

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

/** 
  The BClient class provides a standard interface to location services.
  Any user interface planning to publish locations should do so through
  the BClient.  Handles authentication.
**/

public class BClient {
  String serv;
  String pw, alias;

  BClient(){
  }

  /**
    Set the location server to talk to

    @param serverURL This is a string which specifies the URL for the location server
  **/
  public void setServer(String serverURL){
    serv = serverURL;
  }

  /**
    Used to specify the alias and password this client should use

    @param a The alias
    @param p The password
   */
  public void setIdentity(String a, String p){
    alias = a;
    pw = p;
  }

  /**
    Publish a location at the server

    @param port This is the port for default communications
   */
  public String setLocation(int port){
    String response = toServer(serv,"SETLOC?user="+URLEncoder.encode(alias)+
			       "&port="+URLEncoder.encode(""+port));
    return response;
  }

  /**
    Remove a published location from the server

    @param port The port of the location to be removed
   */
  public String removeLocation(int port){
    String response = toServer(serv,"REMLOC?user="+URLEncoder.encode(alias)+
			       "&port="+URLEncoder.encode(""+port));
    return response;
  }

  /**
    Register for an alias

    @param contact This is the email address to which the initial
    password will be sent
    */
  public void register(String contact){
    String response = toServer(serv,"REGISTER?user="+URLEncoder.encode(alias)+
			       "&contact="+URLEncoder.encode(contact));
  }


  /**
    Don't do anything other than tell the server the user still exists
    (but don't publish a location)
   */
  public void expiryPing(){
    String response = toServer(serv,"EXPING?user="+URLEncoder.encode(alias));
  }

  /**
    Indicate that the a location continues to be valid

    @param port The port of the location
   */
  public void connectionPong(int port){
    String response = toServer(serv,"CONPONG?user="+URLEncoder.encode(alias)+
			       "&port="+URLEncoder.encode(""+port));
  }


  /**
    Change the password
    @param newpw The new password
    */
  public String changePassword(String newpw){
    String response = toServer(serv,"CHPW?user="+URLEncoder.encode(alias)
			       +"&newpw="+URLEncoder.encode(newpw));
    return response;
  }

  /**
    Request the location of another alias

    @param oalias The alias that a location is desired for
    */

  public String requestLocation(String oalias){
    String response = toServer(serv,"REQLOC?user="+URLEncoder.encode(oalias));
    return response;
  }

  String toServer(String s, String rq){
    String resp;
    String fullR = new String("");
    String r = new String(s+rq);
    BufferedReader rr;
    URLConnection uc;
    try {
      URL u = new URL(r);
      uc = u.openConnection();
      uc.setRequestProperty("BHA", authenticationToken(rq,pw));
      rr = new BufferedReader(new InputStreamReader(uc.getInputStream()));
      while((resp = rr.readLine()) != null){
	fullR = new String(fullR+" "+resp);
      }
      rr.close();
    } catch (Exception e){ System.out.println("Sl: "+e);}
    return fullR;
  }

  String authenticationToken(String req, String pass){
    byte hash[];
    String tohex[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
		      "a", "b", "c", "d", "e", "f"};
    try {
      MessageDigest md5 = MessageDigest.getInstance("MD5");
      String digest = new String(hash = md5.digest((new String(req+pass)).getBytes()));
      String digeststr = new String ("");
      for(int ct=0;ct<hash.length;ct++){
	int val;
	if(hash[ct] < 0)
	  val = 256+((int)hash[ct]);
	else
	  val = (int) hash[ct];
	digeststr = new String(digeststr+(tohex[val/16])
			       +(tohex[val%16]));
      }
      return digeststr;
    } catch (Exception e){
      System.out.println("Dammit: "+e);
      return new String("");
    }
  }
}
