!******************************************************************************!
! Test drawing of a polygon in Layert5 and GeodeticUtil.insidePolygon
! on dateline crossing cases
! TODO: actually directly call GeodeticUtil.insidePolygon with these polys
! color point feature green if inside and red if outside
!
! Arguments: None
!
! @issue    NXM-3558 GeodeticUtil.insidePolygon
! @author:  Zachary Matthews
! @since:   NeXtMidas 4.0.2
!******************************************************************************!
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)

  call setDatDir

  if interAct then
    set l:polyTblIdxMax 7                 ! Max size of polygon table
    set l:polyTblIdx 1                    ! Current index of polygon table
    res t:polyTbl {}                      ! Table of polygon points
    new java.util.ArrayList() polyPosList ! ArrayList of polygon points as Positions
    set z:addPtsEnabled false             ! Flag for enabling of adding polygon points
    set Z:checkInsideEnabled false        ! Flag for enabling of checking a point inside the polygon

    set instructions "DR #827438-3 GeodeticUtil.insidePolygon would show.\n\n&
                      Click Add Points to enable polygon point plotting or reset the current polygon plot\n\n&
                      Click Check Inside to enable plotting a feature inside a polygon to test GeodeticUtil.insidePolygon"

    pipe on
      panel/msgid=MAIN/setup/controls=gc
      gcontrol label macro "Test MACRO"
      gcontrol menu  main "Exit with Status =" "PASS,FAIL" TABLE={ItemColors={PASS="GREEN",FAIL="RED"}} /tleft

      gcontrol text  idtext "Instructions" instructions 24 13 /title

      plot/id=geoPlot/xcnt=click/msgid=MAIN    ^{datDir}.world.prm View=GEO
      plot/id=latLonPlot/xcnt=click/msgid=MAIN ^{datDir}.world.prm View=LATLON

      gcontrol button addPoints   "" "Add Points"
      gcontrol button checkInside "" "Check Inside"
      gcontrol/toggle button method "insidePolygon method" "ORIGINAL" "ORIGINAL" 
      set gc.checkInside.enabled false
    pipe off

  endif
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: User indicated tests" msg.data eqss "PASS"
    pipe stop
  elseif msg.name eqs "ADDPOINTS" then
    ! Reset flags and variables for adding points
    set gc.checkInside.enabled false ! Disable the check inside button since in add-point mode
    set checkInsideEnabled false     ! Disable the check-inside flag
    set addPtsEnabled true           ! Enable the add-points flag
    set l:polyTblIdx 1               ! Set the current index of the polygon Table to 1
    set t:polyTbl {}                 ! Reset the polygon point Table
    invoke ,, polyPosList.clear()    ! Reset the polygon Position ArrayList

    ! Clear both plots
    message send geoPlot    NAME=CLOSEFILE DATA="*"
    message send geoPlot    NAME=openfile data="^{datDir}.world.prm
    set reg.geoPlot.removeFeature "*"
    message send latLonPlot NAME=CLOSEFILE DATA="*"
    message send latLonPlot NAME=openfile data="^{datDir}.world.prm
    set reg.latLonPlot.removeFeature "*"
  elseif msg.name eqs "CHECKINSIDE" then
    set checkInsideEnabled true
    set gc.addPoints.enabled true ! Reenable the add-points button, giving the option to reset the polygon if need be
  elseif msg.name eqs "MARK" and (msg.fid eqs "GEOPLOT" or msg.fid eqs "LATLONPLOT") then
    res clickedPt msg.data
    ! If the plot is clicked on when adding polygon points enabled, add the click point to the polygon
    if addPtsEnabled then
      ! Add point to polygon points Table
      set polyTbl.^polyTblIdx {name="POINT_^polyTblIdx",POS=(0.0, ^clickedPt.LAT, ^clickedPt.LON),FLAG=(9,0,2,0,-9,0,5,5),CONN=1}
      ! Add point to polygon Position ArrayList
      invoke polyPosListEntry nxm.sys.lib.Position.fromGeo(0.0,^clickedPt.LAT,^clickedPt.LON)
      invoke ,, polyPosList.add(polyPosListEntry)
      ! Increment the polygon Table index by 1
      calc l:polyTblIdx polyTblIdx 1 +
      ! If the last point in the polygon has been reached, complete the polygon and disable adding more points
      if polyTblIdx eq polyTblIdxMax then
        set gc.addPoints.enabled false     ! Disable the add-points button
        set addPtsEnabled false            ! Disable the add-points flag
        set gc.checkInside.enabled true    ! Enable the check-inside button
        set polyTbl.^polyTblIdx polyTbl.1  ! Copy the first row as the last row in the polygon point Table to complete the polygon

        ! Copy the first row as the last row in the polygon Positions ArrayList to complete the polygon
        invoke polyPosListEntry polyPosList.get(0)
        invoke ,, polyPosList.add(polyPosListEntry)
      endif
      ! Plot the modified polygon
      call updatePoly
    elseif checkInsideEnabled then
      ! Convert clicked point into a Position
      invoke posToBeChecked nxm.sys.lib.Position.fromGeo(0.0,^clickedPt.LAT,^clickedPt.LON)

      ! Call this block if calling nxm.sys.lib.GeodeticUtil.insidePolygon(Position,int,double[])
      calc l:arraySize polyPosList.size() 2 *
      new double[^arraySize] polyPointArray
      do l:count 0 polyPosList.size()-1 1
        invoke pos polyPosList.get(count)
        invoke posLon pos.getLon()
        invoke posLat pos.getLat()
        set polyPointArray(^count*2)   posLon
        set polyPointArray(^count*2+1) posLat
      enddo

      if gc.method.value EQS "|ORIGINAL|" then
        invoke posIsInsidePolygon nxm.sys.lib.GeodeticUtil.insidePolygon(posToBeChecked,2,polyPointArray)
      else
        ! Call this block if calling nxm.sys.lib.GeodeticUtil.insidePolygon(Position,List<Position>)
        invoke posIsInsidePolygon nxm.sys.lib.GeodeticUtil.insidePolygon(posToBeChecked, polyPosList)
      endif

      ! Add checked point to the plot
      if posIsInsidePolygon then
        set color "GREEN"
      else
        set color "RED"
      endif
      call addFeature clickedPt.LON clickedPt.LAT color
    endif
  else
    !say "Unhandled message name: ^msg.name from fid: ^msg.fid data: ^msg.data"
  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

