cmake_minimum_required(VERSION 3.7)

project(test_runner CXX)

get_filename_component(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" ABSOLUTE)
get_filename_component(CMAKE_EXTERNALS "${CMAKE_EXTERNALS}" ABSOLUTE)

include(CppUnit)
include(FISPro)
include(GeoFIS)
include(Libiconv)
include(GMock)
include(CTest)

if(NOT DEFINED SKIP_R_TESTS)
	set(SKIP_R_TESTS TRUE)
endif()

if(NOT SKIP_R_TESTS)
	find_package(R REQUIRED)
	include_directories(${R_INCLUDE_DIR})
	get_filename_component(R_LIBRARY_DIR ${R_LIBRARY} PATH)
	find_package(Rcpp REQUIRED)
	include_directories(${RCPP_INCLUDE_DIR})
	get_filename_component(RCPP_LIBRARY_DIR ${RCPP_LIBRARY} PATH)
	find_package(RInside REQUIRED)
	include_directories(${RINSIDE_INCLUDE_DIR})
	get_filename_component(RINSIDE_LIBRARY_DIR ${RINSIDE_LIBRARY} PATH)
	include_directories("include")
endif()

if(BUILD_OPENSUSE)
    require_cppunit()
    require_util()
    require_fispro()
    require_geofis()
    require_libiconv()
    require_gmock()
else()
    find_cppunit()
    find_util()
    find_fispro()
    find_geofis()
    find_libiconv()
    find_gmock()
endif()    

#file(GLOB_RECURSE GEOFIS_CPP_FILES *.cpp)
#foreach(GEOFIS_CPP_FILE ${GEOFIS_CPP_FILES})
#    file(RELATIVE_PATH GEOFIS_RELATIVE_CPP_FILE ${CMAKE_CURRENT_SOURCE_DIR} ${GEOFIS_CPP_FILE}) 
#    message(${GEOFIS_RELATIVE_CPP_FILE})
#endforeach()

set(GEOFIS_TESTER_SOURCES
    cpp/geofis/algorithm/feature/feature_normalization_tester.cpp
    cpp/geofis/algorithm/zoning/aggregation/minimum_aggregation_tester.cpp
    cpp/geofis/algorithm/zoning/fusion/distance/feature_distance_tester.cpp
    cpp/geofis/algorithm/zoning/fusion/distance/zone_distance_adapter_tester.cpp
    cpp/geofis/algorithm/zoning/fusion/neighbor_to_zone_pair_tester.cpp
    cpp/geofis/algorithm/zoning/fusion/zone/zone_tester.cpp
    cpp/geofis/algorithm/zoning/fusion/zone_fusion_tester.cpp
    cpp/geofis/algorithm/zoning/fusion/voronoi/zone_info_tester.cpp
    cpp/geofis/algorithm/zoning/geometry/zone_bounded_tester.cpp
    cpp/geofis/algorithm/zoning/map/map_tester.cpp
    cpp/geofis/algorithm/zoning/pair/zone_pair_distance_tester.cpp
    cpp/geofis/algorithm/zoning/pair/zone_pair_id_comparator_tester.cpp
    cpp/geofis/algorithm/zoning/merge/area/area_merge_tester.cpp
    cpp/geofis/algorithm/zoning/merge/size/size_merge_tester.cpp
    cpp/geofis/algorithm/zoning/merging/merging_tester.cpp
    cpp/geofis/algorithm/zoning/triangulation/voronoi/face_to_polygon_tester.cpp
    cpp/geofis/algorithm/zoning/triangulation/voronoi/voronoi_zone_tester.cpp
    cpp/geofis/algorithm/zoning/zone/zone_joinable_tester.cpp
    cpp/geofis/geometry/geometry_area_tester.cpp
    cpp/geofis/geometry/on_bounded_side_tester.cpp)

set(GEOFIS_TEST_SOURCES cpp/test_runner.cpp ${GEOFIS_TESTER_SOURCES})

if(BUILD_ZONING)
	set(GEOFIS_OGR_TESTER_SOURCES cpp/geofis/ogr/ogr_tester.cpp)
	
    set(GEOFIS_TEST_SOURCES ${GEOFIS_TEST_SOURCES} ${GEOFIS_OGR_TESTER_SOURCES})
    set(GEOFIS_TESTER_SOURCES ${GEOFIS_TESTER_SOURCES} ${GEOFIS_OGR_TESTER_SOURCES})
endif()

if(NOT SKIP_R_TESTS)
	set(GEOFIS_R_TESTER_SOURCES 
		cpp/rcpp/matrix_tester.cpp
		cpp/geofis/rcpp/feature/feature_range_tester.cpp
		cpp/geofis/rcpp/geometry/line_tester.cpp
		cpp/geofis/rcpp/geometry/lines_tester.cpp
		cpp/geofis/rcpp/geometry/polygon_2_tester.cpp
		cpp/geofis/rcpp/geometry/polygon_tester.cpp
		cpp/geofis/rcpp/geometry/polygons_tester.cpp
		cpp/geofis/rcpp/process/zoning/neighborhood/neighborhood_map_tester.cpp
		cpp/geofis/rcpp/process/zoning/voronoi/voronoi_map_tester.cpp
		cpp/geofis/rcpp/process/zoning/map_tester.cpp)

	set(GEOFIS_R_TEST_SOURCES cpp/rinside/environment.cpp ${GEOFIS_R_TESTER_SOURCES})

	set(GEOFIS_TEST_SOURCES ${GEOFIS_TEST_SOURCES} ${GEOFIS_R_TEST_SOURCES})
	set(GEOFIS_TESTER_SOURCES ${GEOFIS_TESTER_SOURCES} ${GEOFIS_R_TESTER_SOURCES})
endif()

# see https://www.boost.org/doc/libs/master/libs/config/doc/html/boost_config/boost_macro_reference.html
set(COMPILE_FLAGS_PROPERTIES "-DBOOST_NO_AUTO_PTR -Wno-nonnull -Wno-dangling-pointer")

if(NOT SKIP_R_TESTS)
	set(COMPILE_FLAGS_PROPERTIES "${COMPILE_FLAGS_PROPERTIES} -DRINSIDE_SUPPORT")
endif()

if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6)
    # gnu++14 is now the default standard 
    # see https://gcc.gnu.org/gcc-6/changes.html
    set(COMPILE_FLAGS_PROPERTIES "${COMPILE_FLAGS_PROPERTIES} -std=gnu++14")
