# set minimum required cmake version
cmake_minimum_required (VERSION 3.2 FATAL_ERROR)

# make sure we are not going to build in the main source directory
set(CMAKE_DISABLE_SOURCE_CHANGES ON)
set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)

#-------------------------------------------------------------------------------
# global settings
#-------------------------------------------------------------------------------

# set project name and version
project (Hammer LANGUAGES CXX VERSION "0.1")

MESSAGE(STATUS "Enabled Languages are ${ENABLED_LANGUAGES}")

include(GNUInstallDirs)

set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/CMakeModules/")


# set the path where to put the generated libraries and executables
set (CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${PROJECT_BINARY_DIR}/lib)
set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${PROJECT_BINARY_DIR}/lib)
set (CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG ${PROJECT_BINARY_DIR}/lib)
set (CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE ${PROJECT_BINARY_DIR}/lib)

# option to enable/disable the tests
include(CMakeDependentOption)
option (ENABLE_TESTS "Enable Hammer unit tests" ON)
option (WITH_PYTHON "Install the Hammer python bindings" ON)
option (WITH_EXAMPLES "Install and build Hammer examples" OFF)
option (WITH_ROOT "Turn on ROOT histogram support" OFF)
option (INSTALL_EXTERNAL_DEPENDENCIES "Enable automatic download of external dependencies" OFF)
option (BUILD_DOCUMENTATION "Build the doxygen documentation" OFF)
option (VERBOSE_DEBUG "Turn on verbose debugging" OFF)
option (SANITIZE "Turn on sanitizers" OFF)
option (DISABLE_BOOST_MULTI "Turn off multithreading for boost" OFF)
CMAKE_DEPENDENT_OPTION(FORCE_BOOST_INSTALL "Force Boost installation even if present" OFF "INSTALL_EXTERNAL_DEPENDENCIES" OFF)
CMAKE_DEPENDENT_OPTION(FORCE_YAMLCPP_INSTALL "Force YAMLCPP installation even if present" OFF "INSTALL_EXTERNAL_DEPENDENCIES" OFF)
CMAKE_DEPENDENT_OPTION(FORCE_EIGEN_INSTALL "Force Eigen installation even if present" OFF "INSTALL_EXTERNAL_DEPENDENCIES" OFF)
CMAKE_DEPENDENT_OPTION(FORCE_HEPMC_INSTALL "Force HepMC installation even if present" OFF "INSTALL_EXTERNAL_DEPENDENCIES;WITH_EXAMPLES" OFF)

if(SANITIZE AND NOT VERBOSE_DEBUG)
	set(VERBOSE_DEBUG ON)
endif()

if(SANITIZE)
	set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/CMakeModules/Sanitizers" ${CMAKE_MODULE_PATH})
	find_package(Sanitizers)
endif()

if(VERBOSE_DEBUG AND NOT ${CMAKE_BUILD_TYPE} STREQUAL "Debug")
	message(STATUS "Verbose debugging turned on: setting build type to 'Debug'")
	set(CMAKE_BUILD_TYPE "Debug")
endif()

if(WITH_ROOT)
    set(MAX_CXX_STD 14)
else()
	set(MAX_CXX_STD 17)
endif()
include(CompilerChecks)

if(INSTALL_EXTERNAL_DEPENDENCIES)
	include(ExternalProject)
	SET_DIRECTORY_PROPERTIES(PROPERTIES EP_PREFIX ${PROJECT_BINARY_DIR}/external)
endif()


#check for Eigen3
# find_package(Eigen3 3.3.0)
# if(NOT EIGEN3_FOUND OR FORCE_EIGEN_INSTALL)
# 	if(INSTALL_EXTERNAL_DEPENDENCIES)
# 		include(AddEigen)
#     else()
# 		message (FATAL_ERROR "Eigen not found. You should install it before installing Hammer.")
# 	endif()
# else()
# 	add_library(ThirdParty::Eigen INTERFACE IMPORTED)
# 	set_property(TARGET ThirdParty::Eigen PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${EIGEN3_INCLUDE_DIR})
# endif()

