!******************************************************************************!
! Tests that the timeline whose first offset is not for the first element in
! the file.
!
! WARNING: Blue Microsecond files still fail this test, but Blue TC pass
!
! Arguments: None
!
! @bug      NXM-3087 TimeLine Broken for TC Keywords
! @since    3.7.3
! @author:  Jeanette McCall
!******************************************************************************!
startmacro
  switch INTERACTIVE interAct GET DEF=TRUE  SDEF=TRUE  ! for normal interactive test(s)
  switch BASELINE    baseline GET DEF=FALSE SDEF=TRUE  ! for defects or more obscure test case(s)

  ! Save off IOOptions as this test changes IOOptions.SuppressInvalidTimeLineEntryErrors
  env get IOOptions origIOOptions

  ! Specs from this file used for timeline creation
  res referenceFile nxm.sys.test.test_fftout_timeline.prm
  
  ! get expected time at first element
  file open/d refFileTag referenceFile
  invoke timeline refFileTag.getTimeLineHandler()
  ! Get Start Time
  invoke starttime refFileTag.getTime()
  file close refFileTag

  ! files with first offset not for first sample
  res testBlueOffset ram:testBlueOffset_3087.tmp
  res testTCOffset testTCOffset_3087.tmp

  ! Inform tester that warnings are expected (is creation of file without first offset for 1st element)
  info "Expect one warning below for 'TimeLine entries for ram:testBlueOffset_3087.tmp do not start at first element ..."


  ! Create Blue Microsecond File where first offset is not for first element
  ! Test that it has correct start time
  ! env set IOOptions +EnableTimeLineAutoCorrectNoOffset0Entry  ! No longer needed as of 3.9.4
  call createFileOffsetNotFirst referenceFile testBlueOffset
  res blueTimeAt0 FILE(testBlueOffset).getTimeAt(0)
  !status/key testBlueOffset
  assert/text="^reg.main.name: Blue Microsecond Timeline timeAt(0) EQ Timecode" blueTimeAt0 eq starttime

  ! Turn off warnings for the rest of the testing
  env set IOOptions +SuppressInvalidTimeLineEntryErrors

  ! Create BLUE TC Keywords File (from Blue microsecond file) - 1st offset is not for first element
  ! Test that it has correct start time
  convert testBlueOffset KWCONV testTCOffset{USEBLUETCTIMELINE=true} OPTIONS={}
  !status/key testTCOffset
  res tcTimeAt0 FILE(testTCOffset).getTimeAt(0)
  assert/text="^reg.main.name: Blue TC Timeline timeAt(0) EQ Timecode" tcTimeAt0 eq starttime

  call testTCAutocorectWithXStart
  call testTIMELINEAutocorectWithXStart

  ! restore IOOPtions to original
  env set IOOptions origIOOptions

endmacro

!******************************************************************************!
! Main process message for this macro. Should be right after the ENDMACRO.
!******************************************************************************!
procedure processMessage m:msg
  if msg.name eqs "MAIN" then
    assert/text="^reg.main.name: Interactive tests for STATUS" msg.data eqss "PASS"
    pipe stop
  else
    say "^reg.main.name: Unhandled message name: ^msg.name from fid: ^msg.fid data: ^msg.data"
  endif
return

!******************************************************************************!
! If an unexpected exception is caught, mark test as failed, unless it is expected
!******************************************************************************!
procedure processException m:emsg
  if expectedException REXISTS then
    assert/text="^reg.main.name: Expected ERROR starts with: ^{expectedException}" expectedException EQSS emsg.data.message
    remove expectedException
  else
    assert/text="^reg.main.name: Caught unexpected exception ^{emsg.data}" "FALSE" isTrue
    if "Trace" SUBS ENV.DEBUG then invoke ,, emsg.data.printStackTrace()
  endif
return

!******************************************************************************!
! Create a File that does not have a TimeLine entry for the first element
!******************************************************************************!
procedure createFileOffsetNotFirst fn:referenceFile fn:fileToCreate

  !-----------------------------------------------------------
  ! Get information from the reference file
  !-----------------------------------------------------------
  ! Get number elements and delta
  status referenceFile SIZE=L:numElements XDELTA=D:delta

  ! Get TimeLine from reference file in table form
  file open/d refFileTag referenceFile
  invoke timeline refFileTag.getTimeLineHandler()
  ! Get bytes per element
  invoke L:bpe refFileTag.getBPE()
  ! Get Start Time
  invoke starttime refFileTag.getTime()

  file close refFileTag

  ! create table with timeline
  invoke timelinetbl=timeline.toTable(12,bpe)
  !res timelinetbl

  !-----------------------------------------------------------
  ! create a timeline that does not have an entry for the first element
  ! (equivalent to reference file but missing first entry)
  !-----------------------------------------------------------
  res tableNoFirstOffset {}
  call tableRemoveEntry timelinetbl 0 tableNoFirstOffset
  invoke timeline_result=nxm.sys.test.TestTimelineCreator.timelineFromTable(delta,bpe,tableNoFirstOffset) 

  !-----------------------------------------------------------
  ! create a new file with this timeline that does not have an
  ! entry for the first element
  !-----------------------------------------------------------
  noop referenceFile fileToCreate ! do not set tl=1 as will replace timeline and it messes up starttime

  file open/d/a newFileTag fileToCreate
  invoke ,, newFileTag.setTimeLineObject(timeline_result)
  file close newFileTag