endif()

if(CMAKE_CXX_COMPILER_VERSION GREATER_EQUAL 12)
	# The standard library no longer supports std::unary_function and std::binary_function. They were deprecated in C++11 and is removed from C++14.
	# see https://www.boost.org/doc/libs/1_69_0/libs/config/doc/html/boost_config/boost_macro_reference.html
	# gcc 12 warns deprecated-declarations
	# CMakeExternals-12.0.1/Install/gtest/1.8.0/x86_64-w64-mingw32/include/gmock/internal/gmock-internal-utils.h:377:10: warning: infinite recursion detected [-Winfinite-recursion]
	# CMakeExternals-12.0.1/Install/cgal/5.2/include/CGAL/Handle_for.h:154:20: warning: pointer used after 'void operator delete(void*, std::size_t)' [-Wuse-after-free]
    set(COMPILE_FLAGS_PROPERTIES "${COMPILE_FLAGS_PROPERTIES} -DBOOST_NO_CXX98_FUNCTION_BASE -Wno-infinite-recursion -Wno-use-after-free")
endif()

if(BOOST_VERSION VERSION_LESS 1.60)
    set(COMPILE_FLAGS_PROPERTIES "${COMPILE_FLAGS_PROPERTIES} -Wno-parentheses -Wno-deprecated-declarations")
elseif(BOOST_VERSION VERSION_LESS 1.68)
    set(COMPILE_FLAGS_PROPERTIES "${COMPILE_FLAGS_PROPERTIES} -Wno-parentheses")
elseif((BOOST_VERSION VERSION_EQUAL 1.69) OR (BOOST_VERSION VERSION_EQUAL 1.74))
    set(COMPILE_FLAGS_PROPERTIES "${COMPILE_FLAGS_PROPERTIES} -DBOOST_ALLOW_DEPRECATED_HEADERS")
endif()

if(MINGW AND TARGET_32_BITS AND ((BOOST_VERSION VERSION_GREATER 1.72) AND (BOOST_VERSION VERSION_LESS 1.76)))
    # see boost/config/compiler/gcc.hpp
    # if __MINGW32__ BOOST_NO_CXX11_THREAD_LOCAL defined
    # so Boost.Multiprecision and Boost.Math deprecated
    set(COMPILE_FLAGS_PROPERTIES "${COMPILE_FLAGS_PROPERTIES} -DBOOST_MP_DISABLE_DEPRECATE_03_WARNING -DBOOST_MATH_DISABLE_DEPRECATED_03_WARNING")
