! This will test the GET and SET functions of RMIF.
!
! @author  J. Czechowski IV / Neon Ngo
!
! <oPort> The other RMIF remote's port (0 means it has not been set yet)

startmacro L:oPort[0]
  switch DEBUG   debug        GET DEF=false SDEF=true
  switch VERBOSE verbose      GET DEF=false SDEF=true
  switch STATEM  statemachine GET DEF=false SDEF=true

  if statemachine then ! Switch to legacy remote names, just for this test case
    invoke previousLegacyRemote nxm.sys.net.Rmif.getStatemUsesLegacyRemoteNames()
    res z:mytrue true
    invoke ,, nxm.sys.net.Rmif.setStatemUsesLegacyRemoteNames(^mytrue)
  endif

  timer set

  set timelost 4.0  ! this is slightly different than RMIF default 5s time lost
  set L:anyAvailablePort -1

  pipe init
    set mode    0
    set newmode 0

    if /Bravo then
      ! start second RMIF instance
      res foo "B:FOO"
      res bar "B:BAR"

      res thisHost  "BRAVO"
      res otherHost "REMOTE"

      res otherHP "localhost:^oPort"

      rmif/id=^thisHost/STATEM=^statemachine/VERBOSE=^verbose anyAvailablePort foo|bar
      say " in /BRAVO-------"
      if statemachine then
        invoke myRmif reg.bravo.getRmif()
        invoke myPort myRmif.getPort()
        res otherHost "REMOTE_127_0_0_1_^{myPort}"
      endif
      if debug then
        say "        Second RMIF client started on port=^reg.^{thisHost}.port with ID=^thisHost"
      endif
      message sendw ^thisHost ,, "OPEN" ,, {ID=^otherHost,HP=^otherHP}
      say " end /BRAVO-------"

    else ! /ALPHA
      say " in /ALPHA-------"
      ! start first RMIF instance
      if debug then
        say "      Starting tests for RMIF's GET/SET Methods"
        say "        (This may take 20 seconds to complete)"
      endif

      res foo "A:FOO"
      res bar "A:BAR"

      res thisHost  "ALPHA"
      res otherHost "REMOTE_WHAT"

      ! setting default time lost for remotes to this RMIF to test Bug 1459
      rmif/id=^thisHost/ppt={TIMELOST=^timelost}/STATEM=^statemachine/VERBOSE=^verbose anyAvailablePort foo|bar|mode|newmode
      if statemachine then
        invoke myRmif reg.alpha.getRmif()
        invoke myPort myRmif.getPort()
        res otherHost "REMOTE_127_0_0_1_^{myPort}"
      endif
      
      ASSERT/text="TEST_RMIF: Set RMIF default Time Lost property" reg.^{thisHost}.timeLost eq timeLost
      if debug then
        say "        First  RMIF client started on port=^reg.^{thisHost}.port with ID=^thisHost"
      endif
      run/bg "%test_rmif_get_set_temp/STATEM=^statemachine/DEBUG=^debug/VERBOSE=^verbose/BG/Bravo ^reg.^{thisHost}.port"

      ! most of the time the second RMIF instance is running a the next port, so pre-populate it
      calc L:tmpPort ^reg.^{thisHost}.port 1 +
      res otherHP "localhost:^tmpPort"

      ! pause up to 2.5 seconds waiting for 2nd RMIF to startup and connect to 1st RMIF
      res otherHost
      do i 1 25
        say "in loop ^{reg}"
        if reg.remote rexists then
          res otherHP "localhost:^reg.remote.port"
          res reg.remote
          res otherHP
          break
        else
          pause 0.1
        endif
      enddo

    endif
    say "end APLPHA ----"

    set this.timers 2
    set this.timer(0) 0.5
    set this.timer(1) 40
  pipe off

  if statemachine then
    invoke ,, nxm.sys.net.Rmif.setStatemUsesLegacyRemoteNames(^previousLegacyRemote)
  endif

endmacro


! This will send a message.
!
! If debug is on the message will be printed out before sending.
!
procedure sendMsg id name data
  if debug then
    say "^thisHost: Send ^name = ^data to ^id"
  endif

  message send id ,, name ,, data
return


