//////////////////////////////////////////////////
// JIST (Java In Simulation Time) Project
// Timestamp: <MacInterface.java Tue 2004/04/06 11:32:16 barr pompom.cs.cornell.edu>
//

// Copyright (C) 2004 by Cornell University
// All rights reserved.
// Refer to LICENSE for terms and conditions of use.

package jist.swans.mac;

import jist.swans.misc.Message;
import jist.swans.misc.MessageAnno;

import jist.runtime.JistAPI;
import jist.runtime.JistAPI.Continuable;
import jist.runtime.JistAPI.Continuation;

/**
 * Defines the interface of all Link layer entity implementations.
 *
 * @author Rimon Barr &lt;barr+jist@cs.cornell.edu&gt;
 * @version $Id: MacInterface.java,v 1.19 2004/04/06 16:07:48 barr Exp $
 * @since SWANS1.0
 */

public interface MacInterface
{

  /**
   * Update mac regarding new mode of its radio.
   *
   * @param mode new radio mode
   */
  void setRadioMode(byte mode);

  /**
   * Radio has locked onto a packet signal; mac may have a peek.
   *
   * @param msg packet currently in flight
   */
  void peek(Message msg, MessageAnno anno);

  /**
   * Radio has received a packet for mac to process.
   *
   * @param msg packet received
   * @param anno
   */
  void receive(Message msg, MessageAnno anno);

  //////////////////////////////////////////////////
  // from network layer
  //

  /**
   * Network layer would like to send the following packet. Should be called
   * only after Mac has notified that it is wants a packet.
   *
   * @param msg packet to send
   * @param nextHop destination mac
   */
  void send(Message msg, MacAddress nextHop, MessageAnno anno);


  //////////////////////////////////////////////////
  // 802.11 interface
  //

  /**
   * Extends the default Mac interface with 802_11 functions.
   *
   * @author Rimon Barr &lt;barr+jist@cs.cornell.edu&gt;
   * @since SWANS1.0
   */
  public static interface MacDcf extends MacInterface
  {

    /**
     * Initiate a timer event. Note that only one timer event can be active at a
     * given time.
     *
     * @param delay timer duration
     * @param mode new mode
     */
    void startTimer(long delay, byte mode);

    /**
     * Process mac timeout.
     *
     * @param timerId timer identifier
     */
    void timeout(int timerId);

    /**
     * Collision free send sequence complete.
     *
     * @param backoff is a backoff required
     * @param delPacket is processing for this packet complete
     */
    void cfDone(boolean backoff, boolean delPacket);


    public static final class Dlg implements MacInterface.MacDcf, JistAPI.Proxiable {
      MacInterface.MacDcf mac;

      public Dlg(MacInterface.MacDcf impl) {
        this.mac = impl;
      }

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

      public void cfDone(boolean backoff, boolean delPacket) {
        mac.cfDone(backoff, delPacket);
      }

      public void peek(Message msg, MessageAnno anno) {
        mac.peek(msg, anno);
      }

      public void receive(Message msg, MessageAnno anno) {
        mac.receive(msg, anno);
      }

      public void send(Message msg, MacAddress nextHop, MessageAnno anno) {
        mac.send(msg, nextHop, anno);
      }

      public void setRadioMode(byte mode) {
        mac.setRadioMode(mode);
      }

      public void startTimer(long delay, byte mode) {
        mac.startTimer(delay, mode);
      }

      public void timeout(int timerId) {
        mac.timeout(timerId);
      }
    }
  } // interface: 802_11


  public static final class Dlg implements MacInterface, JistAPI.Proxiable {
    MacInterface mac;

    public Dlg(MacInterface impl) {
      this.mac = impl;
    }

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

    public void peek(Message msg, MessageAnno anno) {
      mac.peek(msg, anno);
    }

    public void receive(Message msg, MessageAnno anno) {
      mac.receive(msg, anno);
    }

    public void send(Message msg, MacAddress nextHop, MessageAnno anno) {
      mac.send(msg, nextHop, anno);
    }

    public void setRadioMode(byte mode) {
      mac.setRadioMode(mode);
    }
  }
  
  public static interface IMacEDcf extends MacInterface.MacDcf {
    
    /** access category constants */
    public static final short AC_BK = 0;

    public static final short AC_BE = 1;

    public static final short AC_VI = 2;

    public static final short AC_VO = 3;

    public static final short TXOP_AC_NONE = -1;

    /** mac mode: idle. */
    public static final byte MAC_QMODE_SIDLE = 0;

    /** mac mode: transmit. */
    public static final byte MAC_QMODE_STX = 1;

    /** mac mode: nav. */
    public static final byte MAC_QMODE_SNAV = 2;
    
    public void continueSend(int ac);
    
    public void resetTXOPEvent();
    
    public boolean isQueueFull(short ac) throws Continuation;
    
    public static final class DlgE implements IMacEDcf, JistAPI.Proxiable {
      IMacEDcf mac;

      public DlgE(IMacEDcf impl) {
        this.mac = impl;
      }

      public MacInterface getProxy() {
        return (MacInterface) JistAPI.proxy(this, MacInterface.class);
      }
      
      public void cfDone(boolean backoff, boolean delPacket) {
        mac.cfDone(backoff, delPacket);
      }

      public void peek(Message msg, MessageAnno anno) {
        mac.peek(msg, anno);
      }

      public void receive(Message msg, MessageAnno anno) {
        mac.receive(msg, anno);
      }

      public void send(Message msg, MacAddress nextHop, MessageAnno anno) {
        mac.send(msg, nextHop, anno);
      }

      public void setRadioMode(byte mode) {
        mac.setRadioMode(mode);
      }

      public void startTimer(long delay, byte mode) {
        mac.startTimer(delay, mode);
      }

      public void timeout(int timerId) {
        mac.timeout(timerId);
      }
      
      public void continueSend(int ac) {
        mac.continueSend(ac);
      }
      
      public void resetTXOPEvent() {
        mac.resetTXOPEvent();
      }

      public boolean isQueueFull(short ac)  throws Continuation {
        return mac.isQueueFull(ac);
      }
    }
  }

} // interface: MacInterface

                          