/**
 * @author Frank Zeyda, Kun Wei
 */
package cdx;

import javax.safetycritical.Mission;
import javax.safetycritical.AperiodicEvent;

/**
 * The single mission of the parallel CDx.
 *
 * The seven handlers of the mission are
 *   InputFrameHandler,
 *   ReducerHandler,
 *   DetectorHandler (four instances), and OutputCollisionsHandler.
 */
public class CDxMission extends Mission {
  /**
   * Records the current radar frame.
   */
  public RawFrame currentFrame;

  /**
   * Records previous aircraft positions.
   */
  public StateTable state;

  /**
   * Records a partition of the computational work as it is distributed
   * between the parallel detection handlers.
   */
  public Partition work;

  /**
   * Records the number of collisions calculated by the detector handlers.
   */
  public int collisions;

  /* Control object used to orchestrate execution of the handlers.
   *   
   * This instance is not introduced as a field since this causes a memory
   * violation issue with our (outdated) reference implementation of SCJ.
   */
  /*public DetectorControl control;*/

  /**
   * Simulation object used to generate frames and maintain simulation data.
   */
  public final Simulation simulator;

  public CDxMission() {
    simulator = new Simulation();
    currentFrame = new RawFrame();
    state = new StateTable();
    work = new Partition(Constants.DETECTORS);
    collisions = 0;
  }

  public void initialize() {
    /* OutputCollisionsHandler outputs the collisions results. */
    OutputCollisionsHandler h1 = new OutputCollisionsHandler(this);

    /* The SCJ event output releases OutputCollisionsHandler. */
    AperiodicEvent output = new AperiodicEvent(h1);

    DetectorControl control = new DetectorControl(output, Constants.DETECTORS);

    /* DetectorHandler instances carry out the actual detection work. */
    DetectorHandler[] hdls = new DetectorHandler[Constants.DETECTORS];
    for (int i = 1; i <= Constants.DETECTORS; i++) {
      hdls[i - 1] = new DetectorHandler(this, control, i);
    }

    /* The SCJ event detect releases all DetectroHandlers. */
    AperiodicEvent detect = new AperiodicEvent(hdls);

    /* ReducerHandler performs voxel hashing and division of work. */
    ReducerHandler h2 = new ReducerHandler(this, detect, control);

    /* The SCJ event reduce releases ReducerHandler. */
    AperiodicEvent reduce = new AperiodicEvent(h2);

    /* InputFrameHandler reads radar frames; it is the only periodic handler. */
    InputFrameHandler h3 = new InputFrameHandler(this, reduce);

    /* We are ready now to process radar frames. */
    simulator.detectorReady = true;
  }

  public long missionMemorySize() {
    return Constants.PERSISTENT_DETECTOR_SCOPE_SIZE;
  }

  /**
   * Method to get the current frame object.
   */
  public RawFrame getFrame() {
    return currentFrame;
  }

  /**
   * Method to set the current frame object.
   */
  public void setFrame(RawFrame frame) {
    currentFrame = frame;
  }

  /**
   * Method to get the shared partition variable.
   */
  public StateTable getState() {
    return state;
  }

  /**
   * Method to set the shared partition variable.
   */
  public void setState(StateTable state) {
    this.state = state;
  }

  /**
   * Method to get the shared work variable.
   */
  public Partition getWork() {
    return work;
  }

  /**
   * Method to set the shared work variable.
   */
  public void setWork(Partition work) {
    this.work = work;
  }

  /**
   * This method initialises the number of collisions by setting it to 0.
   */
  public synchronized void initColls() {
    collisions = 0;
  }

  /**
   * This method records a partial collisions result as it is generated by the
   * detection handlers.
   *
   * @param n Number of collisions to be recorded.
   */
  public synchronized void recColls(int n) {
    collisions += n;
  }

  /**
   * This method returns the cumulative number of collisions recorded.
   */
  public synchronized int getColls() {
    return collisions;
  }

  /**
   * This method prints out the number of generated and dropped frames. It
   * is not part of the model and used to debug execution of the program.
   */
  public void dumpResults() {
    System.out.println("Generated frames: " + Constants.MAX_FRAMES);
    System.out.println("Frames dropped : " + simulator.droppedFrames);
  }
}
