# Get the name of the current directory but with no path:
#get_filename_component(TARGET ${CMAKE_CURRENT_BINARY_DIR} NAME)

# ${TARGET}-objlib will be the name of the object files collection (in CMake
# parlance that is an "OBJECT" library type. In that library, that is simply a
# list of compiled object files, I put all the *.o files that make the ${TARGET}
# (minexpert or massxpert) executable image file, but not main.cpp. This is done
# because when building the tests/tests binary for tests relating to ${TARGET},
# I'll reuse these compiled object files.

if(APPLE)
	set(TARGET mineXpert)
	message(STATUS "APPLE: ${TARGET}")
elseif(UNIX AND NOT APPLE)
	set(TARGET minexpert)
	message(STATUS "NON-APPLE: ${TARGET}")
elseif(WIN64)
	set(TARGET mineXpert)
	message(STATUS "WIN64: ${TARGET}")
endif()

message("")
message(STATUS "${BoldGreen}Starting configuring of the ${TARGET} submodule${ColourReset}")
message("")


#############################################################
# Software configuration
message(STATUS "CMAKE_CURRENT_BINARY_DIR: " ${CMAKE_CURRENT_BINARY_DIR})

########################################################
# Files
file(GLOB MINEXPERT-objlib_nongui_SRCS nongui/*.cpp)
file(GLOB MINEXPERT-objlib_gui_SRCS gui/*.cpp)
file(GLOB MINEXPERT-objlib_UIS gui/ui/*.ui)

# The only file that does not enter in the object library of
# object files (see notice above).
file(GLOB MINEXPERT-exec_SRCS main.cpp)

# The desktop file
if(UNIX AND NOT APPLE)
	install(FILES org.msxpertsuite.minexpert.desktop
		DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications)
endif()

# Instruct CMake to run moc automatically when needed.
set(CMAKE_AUTOMOC ON)

find_package(Qt5 COMPONENTS Widgets Xml Svg Sql Script PrintSupport)

qt5_wrap_ui(MINEXPERT-objlib_UIS_H ${MINEXPERT-objlib_UIS})

qt5_add_resources(MINEXPERT_QRC_CPP gui/application.qrc)

### These two lines required because now CMake only automocs
### the generated files and not the source files.
set_source_files_properties(${MINEXPERT-objlib_UIS_H} PROPERTIES SKIP_AUTOMOC ON)
set_source_files_properties(${MINEXPERT_QRC_CPP} PROPERTIES SKIP_AUTOMOC ON)


add_library(MINEXPERT-objlib OBJECT
	${MINEXPERT-objlib_nongui_SRCS}
	${MINEXPERT-objlib_gui_SRCS}
	${MINEXPERT-objlib_UIS_H})

###############################################################
# Configuration of the binary to be built
###############################################################

# Now we can only add the executable, because we have defined the sources of the
# object library above.

if(NOT APPLE)
	add_executable(${TARGET}
		${MINEXPERT-exec_SRCS}
		$<TARGET_OBJECTS:MINEXPERT-objlib>
		${MINEXPERT_QRC_CPP})
else()

	# Copy the icon file to the Contents/Resources directory of the bundle at
	# location ${MACOSX_PACKAGE_LOCATION}.
	set_source_files_properties(../images/msXpertSuite.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources)

	# Identify MacOS bundle

	set(MACOSX_BUNDLE_BUNDLE_NAME ${TARGET})
	message(STATUS "MACOSX_BUNDLE_BUNDLE_NAME: ${MACOSX_BUNDLE_BUNDLE_NAME}")

	set(MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION})
	set(MACOSX_BUNDLE_LONG_VERSION_STRING ${PROJECT_VERSION})
	set(MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION})
	set(MACOSX_BUNDLE_COPYRIGHT ${COPYRIGHT})
	set(MACOSX_BUNDLE_GUI_IDENTIFIER ${IDENTIFIER})
	set(MACOSX_BUNDLE_ICON_FILE ../images/msXpertSuite.icns)

	set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=10.9"
		CACHE STRING "Flags used by the compiler during all build types." FORCE)

	#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility-inlines-hidden"
	#CACHE STRING "Flags used by the compiler during all build types." FORCE)

	set(CMAKE_OSX_SYSROOT "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/"
		CACHE STRING "MacOSX10.12.sdk." FORCE)

	add_executable(${TARGET} MACOSX_BUNDLE
		${MINEXPERT-exec_SRCS}
		$<TARGET_OBJECTS:MINEXPERT-objlib>
		${MINEXPERT_QRC_CPP}
		../images/msXpertSuite.icns
		)

	set_target_properties(${TARGET} PROPERTIES MACOSX_BUNDLE_ICON_FILE msXpertSuite.icns)

endif()


###############################################################
# Installation directories depending on the platform and module
###############################################################

if(WIN64)
	set(CMAKE_INSTALL_PREFIX "C:/Program Files/msXpertSuite")
	set(MINEXPERT_BIN_DIR ${CMAKE_INSTALL_PREFIX})
	set(MINEXPERT_JAVASCRIPT_DIR ${CMAKE_INSTALL_PREFIX}/javascript/minexpert)
	set(MINEXPERT_DATA_DIR ${CMAKE_INSTALL_PREFIX}/data/minexpert)
	set(MINEXPERT_DOC_DIR ${CMAKE_INSTALL_PREFIX}/doc/minexpert)
elseif(UNIX AND NOT APPLE)
	set(MINEXPERT_BIN_DIR ${CMAKE_INSTALL_PREFIX}/bin)
	set(MINEXPERT_JAVASCRIPT_DIR ${CMAKE_INSTALL_PREFIX}/share/msxpertsuite-minexpert/javascript)
	set(MINEXPERT_DATA_DIR ${CMAKE_INSTALL_PREFIX}/share/msxpertsuite-minexpert/data)
	set(MINEXPERT_DOC_DIR ${CMAKE_INSTALL_PREFIX}/share/doc/msxpertsuite-minexpert/doc)
elseif(APPLE)
	SET (BUNDLE_DIR ${CMAKE_CURRENT_BINARY_DIR}/mineXpert.app)
	SET(CMAKE_INSTALL_PREFIX "${BUNDLE_DIR}/Contents")
	SET (MINEXPERT_BIN_DIR ${BUNDLE_DIR}/Contents/MacOS)
	SET (MINEXPERT_JAVASCRIPT_DIR ${BUNDLE_DIR}/Contents/Resources/minexpert/javascript)
	SET (MINEXPERT_DATA_DIR ${BUNDLE_DIR}/Contents/Resources/minexpert/data)
	SET (MINEXPERT_DOC_DIR ${BUNDLE_DIR}/Contents/Resources/minexpert/doc)
endif()

message(STATUS "CMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX}")
message(STATUS "MINEXPERT_BIN_DIR: ${MINEXPERT_BIN_DIR}")
message(STATUS "MINEXPERT_JAVASCRIPT_DIR ${MINEXPERT_JAVASCRIPT_DIR}")
message(STATUS "MINEXPERT_DATA_DIR: ${MINEXPERT_DATA_DIR}")
message(STATUS "MINEXPERT_DOC_DIR: ${MINEXPERT_DOC_DIR}")

# Prepare various directory names for the parent directory to use later.
set_directory_properties(PROPERTIES CMAKE_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX})
set_directory_properties(PROPERTIES MINEXPERT_TARGET_NAME ${TARGET})
set_directory_properties(PROPERTIES MINEXPERT_BIN_DIR ${MINEXPERT_BIN_DIR})
set_directory_properties(PROPERTIES MINEXPERT_JAVASCRIPT_DIR ${MINEXPERT_JAVASCRIPT_DIR})
set_directory_properties(PROPERTIES MINEXPERT_DATA_DIR ${MINEXPERT_DATA_DIR})
set_directory_properties(PROPERTIES MINEXPERT_DOC_DIR ${MINEXPERT_DOC_DIR})


###############################################################
# JavaScript material
###############################################################

add_subdirectory(javascript)

qt5_use_modules(${TARGET} Widgets)
qt5_use_modules(${TARGET} Xml)
qt5_use_modules(${TARGET} Svg)
qt5_use_modules(${TARGET} Sql)
qt5_use_modules(${TARGET} Script)
qt5_use_modules(${TARGET} PrintSupport)

include_directories(

	# The config file is binary directory-specific !!!
	# For the config.h file generated from config.h.in
	# For the ui_Xyyyyy.h files
	${CMAKE_CURRENT_BINARY_DIR}

	# For all the source subdirectories
	${CMAKE_SOURCE_DIR}

	${CMAKE_BINARY_DIR}/libmassgui

	${Qt5Widgets_INCLUDE_DIRS}
	${Qt5Xml_INCLUDE_DIRS}
	${Qt5Svg_INCLUDE_DIRS}
	${Qt5Sql_INCLUDE_DIRS}
	${Qt5Script_INCLUDE_DIRS}
	${Qt5PrintSupport_INCLUDE_DIRS})


# On GNU/Linux, make sure we have the QCustomPlot library
# installed on the system (on MINGW, we have the
# source files (see above).
if(NOT WIN64 AND NOT APPLE)

	find_package(QCustomPlot)

	if(NOT QCustomPlot_FOUND)
		message(FATAL_ERROR "QCustomPlot not found!")
	else()
		message(STATUS "QCustomPlot found!")
	endif()

endif()

# Now handle the private libraries for non-gui stuff (libmass.a) and gui stuff
# (libmassgui.a)
if(APPLE)

	set(MASSLIB "${CMAKE_BINARY_DIR}/libmass/libmass.a")
	set(MASSGUILIB "${CMAKE_BINARY_DIR}/libmassgui/libmassgui.a")

else()

	set(MASSLIB "-Wl,-whole-archive ${CMAKE_BINARY_DIR}/libmass/libmass.a -Wl,-no-whole-archive")
	set(MASSGUILIB "-Wl,-whole-archive ${CMAKE_BINARY_DIR}/libmassgui/libmassgui.a -Wl,-no-whole-archive")

endif()

message(STATUS "libdir: ${CMAKE_BINARY_DIR}/libmass/libmass.a")
message(STATUS "guilibdir: ${CMAKE_BINARY_DIR}/libmassgui/libmassgui.a")

message(STATUS "Using parallelizing library ${OPENMP_LIBRARY}")

set(required_target_link_libraries
	${MASSLIB}
	${MASSGUILIB}
	${OPENMP_LIBRARY}
	Qt5::Widgets
	Qt5::Xml
	Qt5::Svg
	Qt5::Sql
	Qt5::Script
	Qt5::PrintSupport)


# On WIN64 we provide a number of libraries by our own, that we
# put in /usr/local/lib under /mingw64/.
if(WIN64)
	set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -LC:/msys64/mingw64/usr/local/lib")
endif()


##############################################################
# libpwiz for reading mass spec data files,
message(STATUS "${BoldYellow}Link against the libpwiz library.${ColourReset}")
if(WIN64)
	include_directories("C:/msys64/mingw64/usr/local/include/pwiz")
elseif(APPLE)
	include_directories("/opt/local/include/pwiz")
	link_directories("/opt/local/lib")
else()
	include_directories("/usr/include/pwiz")
endif()

set(required_target_link_libraries
	${required_target_link_libraries}
	pwiz)

##############################################################
# libboost_* on mingw
# On MINGW.* we are our own provider of the boost libraries.
if(WIN64)

	message(STATUS "${BoldYellow}Link against the libboost libraries.${ColourReset}")

	include_directories("${CMAKE_SOURCE_DIR}/../../boost/boost_1_56_0")

	set(required_target_link_libraries
		${required_target_link_libraries}
		boost_chrono
		boost_filesystem
		boost_iostreams
		boost_program_options
		boost_serialization
		boost_system
		boost_thread
		z)

elseif(APPLE)
	# With macport
	include_directories("/opt/local/include")
	# Attention #####
	# below for
	# /opt/local/include/pwiz/libraries/boost_aux/boost/utility/singleton.hpp
	include_directories("/opt/local/include/pwiz/libraries/boost_aux")
	link_directories("/opt/local/lib")

	set(required_target_link_libraries
		${required_target_link_libraries}
		boost_chrono-mt
		boost_filesystem-mt
		boost_iostreams-mt
		boost_program_options-mt
		boost_serialization-mt
		boost_system-mt
		boost_thread-mt
		z)

endif()

# On MINGW.*, we'll need to add the -lstdc++ flag. Don't ask why.
if(WIN64)

	set(required_target_link_libraries
		${required_target_link_libraries}
		"stdc++")

endif()

# When on UNIX/NOT APPLE we can make use the system-wide qcustomplot library.
if(UNIX AND NOT APPLE)

	set(required_target_link_libraries
		${required_target_link_libraries}
		"qcustomplot")

endif()


#### Debugging stuff
#message(STATUS required_target_link_libraries: ${required_target_link_libraries})

#message(STATUS "Now printing all the include directories -I...")

#get_property(dirs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES)
#foreach(dir ${dirs})
	#message(STATUS "included dir='${dir}'")
#endforeach()

#message(STATUS "Now printing all the linking directories -L...")

#get_property(dirs DIRECTORY PROPERTY LINK_DIRECTORIES)
#foreach(dir ${dirs})
	#message(STATUS "link directory dir='${dir}'")
#endforeach()

# Finally actually set the linking dependencies to the executable.
target_link_libraries(${TARGET}
	${required_target_link_libraries})


# Add an explicit dependency to libmass and libmassgui so that when invoking
# make from inside the massxpert bin build dir, the dependencies get built.
add_dependencies(${TARGET} mass massgui)

if(PROFILE)
	message(STATUS "Profiling is requested, adding linker -pg flag.")
	set (CMAKE_EXE_LINKER_FLAGS "-pg")
endif()

if(NOT APPLE)
	# We want to install the binary arch-dependent target in
	# specific situations. To have proper control, we define the arch
	# component.
	install(TARGETS ${TARGET}
		RUNTIME
		COMPONENT arch
		DESTINATION ${MINEXPERT_BIN_DIR})
endif()


#############################################################
##########################
# EXTRACTION OF THE JAVASCRIPT-RELATED DOCUMENTATION FROM THE SOURCE FILES

if(UNIX AND NOT APPLE)
	if(DEVMODE)

		message(STATUS "mineXpert: extracting JavaScript-related documentation")
		execute_process(COMMAND devdoc/scripts/jsExtract.py -i libmass/DataPointJs.cpp
			libmass/DataPointJsPrototype.cpp
			minexpert/nongui/SavGolParamsJSDoc.cpp
			minexpert/nongui/SavGolFilterJs.cpp minexpert/nongui/SavGolFilterJsPrototype.cpp
			minexpert/nongui/MzIntegrationParamsJs.cpp minexpert/nongui/MzIntegrationParamsJsPrototype.cpp
			libmass/TraceJs.cpp libmass/TraceJsPrototype.cpp
			libmass/MassSpectrumJs.cpp libmass/MassSpectrumJsPrototype.cpp
			minexpert/gui/AbstractPlotWidget.cpp minexpert/gui/ColorMapPlotWidget.cpp
			minexpert/gui/TicChromPlotWidget.cpp minexpert/gui/MassSpecPlotWidget.cpp
			minexpert/gui/DriftSpecPlotWidget.cpp minexpert/gui/MainWindow.cpp
			minexpert/gui/SqlMassDataSlicerWnd.cpp
			OUTPUT_FILE minexpert/user-manual/devdoc-javascript-reference.txt
			WORKING_DIRECTORY	${CMAKE_SOURCE_DIR})

	endif()
endif()

#############################################################
##########################
# BUILD OF THE USER MANUAL

message(STATUS "mineXpert User Manual to be built")
add_subdirectory(user-manual)


message("")
message(STATUS "${BoldGreen}Finished configuring of the mineXpert submodule.${ColourReset}")
message("")
