
# set testing tools:
# - int (internal)
# - gg_gridname (internal)
# - grib_compare (bundle, on provided path, or on system path)
# - cmp (strict binary comparison)

if( ENABLE_INSTALL_TOOLS )
  get_target_property( CMD_INT         int         LOCATION )
  get_target_property( CMD_GG_GRIDNAME gg_gridname LOCATION )
endif()

if( TARGET grib_compare )
  get_target_property( CMD_GRIB_COMPARE grib_compare LOCATION )
endif()
if( NOT CMD_GRIB_COMPARE )
  find_program( CMD_GRIB_COMPARE grib_compare NO_DEFAULT_PATH HINTS "${grib_api_BASE_DIR}" PATH_SUFFIXES "bin" )
endif()
if( NOT CMD_GRIB_COMPARE )
  find_program( CMD_GRIB_COMPARE grib_compare )
endif()

find_program( CMD_CMP cmp )


# set testing environments (grib_api, libemos)
if( NOT grib_api_BASE_DIR AND CMD_GRIB_COMPARE )
  get_filename_component( _grib_compare_dir "${CMD_GRIB_COMPARE}" PATH )
  get_filename_component( grib_api_BASE_DIR "${_grib_compare_dir}" ABSOLUTE )
  set( grib_api_BASE_DIR "${grib_api_BASE_DIR}/../" )
endif()

if( grib_api_BASE_DIR )
  set( _grib_environment
    GRIB_DEFINITION_PATH=${grib_api_BASE_DIR}/share/grib_api/definitions/:${grib_api_BASE_DIR}/share/grib_api/definitions/grib1/
    GRIB_SAMPLES_PATH=${grib_api_BASE_DIR}/share/grib_api/samples/ )
endif()
set( _emos_environment
  "${_grib_environment}"
# JDCNDBG=2
# INTF2_DEBUG=1
  CONFIG_INTERP=ON_FLY
  MARS_LSM_PATH=${PROJECT_SOURCE_DIR}/tables/interpol
  ECMWF_LOCAL_TABLE_PATH=${PROJECT_SOURCE_DIR}/gribtables
  LOCAL_DEFINITION_TEMPLATES=${PROJECT_SOURCE_DIR}/gribtemplates )


# log information
ecbuild_info( "Test tool int:          ${CMD_INT}" )
ecbuild_info( "Test tool gg_gridname:  ${CMD_GG_GRIDNAME}" )
ecbuild_info( "Test tool grib_compare: ${CMD_GRIB_COMPARE}" )
ecbuild_info( "Test tool cmp:          ${CMD_CMP}" )
if( NOT CMD_INT OR NOT CMD_GG_GRIDNAME OR NOT CMD_GRIB_COMPARE OR NOT CMD_CMP )
  ecbuild_info( "(some tools not found, some tests disabled)" )
endif()
ecbuild_debug( "Test _grib_environment: ${_grib_environment}" )
ecbuild_debug( "Test _emos_environment: ${_emos_environment}" )


# configure Fortran-based targets for double precision (compilation & linking)
ecbuild_add_fortran_flags(${emos_double_precision_flags})


################ I N T E R P O L A T I O N ################

