package brn.swans.radio;

import jist.runtime.JistAPI;
import jist.swans.Constants;
import jist.swans.misc.Util;
import brn.swans.radio.RadioNoiseAdditiveBER.StateAdditive;

/**
 * Implementation of several Channel Clear Assessment (CCA) modes
 * for {@code RadioNoiseAdditiveBER}
 *
 * @author kurth
 */
public interface ChannelClearAssessment {

  void updateDuration(Long duration);

  boolean doesSense(StateAdditive state);


  /**
   * Class for mode 1 CCA: energy threshold only
   */
  public static class Mode1 implements ChannelClearAssessment {
    /**
     * CCA energy threshold
     */
    private final double energyLevel_mW;

    public Mode1() {
      this.energyLevel_mW = Util.fromDB(Constants.SENSITIVITY_DEFAULT);
    }

    public Mode1(double energyLevel_mW) {
      this.energyLevel_mW = energyLevel_mW;
    }

    public void updateDuration(Long duration) {}

    public boolean doesSense(StateAdditive state) {
      // check total energy
      if (state.totalPower_mW >= energyLevel_mW)
        return true;
      return false;
    }

  }


  /**
   * Class for mode 2 CCA: preamble detection only
   */
  public static class Mode2 implements ChannelClearAssessment {
    /** time of the expected end of the reception process of the current frame,
     * taken form preamble. The phy does something similar to the MAC NAV! */
    private long endCarrierBusy = -1;

    public void updateDuration(Long duration) {
      this.endCarrierBusy = Math.max(endCarrierBusy, JistAPI.getTime() + duration);
    }

    public boolean doesSense(StateAdditive state) {
      // NAV: if we read an duration, which is still active...
      if (JistAPI.getTime() < endCarrierBusy)
        return true;
      return false;
    }
  }

  /**
   * Class for mode 3 CCA: preamble detection + energy threshold
   */
  public static class Mode3 implements ChannelClearAssessment {
    /** CCA energy threshold, in the case the preamble was missed.
     * Use -62 from 802.11a spec.
     * Use -76 from 802.11g spec.
     * Atheros 802.11a: RX sensitivity + 10dBm
     * 802.11a spec: RX sensitivity + 20dBm
     *
     * -100.5dB Noise + 8dB NF + 5.4dB SNR_thres + 10dB atheros_thres = -77dB
     *
     * Reis et al. report a CCA threshold of -81dBm for Atheros 802.11abg cards,
     * but they do not distuingish b/w preamble and energy detection in CCA.
     * (Measurement-Based Models of Delivery and Interference in Static
     * Wireless Networks)
     * Lee et al. report a CCA threshold of 10dB above receiver sensitivity.
     */
    private final double energyLevel_mW;

    /** time of the expected end of the reception process of the current frame,
     * taken form preamble. The phy does something similar to the MAC NAV! */
    private long endCarrierBusy = -1;

    public Mode3() {
      this.energyLevel_mW = Util.fromDB(-77);
    }

    public Mode3(double energyLevel_mW) {
      this.energyLevel_mW = energyLevel_mW;
    }

    public void updateDuration(Long duration) {
      this.endCarrierBusy = Math.max(endCarrierBusy, JistAPI.getTime() + duration);
    }

    public boolean doesSense(StateAdditive state) {
      // check total energy
      if (state.totalPower_mW >= energyLevel_mW)
        return true;
      // NAV: if we read an duration, which is still active...
      if (JistAPI.getTime() < endCarrierBusy)
        return true;
      return false;
    }
  }

}
