// Note: this is a script intended for use within µManager Software via the Script Panel located in the dropdown 'tools' menu 


import org.micromanager.*;
import org.micromanager.api.AcquisitionOptions;
import org.micromanager.api.PositionList;
import org.micromanager.api.MultiStagePosition;
import org.micromanager.navigation.StagePosition;
import java.lang.System;
import ij.IJ;
import ij.*;

//////////////
  
  // standard function to find an item in an array (does item exist?)
inArray(int[] array, int test) {
  for(ii=0;ii<array.length;ii++){
    if (test==array[ii]){
      return(true);
    }
  }
  return(false);
} 

//////////////
  
  
  fireStim(int frame, int[] position){
    fireStart = System.currentTimeMillis();
    print("Initiate FireStim: " + (fireStart - start) + "ms");
    mmc.setShutterDevice("Fluorescence");
    mmc.setAutoShutter(false);
    mmc.setExposure(Stim_Exposure); 
    mmc.setStateLabel("ExcitationWheel", "A488");
    mmc.waitForDevice("ExcitationWheel");       
    
    // P position integar
    for (int P=0; P < pl.getNumberOfPositions(); P++){
      if (inArray(position, P)){
        print("\nInitiate StimImaging");
        acqs[P] = pl.getPosition(P).getLabel();
        MultiStagePosition.goToPosition(pl.getPosition(P), mmc);     
        mmc.waitForDevice("ZStage");
        mmc.waitForDevice("XYStage");
        print(System.currentTimeMillis() - fireStart);
        mmc.setShutterOpen(true);
        now = System.currentTimeMillis();
        print("Acquiring position " + P + ", frame " + (frame+1) + ", channel A488 at " + Stim_Exposure + "ms Exposure; start: "+ (now - start) + " ms.");
        gui.snapAndAddImage(acqs[P], frame, 1, 0, 0);       
        mmc.setShutterOpen(false);  
        print(System.currentTimeMillis() - fireStart);          
      } 
    }
    // Reset position
    MultiStagePosition.goToPosition(pl.getPosition(0), mmc);    
  }

//////////////
  
  
  firePhase(int frame){
    fireStart = System.currentTimeMillis();
    print("Initiate FirePhase " + (fireStart - start) + "ms");
    
    mmc.setShutterDevice("PhaseContrast");
    mmc.setAutoShutter(false);
    mmc.setExposure(Phase_Exposure); // change to appropriate exposure for phase
    
    // P position integer
    for (int P=0; P < pl.getNumberOfPositions(); P++){
      acqs[P] = pl.getPosition(P).getLabel();
      MultiStagePosition.goToPosition(pl.getPosition(P), mmc);   
      mmc.waitForDevice("ZStage");
      mmc.waitForDevice("XYStage"); 
      mmc.setShutterOpen(true);
      mmc.waitForDevice("PhaseContrast");   
      now = System.currentTimeMillis();
      print("Acquiring position " + P + ", frame " + (frame+1) + ", Phase contrast at " + Phase_Exposure + "ms Exposure; start: "+ (now - start) + " ms.");
      gui.snapAndAddImage(acqs[P], frame, 0, 0, 0);     
      mmc.setShutterOpen(false);    
      print(System.currentTimeMillis() - fireStart);            
    }   
    // Reset position
    MultiStagePosition.goToPosition(pl.getPosition(0), mmc);    
  }

//////////////
  
  // START CODE HERE

gui.closeAllAcquisitions(); // clear all previous acquisitions
gui.clearMessageWindow(); // I might want to comment this out

gd = new ij.gui.GenericDialog("Set Imaging Parameters");
gd.addNumericField("Choose Time Points", 577, 0);
gd.addNumericField("Choose Time Interval (ms)", 300000, 0); // 5 min interval = 300000
gd.addNumericField("Choose Phase Exposure Time (ms): ", 10,0); // phase at 10ms?
gd.addStringField("Choose Stimulation Frame(s) (ex: 1,2,3)","7,13,19,25,31,37,43,49,55,61,67,73,79,85,91,97,103,109,115,121,127,133,139,145,151,157,163,169,175,181,187,193,199,205,211,217,223,229,235,241,247,253,259,265,271,277,283,289,295,301,307,313,319,325,331,337,343,349,355,361,367,373,379,385,391,397,403,409,415,421,427,433,439,445,451,457,463,469,475,481,487,493,499,505,511,517,523,529,535,541,547,553,559,565,571,577");
gd.addNumericField("Choose Stim (488nm) Exposure Time (ms): ", 2000,0); // opto stim at 2sec
gd.addStringField("Choose Stimulation Positions(s) (ex: 0,1,2,3)","1,2,3");
gd.showDialog();

