if(JDUTIL_HELPERS)
	return()
endif()
set(JDUTIL_HELPERS 1)

macro(prepend_to_list variable str)
	set(out )
	foreach(item ${${variable}})
		list(APPEND out ${str}${item})
	endforeach()
	set(${variable} ${out})
endmacro()

macro(add_ui_files variable)
	foreach(basename ${ARGN})
		set(${variable} ${${variable}}
			${basename}.h
			${basename}.cpp
			${basename}.ui
		)
	endforeach()
endmacro()

macro(add_qrc_files variable)
	qt5_add_resources(_qrc_out ${ARGN})
	foreach(qrcfile ${_qrc_out})
		set_source_files_properties(${qrcfile} PROPERTIES COMPILE_FLAGS -Wno-global-constructors)
	endforeach()
	set(${variable} ${${variable}} ${_qrc_out})
endmacro()

macro(clean_qt target)
	target_compile_definitions(${target} PRIVATE QT_NO_CAST_FROM_ASCII=1 QT_NO_CAST_TO_ASCII=1)
endmacro()

if(APPLE)
	set(JDUTIL_OS_BUNDLE MACOSX_BUNDLE)
elseif(WIN32)
	set(JDUTIL_OS_BUNDLE WIN32)
endif()

set(_helpers_path ${CMAKE_CURRENT_LIST_DIR})
function(setup_app variable copyright identifier iconfilebase)
	if(APPLE)
		set(_icon_file ${iconfilebase}.icns)
		set_source_files_properties(${_icon_file} PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
		set(MACOSX_BUNDLE_BUNDLE_NAME ${PROJECT_NAME})
		set(MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION})
		set(MACOSX_BUNDLE_LONG_VERSION_STRING ${PROJECT_VERSION})
		set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}")
		set(MACOSX_BUNDLE_COPYRIGHT ${copyright})
		set(MACOSX_BUNDLE_GUI_IDENTIFIER ${identifier})
		set(MACOSX_BUNDLE_ICON_FILE ${_icon_file})
		list(APPEND ${variable} ${_icon_file})
	elseif(WIN32)
		set(_icon_file ${iconfilebase}.ico)
		configure_file("${_helpers_path}/data/windows_metafile.rc.in" ${CMAKE_CURRENT_BINARY_DIR}/"windows.rc")
		set(CMAKE_RC_COMPILER_INIT windres)
		enable_language(RC)
		set(CMAKE_RC_COMPILE_OBJECT "<CMAKE_RC_COMPILER> <FLAGS> -O coff <DEFINES> -i <SOURCE> -o <OBJECT>")
		list(APPEND ${variable} ${CMAKE_CURRENT_BINARY_DIR}/"windows.rc")
	endif()
endfunction()

function(gather_flags opts target libs)
	get_target_property(includes ${target} INTERFACE_INCLUDE_DIRECTORIES)
	if(includes)
		foreach(include ${includes})
			set(opts "${opts} -isystem ${include}")
		endforeach()
	endif()

	get_target_property(defines ${target} INTERFACE_COMPILE_DEFINITIONS)
	if(defines)
		foreach(define ${defines})
			if(NOT define MATCHES "^\\$<.*>$")
				set(opts "${opts} -D${define}")
			endif()
		endforeach()
	endif()

	get_target_property(options ${target} INTERFACE_COMPILE_OPTIONS)
	if(options)
		foreach(option ${options})
			set(opts "${opts} ${option}")
		endforeach()
	endif()

	get_target_property(libs ${target} LINK_LIBRARIES)
	if(libs)
		foreach(lib ${libs})
			if(${lib} IN_LIST libs)
				gather_flags("${opts}" ${lib} "${libs};${target}")
			endif()
		endforeach()
	endif()

	set(opts ${opts} PARENT_SCOPE)
	set(libs ${libs} ${target} PARENT_SCOPE)
endfunction()

function(gather_flags_for_target target)
	gather_flags("" ${target} ${target})

	get_target_property(libs ${target} LINK_LIBRARIES)
	if(libs)
		foreach(lib ${libs})
			gather_flags("${opts}" ${lib} "${libs}")
		endforeach()
	endif()

	get_target_property(defines ${target} COMPILE_DEFINITIONS)
	if(defines)
		foreach(define ${defines})
			set(opts "${opts} -D${define}")
		endforeach()
	endif()

	get_target_property(options ${target} COMPILE_OPTIONS)
	if(options)
		foreach(option ${options})
			set(opts "${opts} ${option}")
		endforeach()
	endif()

	get_target_property(standard ${target} CXX_STANDARD)
	if(standard)
		set(opts "${opts} -std=c++${standard}")
	endif()

	get_target_property(includes ${target} INCLUDE_DIRECTORIES)
	if(includes)
		foreach(include ${includes})
			if(include MATCHES "^\\$<BUILD_INTERFACE:.*>$")
				string(REPLACE "$<BUILD_INTERFACE:" "" include "${include}")
				string(REPLACE ">" "" include "${include}")
				set(opts "${opts} -I${include}")
			elseif(NOT include MATCHES "^\\$<.*>$")
				if(include MATCHES "${CMAKE_CURRENT_SOURCE_DIR}/.*")
					set(opts "${opts} -I${include}")
				else()
					set(opts "${opts} -isystem ${include}")
				endif()
			endif()
		endforeach()
	endif()

	separate_arguments(opts UNIX_COMMAND "${opts}")
	set(opts "${opts}" PARENT_SCOPE)
endfunction()

function(append_if_valid_cxx_flag VAR FLAG OUTVAR)
	set(dir ${CMAKE_BINARY_DIR}/try_compile/${VAR})
	file(WRITE ${dir}/main.cpp "int main(){}")
	try_compile(flag_compiles_${VAR} ${dir} ${dir}/main.cpp COMPILE_DEFINITIONS ${FLAG})
	if(${flag_compiles_${VAR}})
		set(OUTVAR "${OUTVAR} ${FLAG}" PARENT_SCOPE)
	endif()
endfunction()
