// SMTPReceiver.java	(C) K. J. Turner, P. K. Johnson	04/03/06

// Simple Mail Transfer Protocol receiver (server)

package protocol;

import java.util.Vector;
import support.*;

public class  SMTPReceiver implements ProtocolEntity {
  private PDU pduReceived;
  private ProtocolEntity peer;
  private Medium medium;
  private String name;
  private PDU pduSent;

  final static String clientData = "DATA";
  final static String clientFrom = "MAIL FROM: sender";
  final static String clientHello = "HELO client";
  final static String clientMail = "Mail message";
  final static String clientQuit = "QUIT";
  final static String clientRecipient = "RCPT TO: recipient";
  final static String invalidRecipient = "550 Recipient invalid";
  final static String invalidSender = "550 Sender invalid";
  final static String okRecipient = "250 Recipient OK";
  final static String okSender = "250 Sender OK";
  final static String serverAccept = "250 Message accepted";
  final static String serverClosing = "221 Server Closing";
  final static String serverHello = "250 Server hello to client";
  final static String serverReady = "220 Server ready";
  final static String serverSend = "354 Send mail";
  final static String tcpConnect = "TCP connect";
  final static String tcpDisconnect = "TCP disconnect";

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

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

  public Vector<String> getServices() {
    Vector<String> list = new Vector<String>();
    String pduType;
    if (pduReceived != null) {			// non-null PDU received?
      pduType = pduReceived.type;		// get PDU type
      if (pduType.equals(clientData))		// got client data?
	list.addElement(serverSend);		// reply server send
      else if (pduType.startsWith(clientFrom)) { // got sender?
	list.addElement(okSender);		// reply sender OK
	list.addElement(invalidSender);		// reply sender invalid
      }
      else if (pduType.equals(clientHello))	// got client hello?
	list.addElement(serverHello);		// reply server hello
      else if (pduType.equals(clientMail))	// got client mail message?
	list.addElement(serverAccept);		// reply server accept
      else if (pduType.equals(clientQuit))	// got client quit?
	list.addElement(serverClosing);		// reply server closing
      else if (pduType.startsWith(clientRecipient)) { // got recipient?
	list.addElement(okRecipient);		// reply recipient OK
	list.addElement(invalidRecipient);	// reply recipient invalid
      }
      else if (pduType.equals(tcpConnect))	// got TCP disconnect?
	list.addElement(serverReady);		// reply server ready?
						// no action on TCP disconnect
    }
    return(list);
  }

  public void initialise() {
    pduReceived = null;
  }

  public Vector<ProtocolEvent> performService(String s) {
    Vector<ProtocolEvent> events = new Vector<ProtocolEvent>();
    if (s.equals(invalidRecipient))		// send recipient invalid?
      transmitPDU(new PDU(invalidRecipient), peer);
    else if (s.equals(invalidSender)) 		// send sender invalid?
      transmitPDU(new PDU(invalidSender), peer);
    else if (s.equals(okRecipient))		// send recipient OK?
      transmitPDU(new PDU(okRecipient), peer);
    else if (s.equals(okSender))		// send sender OK?
      transmitPDU(new PDU(okSender), peer);
    else if (s.equals(serverAccept))		// send message accepted?
      transmitPDU(new PDU(serverAccept), peer);
    else if (s.equals(serverClosing))		// send server closing?
      transmitPDU(new PDU(serverClosing), peer);
    else if (s.equals(serverHello))		// send server hello?
      transmitPDU(new PDU(serverHello), peer);
    else if (s.equals(serverReady))		// send server ready?
      transmitPDU(new PDU(serverReady), peer);
    else if (s.equals(serverSend))		// send server send?
      transmitPDU(new PDU(serverSend), peer);
    if (pduSent != null) {			// PDU to send?
      events.addElement(new ProtocolEvent(ProtocolEvent.TRANSMIT, pduSent));
      events.addElement(new ProtocolEvent(ProtocolEvent.RECEIVE, pduSent));
    }
    pduSent = null;				// nullify just in case
    return(events);
  }

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

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

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

}
