package messages;

import java.util.*;

public class Port {
  int nextId= 0;
  int served= 0;

  List msgList= new ArrayList();
  int maxsize;

  public Port() { this(100); }

  public Port(int maxsize) {
    this.maxsize= maxsize;
  }

  public synchronized Message receive() {
    try {
      while (msgList.isEmpty())
        wait();
      notifyAll();
      return (Message)msgList.remove(0);
    }
    catch (InterruptedException excp) {
      return null;
    }
  }

  public synchronized Message receive(long delay) {
    try {
      long ini= System.currentTimeMillis();
      long elapsed= 0;
      while (msgList.isEmpty() && elapsed<delay) {
        wait(delay-elapsed);
        elapsed= System.currentTimeMillis()-ini;
      }
      if (msgList.isEmpty())
        return null;
      else {
        notifyAll();
        return (Message)msgList.remove(0);
      }
    }
    catch (InterruptedException excp) {
      return null;
    }
  }

  public void send(Message msg) {
    submit(msg);
    waitReply(msg);
  }

  public synchronized void submit(Message msg) {
    try {
      int id= nextId++;
      while (id>served || msgList.size()>=maxsize)
        wait();
      served++;
      msgList.add(msg);
      msg.isReplied= false;
      notifyAll();
    }
    catch (InterruptedException excp) {
    }
  }

  public void waitReply(Message msg) {
    try {
      synchronized (msg) {
        while (!msg.isReplied)
          msg.wait();
      }
    }
    catch (InterruptedException excp) {
    }
  }

  public void reply(Message msg) {
    synchronized (msg) {
      msg.isReplied= true;
      msg.notifyAll();
    }
  }
}