if (gd.wasCanceled())
  return;

// populate variables with user data
Total_TimePoints = (int)gd.getNextNumber();
Interval = (int)gd.getNextNumber();
Phase_Exposure = (int)gd.getNextNumber();
Stim_Exposure = (int)gd.getNextNumber(); 

StimStr=gd.getNextString();
StimStrArr = StimStr.split(",");

int[] StimIntArr = new int[StimStrArr.length];
int[] Stim_FrameLabel = new int[StimStrArr.length];

for(z=0;z<StimStrArr.length;z++){
  String placeholder = StimStrArr[z].toString();
  StimIntArr[z] = Integer.valueOf(placeholder)-1; // '-1' Changes all frames to base0 format to match numframes later on
  Stim_FrameLabel[z] = Integer.valueOf(placeholder); // This is an Exact Duplicate of StimIntArr without -1 for 0 base, solely for Frame Labeling purposes
}

StimPosStr=gd.getNextString();
StimPosStrArr = StimPosStr.split(",");

int[] StimPosIntArr = new int[StimPosStrArr.length];
int[] StimPos_FrameLabel = new int[StimPosStrArr.length];

for(z=0;z<StimPosStrArr.length;z++){
  String placeholder = StimPosStrArr[z].toString();
  StimPosIntArr[z] = Integer.valueOf(placeholder); 
  StimPos_FrameLabel[z] = Integer.valueOf(placeholder); // This is an Exact Duplicate of StimPosIntArr without -1 for 0 base, solely for Frame Labeling purposes
}

if(Total_TimePoints<1){Total_TimePoints=1;}

// from dialog
numFrames = Total_TimePoints;
intervalRep = Interval;
Stim_Frames = StimIntArr;
StimPos_Frames = StimPosIntArr;  

print(" \n" + "Running: " 
      + " \nTotal Frames: " + (int) Total_TimePoints 
      + " \nInterval: " + (int) Interval + " ms" 
      + " \nBlue Light Stimulation On Frame(s): " + Arrays.toString(Stim_FrameLabel) 
      + " \nBlue Exposure Time: " + Stim_Exposure + " ms"
      + " \nRed Exposure Time: " + Red_Exposure + " ms"
      + " \nBlue Light Stimulation On Positions(s): " + Arrays.toString(StimPos_FrameLabel) 
      + " \n");

// parameters
mmc.setProperty("Fluorescence","Delay_ms","20");
mmc.setAutoShutter(false);

// file locations
acqName = "test_opto_multiple_alternating_pos+channels";
rootDirName = "C:\\Users\\raseidma\\Desktop\\TEST ACQ CRAP DIRECTORY";

// channels, exposures, XY positions, Z slices
String[] channels = {"Phase","A488"};
int[] exposures = {Phase_Exposure, Stim_Exposure};
numSlices = 1;
channelGroup = "Channel";
PositionList pl = gui.getPositionList();

String[] acqs = new String[pl.getNumberOfPositions()];
start = System.currentTimeMillis();

for (int P=0; P < pl.getNumberOfPositions(); P++) {
  acqs[P] = pl.getPosition(P).getLabel();
  // create acquisition and set options
  gui.openAcquisition(acqs[P], rootDirName, numFrames, channels.length, numSlices);
  for (int i=0; i<channels.length; i++)
    gui.setChannelName(acqs[P], i, channels[i]);
}

MultiStagePosition.goToPosition(pl.getPosition(0), mmc);
mmc.setExposure(exposures[0]);
//mmc.setConfig(channelGroup, channels[0]); 
//mmc.setStateLabel("ExcitationWheel", channels[0]);    
mmc.setShutterOpen(false);  
mmc.waitForSystem();    
start = System.currentTimeMillis();

// The bulk code
for (int i=0; i<numFrames; i++) {
  reStart = System.currentTimeMillis();
  
  // every frame perform phase imaging
  firePhase(i);
  
  // if stim frame call fireStim function
  if (inArray(Stim_Frames, i)){
    print("\nInitiate StimImaging");
    fireStim(i, StimPos_Frames);
  } 
  
  itTook = System.currentTimeMillis() - reStart;
  if (itTook > intervalRep){
    print("IntervalRep too short!");
  }
  if (itTook < intervalRep){
    gui.sleep(intervalRep - itTook);
  } 
}
print("\nFinished!")