if( HAVE_LIBEMOS_INTERPOLATION )

  # intuvp2: interpolation to different formats
  foreach( rotated "" "rotated_" )
    foreach( out "regular_ll" "F80" "N80" "O80" )
      set( in "sh_vo-d" )
      set( test "${in}_to_${rotated}${out}" )
      set( rot "--rotation=30/30" )
      if( "${rotated}" STREQUAL "" )
        set( rot "" )
      endif()
      if(     NOT (test MATCHES "^sh_.*_to_O" AND NOT HAVE_FFTW)
          AND NOT (test MATCHES "^.*_to_rotated_[NOF]") )
        set( input  "${PROJECT_SOURCE_DIR}/data/${in}.grib" )
        set( output "intuvp2_${test}.grib" )
        if( out MATCHES "^regular_ll" )
          set( grid "--grid=3.0/3.0" )
        else()
          set( grid "--gridname=${out}" )
        endif()

        # interpolate
        ecbuild_add_test(
          TARGET       intuvp2_${test}_interpol
          DEPENDS      int
          COMMAND      ${CMD_INT}
          ARGS         ${grid} ${rot} --input=${input} --output=${output} --int=intuvp2
          ENVIRONMENT  ${_emos_environment} )

        # compare results to reference data
        ecbuild_add_test(
          TARGET       intuvp2_${test}_compare
          TEST_DEPENDS intuvp2_${test}_interpol
          CONDITION    CMD_GRIB_COMPARE
          COMMAND      ${CMD_GRIB_COMPARE}
          ARGS         ${PROJECT_SOURCE_DIR}/data/${output} ${output}
          ENVIRONMENT  ${_grib_environment} )

        unset( grid )
        unset( output )
        unset( input )
      endif()
      unset( rot )
      unset( test )
      unset( in )
    endforeach()
  endforeach()

  # intf2: interpolation to different formats
  # not possible:
  # - regular_ll to reduced Gaussian (G) (but regular_ll to regular G is possible)
  # - regular G to reduced G
  # - any to rotated reduced/regular G
  # - regular_ll to rotated regular_ll
  foreach( rotated "" "rotated_" )
    foreach( in "sh_vo-d" "sh_z" "regular_ll" "N640" "O640" "F640" )
      foreach( out "regular_ll" "F80" "N80" "O80" "F48" )
        set( test "${in}_to_${rotated}${out}" )
        set( rot "--rotation=30/30" )
        if( "${rotated}" STREQUAL "" )
          set( rot "" )
        endif()
        if(     NOT  test MATCHES "^regular_ll_to_[NO]"
            AND NOT  test MATCHES "^F.*_to_[NO]"
            AND NOT  test MATCHES "^.*_to_rotated_[NOF]"
            AND NOT  test MATCHES "^regular_ll_to_rotated_regular_ll$"
            AND NOT (test MATCHES "^sh_.*_to_O" AND NOT HAVE_FFTW) )
          set( input  "${PROJECT_SOURCE_DIR}/data/${in}.grib" )
          set( output "intf2_${test}.grib" )
          if( out MATCHES "^regular_ll" )
            set( grid "--grid=0.5/0.5" )
          else()
            set( grid "--gridname=${out}" )
          endif()

          # interpolate
          ecbuild_add_test(
            TARGET       intf2_${test}_interpol
            DEPENDS      int
            COMMAND      ${CMD_INT}
            ARGS         ${grid} --autoresol=1 --area=0/0/0/0 ${rot} --input=${input} --output=${output} --int=intf2
            ENVIRONMENT  ${_emos_environment} )

          # check gridname is expected and is a valid Gaussian grid
          if( out MATCHES "^[FNO]" )
            ecbuild_add_test(
              TARGET       intf2_${test}_gridname
              TEST_DEPENDS intf2_${test}_interpol
              CONDITION    CMD_GG_GRIDNAME
              COMMAND      ${CMD_GG_GRIDNAME}
              ARGS         --eq=${out} ${output}
              ENVIRONMENT  ${_grib_environment} )
          endif()

          # compare results to reference data, strict comparison except in some cases
          if( NOT CMD_CMP
              OR test MATCHES  "^regular_ll_to_regular_ll$"  # opensuse131/pgi, lxc/pgi
              OR test MATCHES  "^N640_to_O80$" )             # (minor numeric issues, within 2x packing error)
            ecbuild_add_test(
              TARGET       intf2_${test}_compare
              TEST_DEPENDS intf2_${test}_interpol
              CONDITION    CMD_GRIB_COMPARE
              COMMAND      ${CMD_GRIB_COMPARE}
              ARGS         -P -T 2 ${PROJECT_SOURCE_DIR}/data/${output} ${output}
              ENVIRONMENT  ${_grib_environment} )
          else()
            ecbuild_add_test(
              TARGET       intf2_${test}_compare
              TEST_DEPENDS intf2_${test}_interpol
              CONDITION    CMD_GRIB_COMPARE
              COMMAND      ${CMD_GRIB_COMPARE}
              ARGS         ${PROJECT_SOURCE_DIR}/data/${output} ${output}
              ENVIRONMENT  ${_grib_environment} )
          endif()

          unset( grid )
          unset( output )
          unset( input )
        endif()
        unset( rot )
        unset( test )
      endforeach()
    endforeach()
  endforeach()


  # intf2: interpolate to N/O grids with the same N
  # (distinguish between N640 <> O640)
  foreach( in "N640" "O640" )
    foreach( out "N640" "O640" )
      set( test "${in}_to_${out}" )
      set( input  "${PROJECT_SOURCE_DIR}/data/${in}.grib" )
      set( output "intf2_${test}.grib" )

      # interpolate
      ecbuild_add_test(
        TARGET       intf2_${test}_interpol
        DEPENDS      int
        COMMAND      ${CMD_INT}
        ARGS         --gridname=${out} --autoresol=1 --area=0/0/0/0 --input=${input} --output=${output} --int=intf2
        ENVIRONMENT  ${_emos_environment} )

      # compare results to reference data
      if( in STREQUAL out )
        ecbuild_add_test(
          TARGET       intf2_${test}_compare_same
          TEST_DEPENDS intf2_${test}_interpol
          CONDITION    CMD_GRIB_COMPARE
          COMMAND      ${CMD_GRIB_COMPARE}
          ARGS         ${input} ${output}
          ENVIRONMENT  ${_grib_environment} )
      else()
        ecbuild_add_test(
          TARGET       intf2_${test}_compare_diff
          TEST_DEPENDS intf2_${test}_interpol
          CONDITION    CMD_GRIB_COMPARE
          COMMAND      ${CMD_GRIB_COMPARE}
          ARGS         ${input} ${output}
          ENVIRONMENT  ${_grib_environment} )
        set_tests_properties( intf2_${test}_compare_diff PROPERTIES WILL_FAIL TRUE )
      endif()

      # expect a gridname
      ecbuild_add_test(
        TARGET       intf2_${test}_gridname
        TEST_DEPENDS intf2_${test}_interpol
        CONDITION    CMD_GG_GRIDNAME
        COMMAND      ${CMD_GG_GRIDNAME}
        ARGS         --eq=${out} ${output}
        ENVIRONMENT  ${_grib_environment} )

      unset( output )
      unset( input )
      unset( test )
    endforeach()
  endforeach()


  # intf2: interpolate to regular_ll corresponding to O1280 = 1/16 degree
  if( FALSE )
  foreach( in "O640" )
    set( test "${in}_to_regular_ll_1-16" )
    set( input  "${PROJECT_SOURCE_DIR}/data/${in}.grib" )
    set( output "intf2_${test}.grib" )

    # interpolate
    ecbuild_add_test(
      TARGET       intf2_${test}_interpol
      DEPENDS      int
      COMMAND      ${CMD_INT}
      ARGS         --grid=0.0625/0.0625 --input=${input} --output=${output} --int=intf2
      ENVIRONMENT  ${_emos_environment} )

    # compare results to reference data
    ecbuild_add_test(
      TARGET       intf2_${test}_compare
      TEST_DEPENDS intf2_${test}_interpol
      CONDITION    CMD_GRIB_COMPARE
      COMMAND      ${CMD_GRIB_COMPARE}
      ARGS         ${PROJECT_SOURCE_DIR}/data/${output} ${output}
      ENVIRONMENT  ${_grib_environment} )

    unset( output )
    unset( input )
    unset( test )
  endforeach()
  endif()


  # intf2: test GRIB edition 1 encoding limits
  # snap-milli-degree:     snaps to 0.001 because grid is 0.00025/0.00025, and is GRIB1-encodable
  # snap-sub-milli-degree: snaps to 0.0005, not GRIB1-encodable (failure expected)
  if( FALSE )
  foreach( snap "snap-milli-degree" "snap-sub-milli-degree_bad" )
    set( test "N640_to_regular_ll_${snap}" )
    if( snap MATCHES "^snap-milli-degree" )
      set( eps "0.00076" )
    elseif( snap MATCHES "^snap-sub-milli-degree" )
      set( eps "0.00074" )
    endif()
    ecbuild_add_test(
      TARGET       intf2_${test}_interpol
      DEPENDS      int
      COMMAND      ${CMD_INT}
      ARGS         --grid=0.00025/0.00025 --area=${eps}/0/0/${eps} --input=${PROJECT_SOURCE_DIR}/data/N640.grib --output="intf2_${test}.grib" --int=intf2
      ENVIRONMENT  ${_emos_environment} )
    unset( eps )
    unset( test )
  endforeach()
  set_tests_properties( intf2_N640_to_regular_ll_snap-sub-milli-degree_bad_interpol PROPERTIES WILL_FAIL TRUE )

  set( snap "snap-sub-milli-degree_sub-area_bad" )
  set( test "N640_to_regular_ll_${snap}" )
  ecbuild_add_test(
    TARGET       intf2_${test}_interpol
    DEPENDS      int
    COMMAND      ${CMD_INT}
    ARGS         --grid=0.0625/0.0625 --area=1/0.0625/0/0.5625 --input=${PROJECT_SOURCE_DIR}/data/N640.grib --output="intf2_${test}.grib" --int=intf2
    ENVIRONMENT  ${_emos_environment} )
  set_tests_properties( intf2_${test}_interpol PROPERTIES WILL_FAIL TRUE )
  unset( test )
  unset( snap )
  endif()


  # intf2: compare FFT99 vs FFTW exactly (no tolerance!)
  foreach( in "sh_vo-d" "sh_z" )
    set( output_fftw  "intf2_${in}_to_N80-fftw.grib" )
    set( output_fft99 "intf2_${in}_to_N80.grib" )

    # interpolate forcing FFTW
    ecbuild_add_test(
      TARGET       intf2_${in}_to_N80_fft99_vs_fftw_interpol_fftw
      TEST_DEPENDS intf2_${in}_to_N80_interpol
      DEPENDS      int
      COMMAND      ${CMD_INT}
      CONDITION    HAVE_FFTW
      ARGS         --gridname=N80 --autoresol=1 --area=0/0/0/0 --input=${PROJECT_SOURCE_DIR}/data/${in}.grib --output=${output_fftw} --int=intf2
      ENVIRONMENT  EMOSLIB_FORCED_FFTW=1 ${_emos_environment} )

    # compare results to already interpolated results (exactly)
    ecbuild_add_test(
      TARGET       intf2_${in}_to_N80_fft99_vs_fftw_compare
      TEST_DEPENDS intf2_${in}_to_N80_fft99_vs_fftw_interpol_fftw
      CONDITION    HAVE_FFTW AND CMD_GRIB_COMPARE
      COMMAND      ${CMD_GRIB_COMPARE}
      ARGS         ${output_fft99} ${output_fftw}
      ENVIRONMENT  ${_grib_environment} )

    unset( output_fft99 )
    unset( output_fftw )
  endforeach()


  # intf2: test SH
  set( in  "sh_vo-d" )
  set( test "${in}_to_${in}_trunc" )
  set( input  "${PROJECT_SOURCE_DIR}/data/${in}.grib" )
  set( output "intf2_${test}.grib" )
  ecbuild_add_test(
    TARGET       intf2_${test}_interpol
    DEPENDS      int
    COMMAND      ${CMD_INT}
    ARGS         --input=${input} --output=${output} --out:truncation=63 --int=intf2
    ENVIRONMENT  ${_emos_environment} )
  unset( output )
  unset( input )
  unset( test )
  unset( in )


  # FFTW/FFT990
  ecbuild_add_test( TARGET fft99  SOURCES fft99.F  LIBS emos )
  ecbuild_add_test( TARGET fftw   SOURCES fftw.F   LIBS emos  CONDITION HAVE_FFTW )


