// HTTPReceiver.java

package protocol;				// protocol package

import java.util.*;				// import Java utility classes

import support.*;				// import Jasper support classes

/**
  This is the main class for simulation of an HTTP receiver (i.e. server).

  @author	Kenneth J. Turner, Kenneth A. Whyte
  @version	1.4 (9th March 2006, KJT/KAW): initial version
  <br/>		1.5 (24th July 2010, KJT): minor tidying
*/

public class HTTPReceiver implements ProtocolEntity {

  private PDU pduReceived;
  private PDU pduSent;
  private ProtocolEntity peer;
  private Medium medium;
  private String name;

  private int index;				// data/URL index for move

  public HTTPReceiver(Medium m, String name) {
    this.name = name;
    medium = m;
    initialise();
  }

  public String getName() {
    return(name);
  }

  public void initialise() {
    pduReceived = null;
    index = 1;
  }

  public Vector<String> getServices() {
    int url, moved;				// given/moved URL number
    Vector<String> list = new Vector<String>();
    String sdu;					// SDU

    if (pduReceived != null &&			// PDU not null?
	 (sdu = pduReceived.sdu) != null &&	// SDU not null?
	    sdu.startsWith("URL")) {		// URL and number?
      try {					// parse number
	url = Integer.parseInt(sdu.substring(3)); // get URL number
      }
      catch (NumberFormatException exc) {	// incorrect number
	url = 0;				// set default URL number
      }
    }
    else					// not URL
      url = 0;					// set zero URL number
    if (pduReceived != null && pduReceived.type.equals("GET")) {
      if (url == index)				// URL same as local one?
	moved = index + 1;			// use next local for move
      else					// URL differs from local
	moved = index;				// use local for move
      list.addElement("200 OK(DATA" + url + ") - send requested data");
      list.addElement("301 MOVED(URL" + moved + ") - report moved URL");
      list.addElement("400 ERROR(CODE) - report requested data unavailable");
    }
    if (pduReceived != null && pduReceived.type.equals("HEAD")) {
      if (url == index)				// URL same as local one?
	moved = index + 1;			// use next local for move
      else					// URL differs from local
	moved = index;				// use local for move
      list.addElement
	("200 OK(HEADER" + url + ") - send requested header");
      list.addElement
	("301 MOVED(URL" + moved + ") - report moved URL");
      list.addElement
	("400 ERROR(CODE) - report requested header unavailable");
    }
    if (pduReceived != null && pduReceived.type.equals("POST")) {
      list.addElement("200 OK - acknowledge receipt of data");
      list.addElement("400 ERROR(CODE) - report data not posted");
    }
    if (pduReceived != null && pduReceived.type.equals("PUT")) {
      list.addElement("200 OK - acknowledge receipt of data");
      list.addElement("400 ERROR(CODE) - report data not posted");
    }
    return(list);
  }

  public Vector<ProtocolEvent> performService(String s) {
    Vector<ProtocolEvent> events = new Vector<ProtocolEvent>();
    pduSent = null;
    String data, url;
    int startIndex, endIndex;

    startIndex = s.indexOf ('(') + 1;
    endIndex = s.indexOf (')');
    if (s.startsWith ("200")) {
      if (startIndex < endIndex)		// any data?
	data = s.substring(startIndex, endIndex);
      else					// no data
	data = "";
      transmitPDU(new PDU("200 OK", data), peer);
    }
    if (s.startsWith ("301")) {
      url = s.substring(startIndex, endIndex);	// get URL
      index++;					// update local index
      transmitPDU(new PDU("301 MOVED", url), peer);
    }
    if (s.startsWith("400")) {
      data = s.substring(startIndex, endIndex); // get data
      transmitPDU(new PDU("400 ERROR", data), peer);
    }
    if (pduSent != null) {
      events.addElement(new ProtocolEvent(ProtocolEvent.TRANSMIT, pduSent));
      events.addElement(new ProtocolEvent(ProtocolEvent.RECEIVE, pduSent));
    }
    return(events);
  }

  public Vector<ProtocolEvent> receivePDU(PDU pdu) {
    pduReceived = pdu;
    return(new Vector<ProtocolEvent>());
  }

  public void setPeer(ProtocolEntity peer) {
    this.peer = peer;
  }

  public void transmitPDU(PDU pdu, ProtocolEntity dest) {
    pdu.setSource(this);
    pdu.setDestination(dest);
    pduSent = pdu;
    peer.receivePDU(pdu);
    pduReceived = null;
  }

}