! This will process a message.
!
! If debug is on the message will be printed out before processing.
!
!******************************************************************************!
procedure processMessage m:msg
  if debug then
    say "^reg.main.name: Got message name=^msg.name fid=^msg.fid info=^msg.info data=^msg.data"
  endif

  if msg.name eqs "STATE"
    if msg.data eqs "EXIT"
      pipe stop
    elseif msg.data eqs "OPEN"
      call sendMsg ^otherHost "SET" {MODE="DOSET"}
    endif

  elseif msg.name eqs "GET"
    ! fill in the table values
    foreach key inTable msg.data
      set msg.data.^key ^key
    endfor
    ! send back the results
    message/bg send msg.fid ,, "RET" ,, msg.data
    call sendMsg ^{msg.fid} "RET" ^{msg.data}

  elseif msg.name eqs "RET"
    ! fill in the table values
    foreach key inTable msg.data
      res ^key msg.data.^key
    endfor

  elseif msg.name eqs "SET"
    ! loop through the table values
    foreach key inTable msg.data
      res ^key msg.data.^key
    endfor

    ! send back the results
    call sendMsg ^{msg.fid} "ACK" ^{msg.data}

    !call autotest "REMOTE"

  elseif msg.name eqs "OPEN" then
    !Do Nothing

  elseif msg.name eqs "OPENED" then
    !Do Nothing
    if /Bravo isFalse then
      res mode 2
      ! Bug 1459 - test case to set timeRetry and timeLost on Remote
      res remote msg.data
      res msg.fid
      say "setting remote here  msg:^msg"
      ASSERT/text="TEST_RMIF: Get Remote Time Lost property" remote.timeLost eq timelost
      set remote.timeLost  6
      ASSERT/text="TEST_RMIF: Set Remote Time Lost property" remote.timeLost eq 6
      set remote.timeRetry 0.2
      ASSERT/text="TEST_RMIF: Set Remote Time Retry  property" remote.timeRetry eq 0.2
    endif

  elseif msg.name eqs "CLOSE" then
    !Do Nothing

  elseif msg.name eqs "CLOSED" then
    !Do nothing

  elseif msg.name eqs "ACK" then
    !Do nothing
    if /Bravo then
      foreach key inTable msg.data
        if ^key eqs "NEWMODE" and msg.data.^key eq 4 then
            if debug then
              say "        Closing client ^thisHost"
            endif
          stop
        endif
      endfor
    endif

  elseif msg.name eqs "LINKERR" then
    !Do nothing

  elseif msg.name eqs "TIMER"
    if msg.info eq 0 then
      say "timer otherHost ^otherHost msg ^{msg}"
      call autotest ^otherHost
    else
      assert/text="^reg.main.name: test timed out." false
      pipe stop
    endif

  else
    say "Unhandled message ^msg.name = ^msg.data from ^msg.fid"
  endif
return


! This is the core of the automatic test of the GET/SET functions.
!
procedure autotest s:remote
  say "autotest called with ^remote"
  calc mode mode newmode max

  if debug then
    say "^thisHost: Start ^mode (remote = ^remote)"
  endif

  if /Bravo then

    if mode eq 0 then
      res newmode 1
      say "BRAVO mode eq 0 calling sendMsg with ^otherHost"
      call sendMsg ^otherHost "SET" {BAR="B:BAR"}
      call sendMsg ^otherHost "SET" {NEWMODE=^newmode}

    elseif mode eq 3 then
      res newmode 4
      say "BRAVO mode eq 3 calling SET sendMsg with ^otherHost"
      call sendMsg ^otherHost "SET" {NEWMODE=^newmode}
    else
      say "BRAVO mode eq 3 calling GET sendMsg with ^otherHost"
      call sendMsg ^otherHost "GET" {MODE=}
    endif

  else ! Alpha
    if mode eq 1 then
      res mode 2
      if false ISTRUE then
        info "STATEM: Skipping portion of test RMIF Overriding existing registry entry - invalid operation"
      else
        info "Should see warning on RMIF Overriding existing registry entry for ^otherHost ...  otherHP=^otherHP [^thisHost]"
        message/bg sendw ^thisHost ,, "OPEN" ,, {ID=^otherHost,HP=^otherHP}
      endif

    elseif  mode eq 2 then
      res mode 3
      say "----^{otherHost}----GET------------------"
      call sendMsg ^otherHost "GET" {FOO=}

    elseif mode eq 4 then
      if debug then
        say "        Closing client ^thisHost"
      endif

      res foo
      ASSERT/text="TEST_RMIF: Test GET/SET (1 of 2)" foo EQS "B:FOO"
      ASSERT/text="TEST_RMIF: Test GET/SET (2 of 2)" bar EQS "B:BAR"
      pipe stop
    endif

  endif

  if debug then
    say "^thisHost: Done"
  endif
return