endif( HAVE_LIBEMOS_INTERPOLATION )


####################### G R I B E X #######################

if( HAVE_LIBEMOS_GRIBEX )

  foreach( test "gribex_demo" "gribex_abort" )
    ecbuild_add_test(
      TARGET      ${test}
      SOURCES     ${test}.F
      LIBS        emos
      ARGS        -i ${PROJECT_SOURCE_DIR}/data/test_latlon.grib  # (only for gribex_demo)
      ENVIRONMENT ${_emos_environment} )
    set_tests_properties( ${test} PROPERTIES WILL_FAIL ${HAVE_GRIBEX_ABORT} )
  endforeach()

endif( HAVE_LIBEMOS_GRIBEX )


######################### B U F R #########################

if( HAVE_LIBEMOS_BUFRDC )

  # set bufr tables path (for testing):
  # (check if bufrtables/ is bundled, otherwise set to best guess)
  if( NOT TEST_BUFR_TABLES_PATH AND EXISTS "${PROJECT_SOURCE_DIR}/bufrtables/B0000000000000000000.TXT" )
    set( TEST_BUFR_TABLES_PATH "${PROJECT_SOURCE_DIR}/bufrtables" )
  elseif ( NOT TEST_BUFR_TABLES_PATH )
    set( TEST_BUFR_TABLES_PATH "${BUFR_TABLES_PATH}" )
  endif()

  message( STATUS "TEST_BUFR_TABLES_PATH: ${TEST_BUFR_TABLES_PATH}" )

  if( EXISTS "${TEST_BUFR_TABLES_PATH}" )
    set( TEST_BUFR_TABLES_PATH_EXISTS TRUE )
  else()
    set( TEST_BUFR_TABLES_PATH_EXISTS FALSE )
    message( WARNING "Could not find bufr tables path for testing -- turning off some tests!\nTo enable them set a valid TEST_BUFR_TABLES_PATH (alternatively, BUFR_TABLES_PATH) and re-run cmake" )
  endif()

  # download bufr test files
  file(READ "bufr_data_files.txt" bufr_files)
  string(REGEX REPLACE "\n" ";" bufr_files "${bufr_files}")
  ecbuild_get_test_multidata( TARGET download_bufrs NOCHECK NAMES ${bufr_files} )

  # This must be here or set_tests_properties() may fail
  # FIXME: add PROPERTIES to ecbuild_add_test()
  if( TEST_BUFR_TABLES_PATH_EXISTS )
    ecbuild_add_test(
      TARGET       bufr_decode_all_NotFoundTestFile
      COMMAND      ${CMAKE_BINARY_DIR}/bin/bufr_decode_all
      CONDITION    TEST_BUFR_TABLES_PATH_EXISTS
      ARGS         -i NotFoundTestFile.bufr
      ENVIRONMENT  BUFR_TABLES=${TEST_BUFR_TABLES_PATH} )
    set_tests_properties( bufr_decode_all_NotFoundTestFile PROPERTIES WILL_FAIL TRUE )
  endif( TEST_BUFR_TABLES_PATH_EXISTS )

  ecbuild_add_test(
    TARGET       bufr_decode_all_NotFoundTablesPath
    COMMAND      ${CMAKE_BINARY_DIR}/bin/bufr_decode_all
    ARGS         -i ${PROJECT_SOURCE_DIR}/data/temp_101.bufr
    ENVIRONMENT  BUFR_TABLES="NotFoundTablesPath/" )
  set_tests_properties( bufr_decode_all_NotFoundTablesPath PROPERTIES WILL_FAIL TRUE )

  foreach( bufr_file ${bufr_files} )
    ecbuild_add_test(
      TARGET       bufr_decode_all_${bufr_file}
      COMMAND      ${CMAKE_BINARY_DIR}/bin/bufr_decode_all
      CONDITION    TEST_BUFR_TABLES_PATH_EXISTS
      ARGS         -i ${bufr_file}
      TEST_DEPENDS download_bufrs
      ENVIRONMENT  BUFR_TABLES=${TEST_BUFR_TABLES_PATH} )
  endforeach()

  # tc_tracks series of tests:
  # FIXME: problems with the compare tests, so not running yet (as before)
  if( FALSE AND ENABLE_INSTALL_TOOLS )

    set( in  "${PROJECT_SOURCE_DIR}/data/tracks_05W_PEIPAH_2014041000.fm" )
    set( ref "${PROJECT_SOURCE_DIR}/data/tracks_05W_PEIPAH_2014041000.eps.bufr" )
    set( out                            "tracks_05W_PEIPAH_2014041000.eps.bufr" )
    ecbuild_add_test( TARGET tc_tracks_eps_${out}  DEPENDS tc_tracks_eps COMMAND ${CMAKE_BINARY_DIR}/bin/tc_tracks_eps ARGS    -i "${in}" -o "${out}"  ENVIRONMENT BUFR_TABLES=${TEST_BUFR_TABLES_PATH} )
    ecbuild_add_test( TARGET tc_tracks_eps_${out}4 DEPENDS tc_tracks_eps COMMAND ${CMAKE_BINARY_DIR}/bin/tc_tracks_eps ARGS -4 -i "${in}" -o "${out}4" ENVIRONMENT BUFR_TABLES=${TEST_BUFR_TABLES_PATH} )
    ecbuild_add_test( TARGET tc_tracks_eps_${out}_cmp  TEST_DEPENDS tc_tracks_eps_${out}  CONDITION CMD_CMP COMMAND ${CMD_CMP} ARGS "${ref}" "${out}"  )
    ecbuild_add_test( TARGET tc_tracks_eps_${out}4_cmp TEST_DEPENDS tc_tracks_eps_${out}4 CONDITION CMD_CMP COMMAND ${CMD_CMP} ARGS "${ref}" "${out}4" )

    set( in  "${PROJECT_SOURCE_DIR}/data/tracks_15U_ITA_2014041012.fm" )
    set( ref "${PROJECT_SOURCE_DIR}/data/tracks_15U_ITA_2014041012.det.bufr" )
    set( out                            "tracks_15U_ITA_2014041012.det.bufr" )
    ecbuild_add_test( TARGET tc_tracks_det_${out}  DEPENDS tc_tracks_det COMMAND ${CMAKE_BINARY_DIR}/bin/tc_tracks_det ARGS    -i "${in}" -o "${out}"  ENVIRONMENT BUFR_TABLES=${TEST_BUFR_TABLES_PATH} )
    ecbuild_add_test( TARGET tc_tracks_det_${out}4 DEPENDS tc_tracks_det COMMAND ${CMAKE_BINARY_DIR}/bin/tc_tracks_det ARGS -4 -i "${in}" -o "${out}4" ENVIRONMENT BUFR_TABLES=${TEST_BUFR_TABLES_PATH} )
    ecbuild_add_test( TARGET tc_tracks_det_${out}_cmp  TEST_DEPENDS tc_tracks_det_${out}  CONDITION CMD_CMP COMMAND ${CMD_CMP} ARGS "${ref}" "${out}"  )
    ecbuild_add_test( TARGET tc_tracks_det_${out}4_cmp TEST_DEPENDS tc_tracks_det_${out}4 CONDITION CMD_CMP COMMAND ${CMD_CMP} ARGS "${ref}" "${out}4" )

  endif()

