package nxm.sys.lib;

import nxm.sys.inc.Commandable;
import nxm.sys.inc.IDable;
import nxm.sys.inc.MessageHandler;

/**
  A Processor is a NeXtMidas engine capable of executing the process() methods
  of a list of NeXtMidas primitives.  These commands may belong to independent processing
  chains so that a single piece of hardware can support multiple users.

  @author Jeff Schoen

*/
public class Processor extends Object
	implements IDable, MessageHandler, Commandable {

  /** processor ID */
  public String id;

  /** processor address */
  public String address;

  /** processor state */
  public int state = 0;

  /** vector of commands */
  public KeyVector commands;

  /** default constructor */
  public Processor () {}

  /** open the processor */
  @Override
  public int open () {
    commands = new KeyVector(16);
    return PROCESS ;
  }

  /** start processing */
  public void run () {
    state = INIT;
    state = open();
    while (state!=FINISH || state!=ABORT) {
      if (process()==NOOP) Time.sleep(0.0125);
    }
    state = close();
  }

  /** process a pass through the list of commands */
  @Override
  public int process () {
    int status=NOOP, cstatus;
    for (int i=0; i<commands.size(); i++) {
      Command cmd = (Command)commands.get(i);
      if (cmd.state==FINISH || cmd.state==ABORT) cstatus=NOOP;
      if (cmd.queue.getAvail()>0) cstatus = cmd.processMessage(cmd.queue.get());
      else if (cmd.isPiped && cmd.M.pipeMode!=Midas.PRUN) cstatus=NOOP;
      else cstatus = cmd.process();
      if (cstatus!=NOOP && cstatus!=SLEEP) status = NORMAL;
    }
    return status;
  }

  @Override
  public int processMessage (Message msg) {
    return NOOP;
  }

  /** close the processor */
  @Override
  public int close () {
    for (int i=0; i<commands.size(); i++) {
      Command cmd = (Command)commands.get(i);
      cmd.state = FINISH;
    }
    return FINISH;
  }

  /** add a Command
      @param cmd command to add
      @return number of commands
    */
  public int addCommand (Command cmd) {
    commands.add(cmd.id,cmd);
    return commands.size();
  }

  /** remove a Command
      @param cmd command to remove
      @return number of commands
    */
  public int remCommand (Command cmd) {
    commands.remove(cmd.id);
    return commands.size();
  }

  /** Set processor ID
   *  @param id processor ID */
  public void setID (String id) { this.id = id; }
  @Override
  public String getID() { return id; }

  /** Set processor address
   *  @param address processor address*/
  public void setAddress (String address) { this.address = address; }
  /** Get processor address
   *  @return processor address */
  public String getAddress() { return address; }

}