return

!******************************************************************************!
! Create a new table with the specified entry removed from the original
! (Note: we can not access the Table's remove method directly from the macro language)
!
!******************************************************************************!
procedure tableRemoveEntry T:origtable S:keyToDelete T:newtable

  foreach S:key INTABLE origtable
    if key NEQS keyToDelete then
      TABLE newtable SETKEY ^key origtable.^key
    endif
  endfor

return

!******************************************************************************!
! Test for autocorrect with XStart and for non-integer offsets - TC Keywords
!
!******************************************************************************!
procedure testTCAutocorectWithXStart

  res initTime "2023:05:17::05:20:10"
  new nxm.sys.lib.Time(^initTime) starttime
  invoke startsec starttime.getSec()
  res delta 0.5
  res xstart 0.345
  res initPlusXStart "2023:05:17::05:20:10.345"
  new nxm.sys.lib.Time(^initPlusXStart) expectedTime
  res elem 400.0

  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  ! Make up a TCSAMPLE_1 that is not the first element
  ! and is not an integer valuer
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  ! Set the ceiling of this non-integer value
  res ceil_tcsample 301
  ! The difference back from the ceiling we are using
  res diff2ceil 0.6
  ! Calculate the non-integer offset
  calc origSample ceil_tcsample diff2ceil -
  ! Create the time hack, based on shifiting slightly forward in time
  calc adj_tcsample 302   ! make skip forward to 302ish time
  calc timehackadj  delta adj_tcsample *
  ! Calculate the amount of shift in time hack FSEC expected
  ! when NOOP adjusts the SAMPLE entry to be the ceiling of
  ! the original offset
  calc shift2ceil diff2ceil delta *
  ! Get the TC_WHOLE_1 and TC_SEC_1 values
  invoke hackTime starttime.addSec(timehackadj)
  invoke hackWDouble hackTime.getWSec()
  invoke hackFDouble hackTime.getFSec()

  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  ! Make the file with a TCSAMPLE that is not an integer and not the first element
  ! Make it have a XStart too
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  waveform tc_for_rich.tmp ELEM=^elem FORM=CF START=^xstart delta=^delta SHAPE=sin
  headermod tc_for_rich.tmp TC="2023:05:17::05:20:10"
  KEY tc_for_rich.tmp ADD NAME=TCSAMPLE_1 VALUE=^origSample &
      NAME2=TC_WHOLE_1 VALUE2=^hackWdouble NAME3=TC_FRAC_1 VALUE3=^hackFDouble

  file open tcFileTag tc_for_rich.tmp
    invoke fileTimeLine tcFileTag.getTimeLineHandler()
  file close tcFileTag
  invoke firstTime fileTimeLine.getTimeAt(0)
  assert/text="^reg.main.name: TC autocorrect has XStart as well as TIMECODE" firstTime EQ expectedTime

  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  ! NOOP (any write) will adjust the TC hacks to integer
  ! offset and the 1st being for the first element
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  noop tc_for_rich.tmp tc_copy_for_rich.tmp /TL=2
  ! since we put in a TC_SAMPLE_1 for the first element the time hack is now TC_SAMPLE_2
  ! Check to make sure the sample is now the integer ceiling value of the original sample
  ! Check to make sure the FRAC has been updated appropriately
  key tc_copy_for_rich.tmp GET TCSAMPLE_2 nooptcsample
  key tc_for_rich.tmp GET TC_FRAC_1 tcfrac
  key tc_copy_for_rich.tmp GET TC_FRAC_2 nooptcfrac
  assert/text="^reg.main.name: TCSAMPLE adjusted to ceiling " nooptcsample eq ceil_tcsample
  calc expected_frac tcfrac shift2ceil +
  assert/text="^reg.main.name: TC_FRAC adjusted to match" nooptcfrac eqt expected_frac

  erase tc_copy_for_rich.tmp tc_for_rich.tmp

return

!******************************************************************************!
! Test for autocorrect with XStart - TIMELINE keyword
!
!******************************************************************************!
procedure testTIMELINEAutocorectWithXStart

  res initTime "2023:05:17::05:20:10"
  new nxm.sys.lib.Time(^initTime) starttime
  invoke startsec starttime.getSec()
  res delta 0.5
  res xstart 0.246
  res initPlusXStart "2023:05:17::05:20:10.246"
  new nxm.sys.lib.Time(^initPlusXStart) expectedTime
  res elem 400.0

  res timeline_res (0.5,1.0e-6,301,^startsec)

  waveform blue_for_rich.tmp ELEM=^elem FORM=CF START=^xstart delta=^delta SHAPE=sin
  headermod blue_for_rich.tmp TC="2023:05:17::05:20:10"
  KEY blue_for_rich.tmp ADD NAME=TIMELINE VALUE=^timeline_res

  file open blueFileTag blue_for_rich.tmp
    invoke fileTimeLine blueFileTag.getTimeLineHandler()
  file close blueFileTag
  invoke firstTime fileTimeLine.getTimeAt(0)
  assert/text="^reg.main.name: TIMELINE autocorrect has XStart as well as TIMECODE" firstTime EQ expectedTime

  erase blue_for_rich.tmp
return