endif()

if(CGAL_VERSION VERSION_LESS 4.9)
    # warn about catching polymorphic type 'class CGAL::Uncertain_conversion_exception' by value in CGAL/Lazy.h
    # uninitialized warning in CGAL/Arr_dcel_base.h default constructor of Arr_vertex and Arr_face classes
    set(COMPILE_FLAGS_PROPERTIES "${COMPILE_FLAGS_PROPERTIES} -Wno-attributes -Wno-catch-value -Wno-uninitialized")
elseif(CGAL_VERSION VERSION_LESS 4.10)
    set(COMPILE_FLAGS_PROPERTIES "${COMPILE_FLAGS_PROPERTIES} -Wno-catch-value -Wno-uninitialized -Wno-deprecated-declarations")
elseif(CGAL_VERSION VERSION_LESS 4.12)
    set(COMPILE_FLAGS_PROPERTIES "${COMPILE_FLAGS_PROPERTIES} -Wno-uninitialized")
elseif((CGAL_VERSION VERSION_GREATER 4.12.2) AND (CGAL_VERSION VERSION_LESS 5.3))
    # see https://stackoverflow.com/questions/55732233/why-i-am-getting-boost-parameter-max-arity-redefined-warning-while-compiling for BOOST_PARAMETER_MAX_ARITY=12
    set(COMPILE_FLAGS_PROPERTIES "${COMPILE_FLAGS_PROPERTIES} -DBOOST_PARAMETER_MAX_ARITY=12")
endif()

if(COMPILE_FLAGS_PROPERTIES)
    message(STATUS "GeoFIS Test CXX compile flags: ${COMPILE_FLAGS_PROPERTIES}")
    set_source_files_properties(${GEOFIS_TEST_SOURCES} PROPERTIES COMPILE_FLAGS ${COMPILE_FLAGS_PROPERTIES})
endif()

add_executable(test_runner cpp/test_runner.cpp ${GEOFIS_TEST_SOURCES})
set(TEST_LINK_LIBRARIES ${GeoFIS_LIBRARY_NAME} ${CGAL_LIBRARIES_NAME} ${UTIL_BOOST_PREFIX_LIBRARIES} ${CGAL_BOOST_PREFIX_LIBRARIES} ${GeoFIS_BOOST_PREFIX_LIBRARIES} ${MPFR_LIBRARY} ${GMP_LIBRARY} ${CppUnit_LIBRARY_NAME} ${GTest_LIBRARY_NAME} ${GMock_LIBRARY_NAME} ${Util_LIBRARY_NAME} ${FISPro_LIBRARY_NAME} ${GDAL_LIBRARY_NAME})
if(NOT SKIP_R_TESTS)
    set(TEST_LINK_LIBRARIES ${TEST_LINK_LIBRARIES} ${R_LIBRARY} ${RINSIDE_LIBRARY})
endif()
target_link_libraries(test_runner ${TEST_LINK_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
if(DEPENDENCIES)
	message(STATUS "GeoFIS Test Dependencies = ${DEPENDENCIES}")
	add_dependencies(test_runner ${DEPENDENCIES})
endif()

concat_path(PATH ${CXX_RUNTIME_DIR} ${GeoFIS_RUNTIME_DIR} ${CGAL_RUNTIME_DIR} ${Boost_LIBRARY_DIRS} ${CppUnit_RUNTIME_DIR} ${Util_RUNTIME_DIR} ${FISPro_RUNTIME_DIR} ${Libiconv_RUNTIME_DIR} ${GDAL_RUNTIME_DIR} ${GEOS_RUNTIME_DIR} ${R_LIBRARY_DIR} ${RCPP_LIBRARY_DIR} ${RINSIDE_LIBRARY_DIR})
add_tests(${CMAKE_CURRENT_BINARY_DIR}/test_runner "${PATH}" ${GEOFIS_TESTER_SOURCES})
if(WIN32 AND BUILD_ZONING)
    set_property(TEST ogr_tester APPEND PROPERTY ENVIRONMENT "GDAL_DATA=${GDAL_DATA_DIR}")
endif()

add_custom_command(TARGET test_runner POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_CURRENT_SOURCE_DIR}/resources" "${CMAKE_CURRENT_BINARY_DIR}/resources")
