package brn.swans.route;

import jist.runtime.JistAPI;
import jist.swans.Node;
import jist.swans.mac.MacAddress;
import jist.swans.misc.Message;
import jist.swans.misc.MessageAnno;
import jist.swans.net.NetAddress;
import jist.swans.net.NetInterface;
import jist.swans.net.NetMessage;
import jist.swans.net.NetMessage.Ip;
import jist.swans.route.RouteInterface;

/**
 * DSR routing entity interface.
 */
public interface RouteDsrBrnInterface extends RouteInterface, NetInterface.RawNetHandler {

  /**
   * Called by the discovery component to request transmission of a packet by
   * networking and lower layers.
   *
   * @param msg outgoing packet
   * @param anno
   */
  public void send(NetMessage.Ip msg, int interfaceId, MacAddress nextHop, MessageAnno anno);


  public static interface Discovery extends RouteInterface {

    /**
     * Handle forwarding error
     *
     * @param msg message which could not be forwarded.
     * @param anno the referenced annotation.
     */
    void handleTransmitError(NetMessage.Ip msg, MessageAnno anno);

    /**
     * initialize the discovery module.
     *
     * @param node
     * @param brn
     */
    void setNode(Node node, RouteDsrBrn brn);

    /**
     * Discovery gets the opportunity to handle forwarded packets, for route
     * shortening or rate selection.
     *
     * @param ipMsg the message to be forwarded
     * @param anno the associated annotation
     * @param nextRecipient the address of the next hop
     */
    void forwardPacket(Ip ipMsg, MessageAnno anno, NetAddress nextRecipient);

//    int getMinLinkMetric();

    void setMinLinkMetric(int minLinkMetric);

    void setBitrateFromLinkTable(boolean bitrateFromLinkTable);
  }


  public final static class Dlg implements RouteDsrBrnInterface, JistAPI.Proxiable {
    RouteDsrBrnInterface impl;

    public Dlg(RouteDsrBrnInterface impl) {
      this.impl = impl;
    }

    public RouteDsrBrnInterface getProxy() {
      return (RouteDsrBrnInterface) JistAPI.proxy(this, RouteDsrBrnInterface.class);
    }

    /**
     * @param msg
     * @param lastHop
     * @param anno
     * @see jist.swans.route.RouteInterface#peek(jist.swans.net.NetMessage, jist.swans.mac.MacAddress, jist.swans.misc.MessageAnno)
     */
    public void peek(NetMessage msg, MacAddress lastHop, MessageAnno anno) {
      impl.peek(msg, lastHop, anno);
    }

    /**
     * @param msg
     * @param src
     * @param lastHop
     * @param macId
     * @param dst
     * @param priority
     * @param ttl
     * @param anno
     * @see jist.swans.net.NetInterface.NetHandler#receive(jist.swans.misc.Message, jist.swans.net.NetAddress, jist.swans.mac.MacAddress, byte, jist.swans.net.NetAddress, byte, byte, jist.swans.misc.MessageAnno)
     */
    public void receive(Message msg, NetAddress src, MacAddress lastHop, byte macId, NetAddress dst, byte priority, byte ttl, MessageAnno anno) {
      impl.receive(msg, src, lastHop, macId, dst, priority, ttl, anno);
    }

    /**
     * @param msg
     * @param anno
     * @see jist.swans.route.RouteInterface#send(jist.swans.net.NetMessage, jist.swans.misc.MessageAnno)
     */
    public void send(NetMessage msg, MessageAnno anno) {
      impl.send(msg, anno);
    }

    public void send(Ip msg, int interfaceId, MacAddress nextHop, MessageAnno anno) {
      impl.send(msg, interfaceId, nextHop, anno);
    }

    /**
     * @param msg
     * @param anno
     * @param lastHop
     * @param macId
     * @see jist.swans.net.NetInterface.RawNetHandler#receive(jist.swans.net.NetMessage, jist.swans.misc.MessageAnno, jist.swans.mac.MacAddress, byte)
     */
    public void receive(NetMessage msg, MessageAnno anno, MacAddress lastHop,
        byte macId) {
      impl.receive(msg, anno, lastHop, macId);
    }
  }

}