#check for boost
SET(BOOST_MINREQ_VERSION "1.50.0")
find_package(Boost QUIET)
if(Boost_FOUND)
	find_package(Boost ${BOOST_MINREQ_VERSION} QUIET COMPONENTS system filesystem)
endif()
if(NOT (Boost_FOUND AND Boost_SYSTEM_FOUND AND Boost_FILESYSTEM_FOUND) OR FORCE_BOOST_INSTALL)
	if(INSTALL_EXTERNAL_DEPENDENCIES)
		include(AddBoost)
    else()
		message (FATAL_ERROR "Boost not found. You should install it before installing Hammer.")
	endif()
else()
	add_library(ThirdParty::Boost INTERFACE IMPORTED)
	set_property(TARGET ThirdParty::Boost PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${Boost_INCLUDE_DIRS})
	add_library(ThirdParty::BoostSystem STATIC IMPORTED)
    set_target_properties(ThirdParty::BoostSystem PROPERTIES
                          IMPORTED_LOCATION ${Boost_SYSTEM_LIBRARY}
                          LINKER_LANGUAGE CXX)
	add_library(ThirdParty::BoostFilesystem STATIC IMPORTED)
    set_target_properties(ThirdParty::BoostFilesystem PROPERTIES
                          IMPORTED_LOCATION ${Boost_FILESYSTEM_LIBRARY}
                          INTERFACE_LINK_LIBRARIES ThirdParty::BoostSystem
                          LINKER_LANGUAGE CXX)
	message(STATUS "${Boost_FILESYSTEM_LIBRARY} ${Boost_SYSTEM_LIBRARY}")
	add_dependencies(ThirdParty::BoostSystem ThirdParty::Boost)
	add_dependencies(ThirdParty::BoostFilesystem ThirdParty::Boost)
	add_dependencies(ThirdParty::BoostFilesystem ThirdParty::BoostSystem)
endif()

#check for yaml-cpp
SET(YamlCpp_MIN_VERSION "0.4.0")
find_package(YamlCpp ${YamlCpp_MIN_VERSION})
if(NOT YamlCpp_FOUND OR FORCE_YAMLCPP_INSTALL)
	if(INSTALL_EXTERNAL_DEPENDENCIES)
		include(AddYamlCpp)
    else()
		message (FATAL_ERROR "Yaml-cpp not found. You should install it before installing Hammer.")
	endif()
else()
	add_library(ThirdParty::YamlCpp INTERFACE IMPORTED)
	set_property(TARGET ThirdParty::YamlCpp PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${YamlCpp_INCLUDE_DIRS})
	set_property(TARGET ThirdParty::YamlCpp PROPERTY INTERFACE_LINK_LIBRARIES ${YamlCpp_LIBRARIES})
endif()

if(WITH_ROOT)
	find_package(ROOT)
	if(NOT ROOT_FOUND)
		MESSAGE(STATUS "Asked WITH_ROOT but ROOT was not found. Disabling ROOT support.")
	else()
		add_library(ThirdParty::ROOT INTERFACE IMPORTED)
		set_property(TARGET ThirdParty::ROOT PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${ROOT_INCLUDE_DIR})
		set_property(TARGET ThirdParty::ROOT PROPERTY INTERFACE_LINK_LIBRARIES ${ROOT_LIBRARIES})
		set(HAVE_ROOT TRUE)
	endif()
endif()



