package inp.camac;


/**
 * @author      Maxim V. Kollegov
 * @version     1.00, 02/04/2001
 */
 
import java.io.*; 

  /**
   * Class representing CAMAC crate hardware. 
   * To obtain Crate object use something like this:
   * <pre>
   *    ....
   *   CamacDriver driver = CamacDriver.loadDriver("DriverCC232");
   *   Crate crate        = driver.getCrate(0);
   *    ....
   * </pre>
   */

public class Crate {
  private Module[] modules = new Module[24];
  private int      crateN=-1;  // crate number for multiple crates sytems
  private CamacDriver driver;
  
  /**
   * Package level protected constructor. To obtain Crate object use: 
   * CamacDriver.getCrate( crateN )
   */
  
  Crate(CamacDriver driver, int crateN){
  	 this.driver = driver;
  	 this.crateN = crateN;
  }
  
  /**
   * Add module to station N.<br>
   * N is in terms if camac numeration from 1 to 24.
   * When called execute Module.setN(N) and Module.setCrate(Crate)
   * to inform module about it's location;  
   * @param module  module to add
   * @param N       position (1..24) where to add
   *
   * @see inp.camac.Module#setN
   * @see inp.camac.Module#setCrate
   */
   
   
  public void addModule(Module module,int N){
     if(N<1 || N>24 ) throw new IllegalArgumentException("Invalid N="+N+", must be from 1 to 24");
  	 if( modules[N-1] == null ) {
	      modules[N-1] = module;
	      module.setCrate(this);
	      module.setN(N);
  	 }
    else throw new IllegalArgumentException("Position "+N+" already have module");
  }

  
  /**
   * Remove module from specified position
   * @return  removed Module
   * @param N  position wherefrom to remove module
   */
  public Module removeModule(int N){   
     if(N<1 || N>24 ) throw new IllegalArgumentException("Invalid N="+N+", must be from 1 to 24");  
     Module mod = modules[N-1];
     if(mod!=null) {
       mod.setCrate(null);
       mod.setN(-1);
	   modules[N-1]=null;
     }
     return mod;
  }

  /**
   * @return Module at position N
   */  
  public Module getModule(int N){
     if(N<1 || N>24 ) throw new IllegalArgumentException("Invalid N="+N+", must be from 1 to 24");  
     return modules[N-1];
  }

  
  /**
   * remove Module from Crate
   * @ret removed Module or null if Module not found in Crate
   */
  public Module removeModule(Module m){   
     for(int i=0;i<24;i++){
     	 if (m == modules[i]) {
        	 modules[i]=null;
        	 m.setCrate(null);
        	 m.setN(-1);
          return m;
     	 }
     }
     return null;
  }
   
  /**
   * Methid to execute NAF in Crate 
   * This method can be used public to execute NAF on crate object, but 
   * better to use Module.AF(..) instead.
   * @param N        Camac module position (1..24)
   * @param A        Camac subaddress
   * @param F        Camac function 
   * @param data     Array of data, NAF will be executed as many times as data.length
   *                 if null than NAF will be executed once without data transfer.
   *                 In case of write operation, data from this array must be written 
   *                 in target module. In case of read operation data read from module 
   *                 must be placed in this array.
   * @param bits     Number of significant bits in data transfer. For some sort of 
   *                 hardware this parameter might be usefull to reduce data transfer 
   *                 time. Implementation might return either all 24 bits either only 
   *                 required number of bits
   */
  public void executeNAF(int N,int A,int F,int[] data, int bits) throws IOException{
  	 driver.executeNAF(crateN,N,A,F,data,bits,N>1 ? modules[N-1]:null);
  }
  
  /**
   * Execute Z cycle in Crate 
   */
  public void Z() throws IOException {
  	 driver.Z(crateN);  	 
  }
  
  /**
   * Execute C cycle in Crate 
   */
  public void C() throws IOException {
  	 driver.C(crateN);  	 
  }
  
  /**
   * set Inhibit bus state 
   * @param inhibit  new state of bus 
   */  
  public void I(boolean inhibit) throws IOException {
  	 driver.I(crateN,inhibit);  	 
  }

  /**
   * Enable/disable LAM from given position 
   */
  void enableLAM(int N,boolean enable)  throws IOException{
     driver.enableLAM(crateN,N,enable);
  }
      
}