!******************************************************************************!
! Tests the STATUS command.
!
! Arguments: None
!
! @bug      None
! @since    NeXtMidas 1.5.9
! @author:  Jay Hallam / J. Czechowski IV / Neon Ngo
!******************************************************************************!
startmacro
  switch INTERACTIVE interAct GET DEF=TRUE SDEF=TRUE
  switch BASELINE    baseline GET DEF=FALSE SDEF=TRUE

  call setDatDir
  invoke GcontrolExists reg.shell.M.dictionary.isDictionaryEntry(GCONTROL)

  call test_basics
  call test_timecode
  call test_detached
  call test_advanced
  call test_mimetypes
  call test_image

  res testCases {}
  res testCases.TEST1 {CMD="STATUS ^{datDir}.world.prm /TIME",&
                      INST="Expected:\n&
                      1 information about the world.prm file.\n&
                      2 a WARNing stating that no timeline\n  keywords were found."}
  res testCases.TEST2 {CMD="STATUS/KEY ^{datDir}.cities.txt",&
                      INST="Expected:\n&
                      'No keywords defined for TextFile class' message\n\n&
                      location of message:\n&
                      after cities.txt status information\n\n&
                      It should NOT say 'BaseFile'"}
  res testCases.TEST3 {CMD="STATUS/DATA ^{datDir}.apenny.prm(1:3)",&
                      INST="Expected: a status with a partial data listing of &
                            the file apenny.prm."}

  ! Platinum file with /KEY and /DATA -- the /KEY was not working in the
  ! 2012-12-12 snapshot, so this checks for that issue.
  res testCases.TEST4 {CMD="STATUS/DATA/KEY nxm.sys.test.testplat1001.cdif(:256)",&
                      INST="Expected:\n\n&
                      STATUS/DATA/KEY of a Platinum file\n&
                      - keywords shown\n&
                      - followed by a partial data listing\n\n&
                      2 infos (top+bottom) about not having full support for PLATINUM files\n\n&
                      2 warnings (top+bottom) about fixing TimeCode+TC_PREC"}

  ! A version with a Type 5000 file showing the individual records and using /D
  ! and /K in place of /DATA and /KEY. Also /D= is using a non-default value.
  res testCases.TEST5 {CMD="STATUS/D=4/K ^{datDir}.cities.prm",&
                      INST="Expected:\n\n&
                      A status listing of a Type 5010 file\n\n&
                      - keywords shown:\n  &
                        (VER=1.1, IO=NeXtMidas, CREATOR=NXM2.9.1\n\n&
                      - followed by a listing with exactly 4 entries\n  &
                        (0 through exclusive).\n\n&
                      - The listing should show POS= and NAME=\n  &
                        in an easy-to-read form."}

  ! A variant of #5 but with a CSV file.
  res testCases.TEST6 {CMD="STATUS/D=4/K ^{datDir}.airports.csv{HEADERROWS=1}",&
                      INST="There should be a status listing of a CSV file. It &
                            should indicate that 'No keywords defined for CsvFile &
                            class' and should show a listing with exactly 4 entries &
                            (0 through 3 inclusive). The listing should show &
                            AIRPORT_NAME=, CODE=, LATITUDE= and LONGITUDE= in an &
                            easy-to-read form."}

  ! Test for new Azim/Elev/Roll with Type 5000 (Bug 2709)
  headermod/create ram:test6 TYPE=5000 COMPONENTS=(POS/VD/CARTESIAN/DISTANCE_M,&
                                                   VEL/VD/CARTESIAN/SPEED_M_S,&
                                                   ACC/VD/CARTESIAN/ACCELERATION_M_S2) &
                             RF=TOP QUADWORD(1)=1000 QUADWORD(2)=20 QUADWORD(3)=30 &
                                    QUADWORD(4)=40   QUADWORD(5)=50 QUADWORD(6)=60
  res testCases.TEST6 {CMD="status ram:test6",&
                      INST="There should be a status listing of a BLUE file.\n&
                            It should list:\n &
                            'Altitude  : 1000 m'\n &
                            'Latitude  : 20 deg'\n &
                            'Longitude : 30 deg'\n &
                            'Azimuth   : 40 deg'\n &
                            'Elevation : 50 deg'\n &
                            'Roll      : 60 deg'"}

  ! Test for new Sample Rate & Duration with Type 1000 (Bug 2709)
  waveform ram:test7 DURATION=3.5 DELTA=1/1e6
  res testCases.TEST7 {CMD="status ram:test7",&
                      INST="There should be a status listing of a BLUE file.\n&
                      It should list:\n &
                      'Sample Rate : 1,000,000 Hz'\n &
                      'Duration    : 3.5 sec'"}

  ! Test for new Frame Rate & Duration with Type 2000 (Bug 2709)
  waveform ram:test8 ELEM=3K
  headermod ram:test8 TYPE=2000 FS=1K XSTART=0 XDELTA=1e-6 XUNITS=FREQUENCY_HZ &
                                      YSTART=0 YDELTA=0.5  YUNITS=TIME_S
  res testCases.TEST8 {CMD="status ram:test8",&
                      INST="There should be a status listing of a BLUE file.\n&
                      It should list:\n &
                      'Frame Rate : 2.0 Hz'\n &
                      'Duration   : 1.5 sec'"}


  if interAct AND baseline AND GcontrolExists then
    ! Make sure that status of a file without a timeline does not
    ! generate and error if no timeline exists
    res expectException "FALSE"

    pipe on
      panel/msgid=MAIN/setup/controls=gc
      gcontrol label macro "MACRO"
      gcontrol menu MAIN "Exit with Status = " "PASS,FAIL" /tleft
      set gc.MAIN.itemColors {PASS=GREEN,FAIL=RED}
      gcontrol text idtext "INSTRUCTIONS" &
                      "EXPECTED in shell on right:\n&
                       1) STATUS/D on 2 files\n&
                       2) 1st - world.prm, 2nd cities.prm\n&
                       3) each having headers printed above corresponding data.\n\n&
                       CLICK on each of the tests below" 24 16 /title

      table testCases GETKEYS/S testNames
      gcontrol menu testid "Test files to STATUS" "^testNames"  /nc=1
      shellgui/id=idshellgui/attach
      run status/d ^{datDir}.world.prm
      say " "
      run status/d ^{datDir}.cities.prm
    pipe off

    %test_status_large_platinum_keyword ! NXM-2971
    %test_status_starttime              ! NXM-2037
  endif  ! end if interAct
endmacro

!******************************************************************************!
procedure processMessage m:msg
  !say "msg.name ^msg.name, data ^msg.data"

  if (msg.name EQS "MAIN") then
    assert/text="^reg.main.name: Interactive tests for STATUS" msg.data eqs "PASS"
    pipe stop

  elseif (msg.name EQS "TESTID") then
    ! clear text in SHELLGUI before next test case
    message func=sendx id=idshellgui name="CLEAR"

    res testCase testCases.^{msg.data}

    res gc.idtext.value testCase.inst

    say "nM> ^{testCase.CMD}"
    run testCase.CMD

  else
    say "^reg.main.name: Unhandled message name: ^msg.name from fid: ^msg.fid data: ^msg.data"
  endif
return

!******************************************************************************!
procedure processException m:emsg
!
!  NOTE: This procedure is automatically called if an exception is thrown in the macro
!
  if expectException REXISTS and expectException isTRUE then
    result expectException "FALSE"
    assert/text="^{reg.main.name}: advanced/quoted name " ftype NREXISTS
  else
    assert/text="^{reg.main.name}: unexpected exception " 1 EQ 2
    res/all emsg
    stop
  endif
return

!******************************************************************************!
! Set the dat directory
!******************************************************************************!
procedure setDatDir
  invoke nxmMajor env.nmversion.subString(0,1)
  invoke major java.lang.Integer.valueOf(nxmMajor)
  if major GE 4 then
    invoke s:datDir           nxm.sys.test.DatLocator.getDatDirLocation()
    invoke s:datDirSlash      nxm.sys.test.DatLocator.getDatDirSlashLocation()
    invoke z:sysDatFull       nxm.sys.test.DatLocator.sysDatFull()
    invoke z:sysTestDatExists nxm.sys.test.DatLocator.sysTestDatExists()
  else
    set s:datDir           "nxm.sys.dat"
    set s:datDirSlash      "nxm/sys/dat"
    set z:sysDatFull       true
    set z:sysTestDatExists false
  endif
return

!******************************************************************************!
procedure test_basics
  !
  ! Test the basics: abbreviations of tags available for all data files
  !
  status ^{datDir}.apenny.prm type=ftype &
                sz=size form=format ds=datastart dr=dataRep &
                xs=xstart  xd=xdelta xu=xunits &
                ys=ystart  yd=ydelta yu=yunits tc=timecode

  assert/text="^{reg.main.name}:basics/abbrev TYPE" ftype  EQ 2000
  assert/text="^{reg.main.name}:basics/abbrev FORM" format EQS "SB"
  assert/text="^{reg.main.name}:basics/abbrev SZ"   size EQ 128
  assert/text="^{reg.main.name}:basics/abbrev DS"   datastart EQ 512
  assert/text="^{reg.main.name}:basics/abbrev DR"   dataRep EQS "EEEI"

  assert/text="^{reg.main.name}:basics/abbrev XS"   xstart EQ 0
  assert/text="^{reg.main.name}:basics/abbrev XD"   xdelta EQ 1
  assert/text="^{reg.main.name}:basics/abbrev XU"   xunits EQ 0
  assert/text="^{reg.main.name}:basics/abbrev YS"   ystart EQ 0
  assert/text="^{reg.main.name}:basics/abbrev YD"   ydelta EQ 1
  assert/text="^{reg.main.name}:basics/abbrev YU"   yunits EQ 0
  assert/text="^{reg.main.name}:basics/abbrev TC"   timecode EQ 0

  !
  ! Test the basics: long names for all data files
  !
  status ^{datDir}.apenny.prm type=ftype &
                size=size format=format datastart=datastart datarep=datarep &
                xstart=xstart xdelta=xdelta xunits=xunits &
                ystart=ystart ydelta=ydelta yunits=yunits

  assert/text="^{reg.main.name}:basics/long names TYPE"      ftype  EQ 2000
  assert/text="^{reg.main.name}:basics/long names SIZE"      size EQ 128
  assert/text="^{reg.main.name}:basics/long names FORMAT"    format EQS SB
  assert/text="^{reg.main.name}:basics/long names DATASTART" datastart EQ 512
  assert/text="^{reg.main.name}:basics/long names DATAREP"   dataRep EQS "EEEI"

  assert/text="^{reg.main.name}:basics/long names XSTART" xstart EQ 0
  assert/text="^{reg.main.name}:basics/long names XDELTA" xdelta EQ 1
  assert/text="^{reg.main.name}:basics/long names XUNITS" xunits EQ 0
  assert/text="^{reg.main.name}:basics/long names YSTART" ystart EQ 0
  assert/text="^{reg.main.name}:basics/long names YDELTA" ydelta EQ 1
  assert/text="^{reg.main.name}:basics/long names YUNITS" yunits EQ 0
  assert/text="^{reg.main.name}:basics/long names TIMECODE" timecode EQ 0

  !
  ! Type 2000 specific
  !
  status ^{datDir}.apenny.prm fs=framesize
  assert/text="^{reg.main.name}:basics/abbrev type 2000 FS" frameSize EQ 128
  status ^{datDir}.apenny.prm framesize=framesize
  assert/text="^{reg.main.name}:basics/long names type 2000 FRAMESIZE" frameSize EQ 128

  !
  ! Type 3000 specific
  !
  status ^{datDir}.testxy3000.prm nsr=numSubRecs sr(1)=sr1 sr(2)=sr2 sr(3)=sr3 sr(4)=sr4
  assert/text="^{reg.main.name}:basics/abbrev type 3000 NSR" numSubRecs EQ 4

  assert/text="^{reg.main.name}:basics/abbrev type 3000 SR(1)" sr1.NAME   EQS "ABSC" AND &
                                                               sr1.FORMAT EQS "SF"  AND &
                                                               sr1.OFFSET EQ 0

  assert/text="^{reg.main.name}:basics/abbrev type 3000 SR(2)" sr2.NAME EQS "ORD" AND &
                                                               sr2.FORMAT EQS "SF" AND &
                                                               sr2.OFFSET EQ 4

  assert/text="^{reg.main.name}:basics/abbrev type 3000 SR(3)" sr3.NAME EQS "ORD2" AND &
                                                               sr3.FORMAT EQS "SF" AND &
                                                               sr3.OFFSET EQ 8

  assert/text="^{reg.main.name}:basics/abbrev type 3000 SR(4)" sr4.NAME   EQS "ORD3" AND &
                                                               sr4.FORMAT EQS "SF"   AND &
                                                               sr4.OFFSET EQ 12

  status ^{datDir}.testxy3000.prm sr(ABSC)=srABSC
  assert/text="^{reg.main.name}:basics/abbrev type 3000 SR(1) by name" &
                                                               sr1.NAME   EQS srABSC.NAME AND &
                                                               sr1.FORMAT EQS srABSC.FORMAT  AND &
                                                               sr1.OFFSET EQ  srABSC.OFFSET
  set L:myRes 1
  status ^{datDir}.testxy3000.prm sr(MYRES)=srByRes
  assert/text="^{reg.main.name}:basics/abbrev type 3000 get SR(1) by result" &
                                                               srByRes.NAME   EQS srABSC.NAME AND &
                                                               srByRes.FORMAT EQS srABSC.FORMAT  AND &
                                                               srByRes.OFFSET EQ  srABSC.OFFSET


  remove numSubRecs
  status ^{datDir}.testxy3000.prm NUMBERSUBRECORDS=numSubRecs
  assert/text="^{reg.main.name}:basics/long names type 3000 NUMBERSUBRECORDS" numSubRecs EQ 4

  !
  ! Type 5000 specific
  !
  status ^{datDir}.cone5000.prm nc=numcomp rf=refFrame c(1)=c1 c(2)=c2 c(3)=c3 c(4)=c4
  assert/text="^{reg.main.name}:basics/abbrev type 5000 NC" numcomp EQ 4
  assert/text="^{reg.main.name}:basics/abbrev type 5000 RF" refFrame EQS "ECR"

  assert/text="^{reg.main.name}:basics/abbrev type 5000 C(1)" c1.NAME   EQS "POS"        AND &
                                                              c1.FORMAT EQS "VD"         AND &
                                                              c1.OFFSET EQ   0           AND &
                                                              c1.TYPE   EQS "GEODETIC"   AND &
                                                              c1.UNITS  EQS "DISTANCE_M"

  assert/text="^{reg.main.name}:basics/abbrev type 5000 C(2)" c2.NAME   EQS "POSP"       AND &
                                                              c2.FORMAT EQS "VD"         AND &
                                                              c2.OFFSET EQ   24          AND &
                                                              c2.TYPE   EQS "GEODETIC"   AND &
                                                              c2.UNITS  EQS "DISTANCE_M"

  assert/text="^{reg.main.name}:basics/abbrev type 5000 C(3)" c3.NAME   EQS "CONE"       AND &
                                                              c3.FORMAT EQS "VD"         AND &
                                                              c3.OFFSET EQ   48          AND &
                                                              c3.TYPE   EQS "UNDEFINED"  AND &
                                                              c3.UNITS  EQS "NONE"

  assert/text="^{reg.main.name}:basics/abbrev type 5000 C(4)" c4.NAME   EQS "NAME"       AND &
                                                              c4.FORMAT EQS "1A"         AND &
                                                              c4.OFFSET EQ   72          AND &
                                                              c4.TYPE   EQS "UNDEFINED"  AND &
                                                              c4.UNITS  EQS "NONE"


  status ^{datDir}.cone5000.prm NUMBERCOMPONENTS=numcomp REFERENCEFRAME=refFrame
  assert/text="^{reg.main.name}:basics/long names type 5000 NC" numcomp EQ 4
  assert/text="^{reg.main.name}:basics/long names type 5000 REFERENCEFRAME" refFrame EQS "ECR"

  !
  ! Original NXM Type 6000 specific (Bug 2954), since nxm360
  !
  status nxm.sys.test.t6000_null_in_kwdata.prm sr(1)=sr1
  assert/text="^{reg.main.name}:basics/abbrev Original type 6000 SR(1)" sr1.NAME EQS "F1"     AND &
                                                                        sr1.FORMAT EQS "1A"   AND &
                                                                        sr1.OFFSET EQ 0       AND &
                                                                        sr1.UNITS EQS "NONE"

  !
  ! New NXM Type 6000 specific (Bug 2954), since nxm360
  !
  status ^{datDir}.test6000.prm sr(1)=sr1 
  assert/text="^{reg.main.name}:basics/abbrev New NXM type 6000 SR(1)" sr1.NAME EQS "F1"     AND &
                                                                       sr1.FORMAT EQS "1A"   AND &
                                                                       sr1.OFFSET EQ 0       AND &
                                                                       sr1.UNITS EQS "NONE"

  !
  !  XM Type 6000 specific (Bug 2954), since nxm360
  !
  status nxm.sys.test.t6000_xm.prm sr(1)=sr1 
  assert/text="^{reg.main.name}:basics/abbrev XM type 6000 SR(1)" sr1.NAME EQS "SUBREC1" AND &
                                                                  sr1.FORMAT EQS "SI"    AND &
                                                                  sr1.OFFSET EQ 0        AND &
                                                                  sr1.UNITS EQS "NONE"

return

!******************************************************************************!
procedure test_advanced
  !
  ! Type 5000 QUADWORDS
  !
  noop ^{datDir}.cone5000.prm temp_status_5000_quadwords
  headermod temp_status_5000_quadwords QW(10)=2007
  status temp_status_5000_quadwords QW(10)=qw10_onebase QUADWORD(9)=qw10_zerobase
  assert/text="^{reg.main.name}:advanced: type 5000 QW(10) vs QUADWORD(9)" qw10_zerobase EQ 2007 AND &
                                                                           qw10_onebase EQ qw10_zerobase

  erase temp_status_5000_quadwords
  !
  ! Shape Files
  !
  status ^{datDir}.world.shp type=typeShape
  assert/text="^{reg.main.name}:advanced: SHAPEFILE.type" typeShape EQ 9994

  !
  ! Text Files
  !
  fname filename name="version" ext="txt" opt=sys
  status filename size=textSize
  assert/text="^{reg.main.name}:advanced: TEXTFILE.size" textSize GT 0

  !
  !  Test status on quoted file name
  !
  if "nonexistingfileName" FEXISTS then
    WARNING "Can not run test for quoted file name because the file 'nonexistingfileName' was found"
  else
    ! Here I am checking to make sure status uses the quoted filename
    ! and not the result
    remove ftype
    result nonexistingfileName "apenny"

    ! Expect an exception ... we catch the exception in the macro
    result expectException "TRUE"
    status "nonexistingfileName" type=ftype
  endif

return

!******************************************************************************!
procedure test_detached
! Test file with a -1 in the header detach field (DR#1554).  Pre NXM 270 this would
! throw an exception
  status nxm.sys.test.blue_file_with_detach_minus1.tmp size=detSize
  assert/text="^{reg.main.name}: detached with -1 value in header field" detSize EQ 1

return

!******************************************************************************!
procedure test_timecode
  header/create ram:temp_timecode timecode=2008:01:01:00:00:00
  status ram:temp_timecode timecode=timecode
  assert/text="^reg.main.name: TimeCode" timecode eq 2008:01:01:00:00:00

  ! test for Bug 1794 TC abbreviation for TimeCode
  status ram:temp_timecode tc=tc
  assert/text="^reg.main.name: TC abbreviation for TimeCode" tc eq 2008:01:01:00:00:00

  keyword/scope=main ram:temp_timecode set tc_prec "E-8"
  info "A warning about an invalid TC_PREC value should be printed on the next line."
  status ram:temp_timecode time=t
  assert/text="^reg.main.name: Test with illegal TC_PREC" t eq 2008:01:01:00:00:00
return

!******************************************************************************!
! Tests handling of a number of MIME types
procedure test_mimetypes
  res mimeTypes  {html="text/html",&
                  htm ="text/html",&
                  mm  ="text/plain",&
                  key ="text/plain",&
                  txt ="text/plain",&
                  java="text/plain",&
                  js  ="application/x-javascript",&
                  c   ="text/plain",&
                  css ="text/css",&
                  h   ="text/plain",&
                  tmp ="application/octet-stream",&
                  prm ="application/octet-stream",&
                  pkt ="application/octet-stream",&
                  det ="application/octet-stream",&
                  jnlp="application/x-java-jnlp-file",&
                  jar ="application/x-java-archive"}
  foreach key inTable mimeTypes
    invoke mimeType nxm.sys.lib.BaseFile.getMimeType(this,"myfile.^key")
    assert/text="^reg.main.name: Checking MIME type for ^{key}" mimeTypes.^{key} eqs mimeType
  endfor

  ! *Java class files can use any of the following MIME types: "application/octet-stream",
  ! "application/x-java", "application/java-byte-code", "application/x-java-class",
  ! "application/java", "application/java-class", "application/x-java-vm"

  call checkMimeType ^{datDir}.Sunset.jpg        "image/jpeg"
  call checkMimeType ^{datDir}.network.png       "image/png"
  call checkMimeType ^{datDir}.airports.csv      "text/csv" ! <-- could also use "text/comma-separated-values"
  call checkMimeType ^{datDir}.cities.prm        "application/octet-stream"
  call checkMimeType ^{datDir}.cities.txt        "text/plain"
  call checkMimeType ^{datDir}.world.prm         "application/octet-stream"
  call checkMimeType ^{datDir}.world.shp         "application/octet-stream" ! <-- may change in fututre
  call checkMimeType ^{datDir}.world.dbf         "application/octet-stream" ! <-- may change in fututre
  call checkMimeType ^{datDir}.hwconfig.key      "text/plain"
  if ^{env.NMROOT} EQS "classpath:" then
    warn "SKIPPING ^reg.main.name 'call checkMimeType nxm.sys.test.package.html' since the file is not available in the jar. - TODO add nxm.sys.test.package.html to the jar"
    warn "SKIPPING ^reg.main.name 'call checkMimeType nxm.sys.jars.wbp-support.jar' since jar files are not built into the jar. - TODO fix the jar file issue"
    info "SKIPPING ^reg.main.name 'call checkMimeType nxm.sys.prim.waveform.java' since java files are not included in jar."
  else
    call checkMimeType nxm.sys.test.package.html     "text/html"
    call checkMimeType nxm.sys.jars.wbp-support.jar  "application/x-java-archive"
    call checkMimeType nxm.sys.prim.waveform.java    "text/plain"
  endif
  call checkMimeType nxm.sys.test.kmlSamples.kml   "application/vnd.google-earth.kml+xml"
  call checkMimeType nxm.sys.test.jnlp_master.jnlp "application/x-java-jnlp-file"
  call checkMimeType nxm.sys.exp.waveform.exp      "text/plain"
  call checkMimeType nxm.sys.prim.waveform.class   "application/octet-stream" ! *See note above

return

!******************************************************************************!
procedure checkMimeType fn:fname s:expMimeType
  status fname MimeType=actMimeType class=class
  assert/text="^reg.main.name: Checking MIME type for ^{fname}" expMimeType eqs actMimeType
return

!******************************************************************************!
! Test cases related to images
procedure test_image
  status nxm.sys.test.etna.jpg ImageMetadata=ImageMetadata
  assert/test ImageMetadata rexists
return
