require "rover"
require "rover_utils"
require "relay_board"

#all methods in this class that begin with the word "test"
#will be tested when the run method is called. All "test"
#methods should return a true/false value indicating success
#or failure.
class PrediveTest
  include LogHelper

  def run
    puts "######  Beginning rover pre-dive test  ######\n"
    @summary = ""
    @rover = Rover.instance
    methods = self.methods
    testMethods = Array.new
    methods.each {|method| 
      if(method =~ /test.*/)
        testMethods << method
      end
    }
    testMethods.each{|testMethod|
      puts "\nNext test (#{testMethod}). Run it? [y/n/s(kip)] y"
      response = gets("\n")
      if(response =~ /n/)
        puts("Aborting test sequence")
        break
      elsif(response =~ /s/)
        puts "Skipping #{testMethod}...\n"
        @summary += "  * #{testMethod} skipped\n"
        next
      end
      puts "Running #{testMethod}..."
      begin
        response = self.send(testMethod)
      rescue Exception => e
        puts "caught an exception in test method"
        puts "exception = #{e}"
        response = false
      end
      if(response)
        puts "#{testMethod} succeeded\n"
        @summary += "    #{testMethod} succeeded\n"
      else
        puts "#{testMethod} failed\n"
        @summary += "  ! #{testMethod} failed\n"
      end
    }
    
    @rover.relay.allOff
    puts "all relays turned off"
    puts "Pre-dive testing completed"
    puts "\n######  Summary of Pre-dive Tests  ######"
    puts   "========================================="
    puts @summary
  end

  def testA2D
    chn = 4
    puts "Channel? [#{chn}] "
    response = gets("\n")
    chn = response.to_i if (response.length > 1)
    puts "Enter target voltage: "
    response = gets("\n")
    target = response.to_f
    actual = "0"
    offset = 38900
    low_diff = 11.0
    diff = 2.0
    
    puts("Please wait while I zero-in on that target voltage...")
    while ( ((diff = (target-actual.to_f).abs) > 0.001) && offset <= 41000)
      puts "difference is #{diff}"
      
      # Difference in voltage should be dropping. Keep track of lowest diff
      # and break when the diff starts increasing again.
      # 
      low_diff = diff if (diff < low_diff)
      break if (diff > low_diff)
      
      # Change adjusment value and try again
      #
      offset += 100    
      adc_com = "adc -ac #{chn} -j #{offset}"
      print(adc_com)
      print("...  ")
      actual = `#{adc_com}`
    end
    
    if (offset < 41050)
      puts("Optimal \"j\" value is between #{offset - 100} and #{offset}")
    else
      puts("\nOptimal \"j\" value could not be found between 39000 and 41000")
    end
    true
    
  end
  
  def testMotors
    @rover.relay.motorsOn
    success = true
    puts "setting motor to \"A\""
    @rover.motors.active_motor_num = "A"
    puts "getting motor status"
    sleep(2)
    puts "status: #{@rover.motors.current_status?}"
    sleep(1)
    error = @rover.motors.has_error
    if(error)
      puts "motors have an error: #{@rover.motors.error_message}"
      success = false
    end
    @rover.relay.motorsOff
    success
  end

  def testCurrentMeter
    @rover.relay.acmOn
    sleep(3)
    success = true
    @rover.acm.run
    puts "ACM is running. Is data showing up in logs/latest/acm.csv? [y/n] y"
    response = gets("\n")
    if(response =~ /n/)
      success = false
    end
    @rover.acm.stop_thread
    @rover.relay.acmOff
    success
  end

  def testVideo
    @rover.relay.videoOn
    @rover.relay.camerasOn
    success = true
    puts "check if video is on by going to webserver and observing it in 30secs..."
    sleep(20)
    puts "...in 10secs..."
    sleep(10)
    puts "...OK, now."
    sleep(3)
    puts "is image appearing at http://192.168.0.90 ? [y/n] y"
    response = gets("\n")
    if(response =~ /n/)
      success = false
    end
    @rover.relay.videoOff
    success
  end

  def testOptodes
    @rover.relay.s_optodeOn
    @rover.relay.p_optodeOn
    success = true
    starboard_optode = Aanderaa.new nil, "/dev/starboard_optode"    
    response = starboard_optode.acquire_data
    if(response)
      puts "starboard optode data: #{starboard_optode.rawdata}"
    else
      puts "starboard optode returned false from acquire_data"
      success = false
    end

    port_optode = Aanderaa.new nil, "/dev/port_optode"
    response = port_optode.acquire_data
    if(response)
      puts "port optode data: #{port_optode.rawdata}"
    else
      puts "port optode returned false from acquire_data"
      success = false
    end

    ref_optode = Aanderaa.new nil, "/dev/ref_optode"
    response = ref_optode.acquire_data
    if(response)
      puts "reference optode data: #{ref_optode.rawdata}"
    else
      puts "reference optode returned false from acquire_data"
      success = false
    end
    @rover.relay.s_optodeOff
    @rover.relay.p_optodeOff
    success
  end

  def testValvePump
    @rover.relay.s_valveOn
    success = true
    puts "is starboard valve pump working? [y/n] y"
    response = STDIN.gets("\n")
    if(response =~ /n/)
      success = false
    end
    @rover.relay.s_valveOff

    @rover.relay.p_valveOn
    success = true
    puts "is port valve pump working? [y/n] y"
    response = STDIN.gets("\n")
    if(response =~ /n/)
      success = false
    end
    @rover.relay.p_valveOff
    success
  end

  def testStirMotor
    @rover.relay.s_stirOn
    @rover.relay.p_stirOn
    success = true
    puts "are stir motors working? [y/n] y"
    response = STDIN.gets("\n")
    if(response =~ /n/)
      success = false
    end
    @rover.relay.s_stirOff
    @rover.relay.p_stirOff
    success
  end
  
  def testRack
    success = true

    # Port rack first
    #
    @rover.rack.reinit($PORT_RACK)
    sleep(2)
    puts "getting port racks encoder position"
    puts "Rack encoder position = #{@rover.rack.encoder_position}" 
    puts "send rack home? [y/n] n"
    response = STDIN.gets("\n")
    if(response =~ /y/)
      @rover.rack.home($PORT_RACK)
      puts "did rack go home? [y/n] y"
      response = STDIN.gets("\n")
      if(response =~ /n/)
        success = false
      end
    end

    puts "insert chamber? [y/n] n"
    response = STDIN.gets("\n")
    if(response =~ /y/)
      sleep(1)
      @rover.rack.insert_chamber($PORT_RACK)
      puts "did rack insert? [y/n] y"
      response = STDIN.gets("\n")
      if(response =~ /n/)
        success = false
      end
    end

    puts "send rack home? [y/n] y"
    response = STDIN.gets("\n")
    unless(response =~ /n/)
      @rover.rack.home($PORT_RACK)
      puts "did rack go home? [y/n] y"
      response = STDIN.gets("\n")
      if(response =~ /n/)
        success = false
      end
    end
    @rover.relay.p_rackOff    
    
    # Starboard rack next
    #
    @rover.rack.reinit($STBD_RACK)
    sleep(2)
    puts "getting stbd racks encoder position"
    puts "Rack encoder position = #{@rover.rack.encoder_position}" 
    puts "send rack home? [y/n] n"
    response = STDIN.gets("\n")
    if(response =~ /y/)
      @rover.rack.home($STBD_RACK)
      puts "did rack go home? [y/n] y"
      response = STDIN.gets("\n")
      if(response =~ /n/)
        success = false
      end
    end
    
    puts "insert chamber? [y/n] n"
    response = STDIN.gets("\n")
    if(response =~ /y/)
      sleep(1)
      @rover.rack.insert_chamber($STBD_RACK)
      puts "did rack insert? [y/n] y"
      response = STDIN.gets("\n")
      if(response =~ /n/)
        success = false
      end
    end
      
    puts "send rack home? [y/n] y"
    response = STDIN.gets("\n")
    unless(response =~ /n/)
      @rover.rack.home($STBD_RACK)
      puts "did rack go home? [y/n] y"
      response = STDIN.gets("\n")
      if(response =~ /n/)
        success = false
      end
    end
    @rover.relay.s_rackOff    
    
    success
  end
    
  def testCleanPump
    @rover.relay.s_cleanOn
    success = true
    puts "is starboard cleaning pump working? [y/n] y"
    response = STDIN.gets("\n")
    if(response =~ /n/)
      success = false
    end
    @rover.relay.s_cleanOff

    @rover.relay.p_cleanOn
    success = true
    puts "is port cleaning pump working? [y/n] y"
    response = STDIN.gets("\n")
    if(response =~ /n/)
      success = false
    end
    @rover.relay.p_cleanOff
    success
  end

  
  def testRelay
    success = true

    relay = @rover.relay.rb1
    relays1 = [["Motors", RelayMan::MOTORS], ["V12-A", RelayMan::V12A],
              ["V12-B", RelayMan::V12B], ["V5", RelayMan::V5],
              ["S Valve", RelayMan::S_VALVE], ["S/Ref Optode", RelayMan::S_OPTODE],
              ["S Rack", RelayMan::S_RACK], ["S Stir", RelayMan::S_STIR]]
    relays1.each {|r|
      puts "testing #{r[0]} relay"
      relay.turn_on r[1]
      response = relay.get_status r[1]
      if(response.to_i != 1)
        success = false
        puts "#{r[0]} relay did not turn on"
      else
        relay.turn_off r[1]
        response = relay.get_status r[1]
        if(response.to_i != 0)
          success = false
          puts "#{r[0]} relay did not turn off"
        end
      end
    }
    
    relay = @rover.relay.rb2
    relays1 = [["P Rack", RelayMan::P_RACK], ["Cameras", RelayMan::CAMERAS],
              ["S Clean", RelayMan::S_CLEAN], ["P Clean", RelayMan::P_CLEAN],
              ["P Valve", RelayMan::P_VALVE], ["P Optode", RelayMan::P_OPTODE],
              ["Video", RelayMan::VIDEO], ["P Stir", RelayMan::P_STIR]]
    relays1.each {|r|
      puts "testing #{r[0]} relay"
      relay.turn_on r[1]
      response = relay.get_status r[1]
      if(response.to_i != 1)
        success = false
        puts "#{r[0]} relay did not turn on"
      else
        relay.turn_off r[1]
        response = relay.get_status r[1]
        if(response.to_i != 0)
          success = false
          puts "#{r[0]} relay did not turn off"
        end
      end
    }
    
    @rover.relay.allOff
    response = relay.get_status 0
    if(!response =~ /00/)
      success = false
      puts "relay did not turn all off after relay.allOff command"
    end
    success
  end
end

pre = PrediveTest.new()
pre.run()