if(WITH_PYTHON)
	#setup Python-related packages
	find_package(PythonInterp)

	if(PYTHONINTERP_FOUND)
		INCLUDE(FindPythonModule)
		#check for pip
		find_python_module(pip)
		INCLUDE(AddPythonModule)
		# #check for numpy python bindings
		# find_python_module(numpy)
		# if(NOT PYNUMPY_FOUND)
		# 	if(PYPIP_FOUND AND INSTALL_EXTERNAL_DEPENDENCIES)
		# 		install_python_module(numpy)
		# 	else()
		# 		message (FATAL_ERROR "numpy not found. You should install it before installing Hammer.")
		# 	endif()
		# endif()
		# #check for matplotlib python bindings
		# find_python_module(matplotlib)
		# if(NOT PYMATPLOTLIB_FOUND)
		# 	if(PYPIP_FOUND AND INSTALL_EXTERNAL_DEPENDENCIES)
		# 		install_python_module(matplotlib)
		# 	else()
		# 		message (FATAL_ERROR "matplotlib not found. You should install it before installing Hammer.")
		# 	endif()
		# endif()
		#check for Cython
		include(FindCython)
		if(NOT CYTHON_FOUND)
			if(PYPIP_FOUND AND INSTALL_EXTERNAL_DEPENDENCIES)
				install_python_module(Cython)
			else()
				message (WARNING "Cython compiler not found. Hammer will only be accessible as a library.")
			endif()
		endif()

	else()
		message (WARNING "Python subsystem not found. Hammer will only be accessible as a library.")
	endif()
endif()

#Doxygen support
if(BUILD_DOCUMENTATION)
	find_package(Doxygen)
	if(DOXYGEN_FOUND)
		configure_file(${PROJECT_SOURCE_DIR}/hammer.doxy.in ${PROJECT_BINARY_DIR}/hammer.doxy ESCAPE_QUOTES @ONLY)
		add_custom_target(doc
  			${DOXYGEN_EXECUTABLE} ${PROJECT_BINARY_DIR}/hammer.doxy
  			WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
  			COMMENT "Generating API documentation with Doxygen" VERBATIM)
		install(DIRECTORY "${PROJECT_BINARY_DIR}/html" DESTINATION ${CMAKE_INSTALL_FULL_DOCDIR} OPTIONAL)
	else()
		message(WARNING "Building documentation enabled but doxygen not found. Disabling docs.")
	endif()
endif()

add_subdirectory(include)
add_subdirectory(src)

if(WITH_PYTHON AND PYTHONINTERP_FOUND)
	add_subdirectory(pyext)
endif()

# test support
if (ENABLE_TESTS)
	ENABLE_TESTING()
	add_subdirectory(Tests)
endif()

if(WITH_EXAMPLES)
	find_package(HepMC)
	if(HepMC_FOUND)
		add_library(ThirdParty::HepMC INTERFACE IMPORTED)
		set_property(TARGET ThirdParty::HepMC PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${HepMC_INCLUDE_DIRS})
		set_property(TARGET ThirdParty::HepMC PROPERTY INTERFACE_LINK_LIBRARIES ${HepMC_LIBRARY})
	endif()

	add_subdirectory(Examples)

endif()

add_subdirectory(CMakeModules)

## CPack configuration
include (InstallRequiredSystemLibraries)
set (CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt")
set (CPACK_PACKAGE_VERSION_MAJOR "${Hammer_VERSION_MAJOR}")
set (CPACK_PACKAGE_VERSION_MINOR "${Hammer_VERSION_MINOR}")
set (CPACK_PACKAGE_DESCRIPTION_SUMMARY "The Hammer Package: Automatic test of models")
set(CPACK_PACKAGE_VENDOR "Hammer development team")
set(CPACK_PACKAGE_DESCRIPTION_FILE ${CMAKE_CURRENT_SOURCE_DIR}/README)
set(CPACK_GENERATOR TGZ)
set(CPACK_SOURCE_GENERATOR TGZ)
set(CPACK_SOURCE_IGNORE_FILES "\.gitignore"
							  "\.astylerc"
							  "/\.git/"
                              "/build/" 
							  "/devel/"
							  "/python/"
							  "/master/"
							  "/sandbox/"
							  "/other/"
							  "^internal/"
							  "/\.vscode/"
							  "\.clang-format"
							  "\.DS_Store")
include (CPack)