endif( HAVE_LIBEMOS_BUFRDC )


################ L I N K I N G   T E S T S ################

# these are build-time (not runtime!) tests
# (they are here to guarantee in which platforms link can fail)

ecbuild_add_executable(
  TARGET    link_mars NOINSTALL
  SOURCES   link_mars.F
  CONDITION HAVE_LIBEMOS_INTERPOLATION
  LIBS      emos )

ecbuild_add_executable(
  TARGET    link_prodgen NOINSTALL
  SOURCES   link_prodgen.F
  CONDITION HAVE_LIBEMOS_INTERPOLATION
  LIBS      emos )


###################### H S P 2 G G * ######################

ecbuild_add_test(TARGET hsp2gg SOURCES hsp2gg.F LIBS emos)


##################### E X A M P L E S #####################

ecbuild_add_executable(
  TARGET    example_intf2 NOINSTALL
  SOURCES   example_intf2.F
  CONDITION HAVE_LIBEMOS_INTERPOLATION
  LIBS      emos )

ecbuild_add_executable(
  TARGET    example_intuvp2 NOINSTALL
  SOURCES   example_intuvp2.F
  CONDITION HAVE_LIBEMOS_INTERPOLATION
  LIBS      emos )


############ T E S T S :   R E G R E S S I O N ############

if( HAVE_LIBEMOS_INTERPOLATION )
if( HAVE_LIBEMOS_TESTS_REGRESS )
  add_subdirectory( regress )
endif()
endif( HAVE_LIBEMOS_INTERPOLATION )