!******************************************************************************!
! Create the test file for the polygon and plot it
!******************************************************************************!
procedure updatePoly

    ! create the Type 5000 file to display
    header/create ram:poly TYPE=5000 SR=(NAME/4A,POS/VD,FLAG/8B,CONN/SB)

    file open/d/w out ram:poly ! open the file for editing

    ! update the file
    foreach row INTABLE/V polyTbl
      invoke ,, out.writeDataTable(row)
    endfor

    ! close the file
    file close out ! cleanup resource

    ! Clear both plots
    message send geoPlot    NAME=CLOSEFILE DATA="*"
    message send latLonPlot NAME=CLOSEFILE DATA="*"

    ! Redraw both plots with the modified polygon
    set quals {LAYER={LT="T5",name=LT5_POLYGON,autoselectenable=click,AutoSelectMode=Pixel}}
    message send geoPlot     name=openfile data="^{datDir}.world.prm|ram:poly^{quals}"
    message send latLonPlot  name=openfile data="^{datDir}.world.prm|ram:poly^{quals}"
return

!******************************************************************************!
! Add the feature
!******************************************************************************!
procedure addFeature d:xVal[0] d:yVal[0] s:color[""]
  feature label=geoPlotPt    table={NAME="GEO_PLOT_POINT",TYPE=SYMBOL,X=^xVal,Y=^yVal,&
                                  COLOR=^color,LINE={SYMBOL="UTRI"}} plot=geoPlot
  feature label=latLonPlotPt table={NAME="LATLON_PLOT_POINT",TYPE=SYMBOL,X=^xVal,Y=^yVal,&
                                  COLOR=^color,LINE={SYMBOL="UTRI"}} plot=latLonPlot
return
