require "rover"
require "rover_thread"

class Measure < Monitor
  include LogHelper
  
  $DEFAULT_RECORD_TIME = 1		#Time to record data from optode, in minutes
  $DEFAULT_RECORD_INTERVAL = 14		#Time in minutes to wait between optod reads
  $SHORT_RECORD_INTERVAL = 5		#Time to wait on "short" mission cycle
  
  attr_reader :action, :thr
  attr_accessor :relay, :video, :rack, :ch_op, :rf_op

  def initialize (iterations=1)
    @relay = Rover.instance.relay
    @video = Rover.instance.video
    @rack  = Rover.instance.rack
    @ch_op = Rover.instance.chamber_optode
    @rf_op = Rover.instance.ref_optode
    @thr   = 0
    @pct   = 0
    @abort = false
    @action = "Measure:Initialized"
    if iterations < 1
      syslog("! Measure: Iterations must be at least 1, not #{iterations}")
      @iterations = 1
    else
      @iterations = iterations
    end
  end

  def acquireOptodeData
    # Do one or more recording sessions
    #
    iter = @iterations
    syslog("_ commencing #{iter} iterations")
    while (true)
      currentIter = 1 + (@iterations - iter)
      @action = "Measure:Acquiring Data (#{currentIter} of #{@iterations})"
      
      # Start recording
      #
      syslog("_ turning optodes on and recording data")
      self.relay.optodeOn
      sleep(2)
      reinit_optodes()
      sleep(2)
      @ch_op.run
      @rf_op.run
      sleep($DEFAULT_RECORD_TIME*60)
      
      # Stop
      #
      syslog("_ turning optodes off")
      @ch_op.close
      @rf_op.close
      self.relay.optodeOff
      syslog("_ Finished recording #{currentIter} of #{@iterations}")
      
      # Are we done now?
      #
      iter -= 1
      if (iter == 0 || self.abort?)
        syslog("_ We're done")
        return
      end
      syslog("_ Sleeping until next recording session")
      self.percentComplete += 70/@iterations
      if(Rover::TEST)
        sleep($SHORT_RECORD_INTERVAL*60)
      else
        sleep($DEFAULT_RECORD_INTERVAL*60)
        sleep 5
      end
    end
  end
  
  def reinit_optodes
    Rover.instance.chamber_optode = Aanderaa.new nil, "/dev/chamber_optode"
    Rover.instance.ref_optode = Aanderaa.new nil, "/dev/ref_optode"
    @ch_op = Rover.instance.chamber_optode
    @rf_op = Rover.instance.ref_optode
  end

  def imageCapture camera, name = "test"
      # Turn on video server and capture an image of the measurement site
      #
      syslog("_ turning on video, waiting 30 sec")
      self.relay.videoOn
      sleep(30)               # Wait for server to boot
      
      syslog("_ capturing image")
      unless (@video.captureImage(camera, name))
        syslog ("! Unable to capture image of sediment")
      end
      
      syslog("_ turning off video")
      self.relay.videoOff
  end

  # Run the measure process
  # If abort signal is received we simply jump down to raising the rack
  # and 100% complete
  #
  def run
    @abort = false
    @thr = RoverThread.new do
    
      self.percentComplete=0
      
      # Take image before measurement
      #
      @action = "Measure:Taking First Image"
      self.imageCapture(Video::CHAMBER_1, "before")
      self.percentComplete=5

      # Open chamber valves
      #
      relay.pumpOn
      self.percentComplete=10
      

      unless abort?      
        # Lower the chambers into the sediment
        #
        @action = "Measure:Lowering Chambers"
        syslog("_ Initialize rack")
        self.rack.close
        self.relay.rackOff
        sleep(1)
        syslog("_ rack turned on")
        self.relay.rackOn
        sleep(2)
        Rover.instance.rack = Rack.rover
        self.rack = Rover.instance.rack
        syslog("_ rack re-instantiated")

        syslog("_ Inserting chamber 1")
        unless (rack.insert_chamber)
          syslog ("! Unable to insert chambers in sediment")
          self.abort
        end
        self.percentComplete=15
      end

      relay.pumpOff
      unless abort?
        # Take another image of the measurement site
        #
        @action = "Measure:Taking Second Image"
        self.imageCapture(Video::CHAMBER_1, "inserted")
        self.percentComplete=20
      end
      
      unless abort?
        # Close valve and Begin stirring
        #
        relay.v5On
      
        # Measure the oxygen in the chamber
        #
        acquireOptodeData
        self.percentComplete=95
      
        # Stop stirring
        #
        relay.v5Off
      end
      
      # Open valves and Raise the chamber back to home position
      #
      relay.pumpOn
      sleep 10
      
      if abort?
        @action = "Measure:Aborting - Homing Chambers"
      else
        @action = "Measure:Homing Chambers"
      end
      
      unless (@rack.home)
        syslog ("! Unable to home chambers")
      end
      
      # Done. Close valves and shut off rack motor
      #
      relay.pumpOff
      self.relay.rackOff
      self.percentComplete=100
      if abort?
        @action = "Measure:Aborted"
      else
        @action = "Measure:Initialized"
      end
      
    end      # thread
    
  end        # run

  def abort?
    return @abort
  end

  def abort
    syslog "! Measure: Received abort command"
    @abort = true
    @action = "Measure:Aborting"
    return
  end
    
  def percentComplete
  #  self.synchronize do
      return @pct
   # end
  end

  def currentAction
    return @action
  end
  
private 
  
  def percentComplete= p
#    self.synchronize do
      op = @pct
      @pct = p
      return op
 #   end
  end
  
end        # class Measure
  
