package jist.swans.trans;

import jist.swans.Node;
import jist.swans.misc.Message;
import jist.swans.misc.MessageAnno;
import jist.swans.misc.MessageEvent;
import jist.swans.net.NetAddress;


/**
 * Base class for all trans.
 *
 * @author kurth
 */
public abstract class AbstractTrans {

  // ////////////////////////////////////////////////
  // Events
  //

  public static class SegmentSentEvent extends MessageEvent {
    public NetAddress src;
    public int srcPort;
    public NetAddress dst;
    public int dstPort;

    public SegmentSentEvent() { super(false); }
    public SegmentSentEvent(int nodeId) { super(nodeId); }

    public void handle(Message msg, MessageAnno anno, NetAddress src, int srcPort,
        NetAddress dst, int dstPort) {
      this.src = src;
      this.srcPort = srcPort;
      this.dst = dst;
      this.dstPort = dstPort;
      super.handle(msg, anno);
    }
  }

  public static class SegmentArrivedEvent extends SegmentSentEvent {

    public SegmentArrivedEvent() { super(); }
    public SegmentArrivedEvent(int nodeId) { super(nodeId); }

    public void handle(Message msg, MessageAnno anno, NetAddress src,
        int srcPort, NetAddress dst, int dstPort) {
      super.handle(msg, anno, src, srcPort, dst, dstPort);
    }
  }

  /** helper to assign globally unique flow ids */
  private static int nextFlowId = 1;

  public static int getNextFlowId() {
    return nextFlowId++;
  }

  // ////////////////////////////////////////////////
  // locals
  //
  public SegmentArrivedEvent segmentArrivedEvent;

  public SegmentSentEvent segmentSentEvent;


  public abstract TransInterface getTransProxy();

  private Node node;

  public AbstractTrans() {
    segmentSentEvent = new SegmentSentEvent();
    segmentArrivedEvent = new SegmentArrivedEvent();
  }

  public Node getNode() {
    return node;
  }

  public void setNode(Node node) {
    this.node = node;
    segmentSentEvent = new SegmentSentEvent(node.getNodeId());
    segmentArrivedEvent = new SegmentArrivedEvent(node.getNodeId());
  }

//  private InetSocketAddress[] flowMap;
//  private Integer[] flowIdMap;

//  public void setFlow(int flowId, NetAddress remoteAddr, int remotePort) {
//    InetSocketAddress[] newFlowMap = new InetSocketAddress[1+(null==flowMap ? 0 : flowMap.length)];
//    Integer[] newFlowIdMap = new Integer[1+(null==flowIdMap ? 0 : flowIdMap.length)];
//    if (null != flowMap) {
//      System.arraycopy(flowMap, 0, newFlowMap, 0, flowMap.length);
//      System.arraycopy(flowIdMap, 0, newFlowIdMap, 0, flowMap.length);
//    }
//    flowMap = newFlowMap;
//    flowIdMap = newFlowIdMap;
//    flowMap[flowMap.length-1] = new InetSocketAddress(remoteAddr.toIP(), remotePort);
//    flowIdMap[flowIdMap.length-1] = new Integer(flowId);
//  }
//
//  protected void assignFlow(MessageAnno anno, NetAddress dst, int dstPort) {
//    for (int i = 0; null != flowMap && i < flowMap.length; i++) {
//      if (flowMap[i].getAddress().equals(dst.toIP())
//          &&flowMap[i].getPort() == dstPort) {
//        anno.put(MessageAnno.ANNO_RTG_FLOWID, flowIdMap[i]);
//        return;
//      }
//    }
//  }

}
