
macro(cgv_launchconfig_prepare target)
	cgv_get_viewer_locations(VIEWER_EXE_TMP VIEWER_DEBUG_EXE_TMP)
	set(VIEWER_EXE ${VIEWER_EXE_TMP})
	set(VIEWER_EXE ${VIEWER_EXE_TMP} PARENT_SCOPE)
	set(VIEWER_DEBUG_EXE ${VIEWER_DEBUG_EXE_TMP})
	set(VIEWER_DEBUG_EXE ${VIEWER_DEBUG_EXE_TMP} PARENT_SCOPE)
	set_target_properties(${target} PROPERTIES LAUNCH_CONFIG_ARGUMENTS "")
	set (PLUGIN_POSTFIX "")
	if(NOT WIN32)
		if( (${CMAKE_BUILD_TYPE} MATCHES "Debug")
				OR (${CMAKE_BUILD_TYPE} MATCHES "DEBUG")
				OR (${CMAKE_BUILD_TYPE} MATCHES "debug") )
			# Postfix of "_d.so" for debug mode
			set(PLUGIN_POSTFIX "${CMAKE_DEBUG_POSTFIX}${CMAKE_SHARED_LIBRARY_SUFFIX}")
		else()
			set(PLUGIN_POSTFIX "${CMAKE_POSTFIX}${CMAKE_SHARED_LIBRARY_SUFFIX}")
		endif()
	endif()

	# 1st: plugins - loop through each and inject additional arguments as needed
	separate_arguments(PLUGINS)
	set(PLUGINS_COUNTER "0")
	foreach(plugin ${PLUGINS})
		if(PLUGINS_COUNTER EQUAL 1)
			# First plugin is assumed to be the GUI driver, so inject shader path before continuing on
			set(SHADER_PATH_STRING_UNESCAPED "")
			if ("${SHADER_PATH}" STREQUAL "")
				set(SHADER_PATH_STRING_UNESCAPED "type(shader_config):shader_path='${CGV_DIR}/libs/cgv_gl/glsl'")
			else()
				set(SHADER_PATH_STRING_UNESCAPED "type(shader_config):shader_path='${CGV_DIR}/libs/cgv_gl/glsl\;${SHADER_PATH}'")
			endif()
			string(REPLACE ";" "$<SEMICOLON>" SHADER_PATH_STRING ${SHADER_PATH_STRING_UNESCAPED})
			set_property(
				TARGET ${target} APPEND PROPERTY
				LAUNCH_CONFIG_ARGUMENTS ${SHADER_PATH_STRING}
			)
		endif()
		set_property(
			TARGET ${target} APPEND PROPERTY
			LAUNCH_CONFIG_ARGUMENTS "plugin:${plugin}${PLUGIN_POSTFIX}"
		)
		math(EXPR PLUGINS_COUNTER "${PLUGINS_COUNTER}+1")
	endforeach()

	# 2nd: application plugin
	set_property(
		TARGET ${target} APPEND PROPERTY
		LAUNCH_CONFIG_ARGUMENTS "plugin:${target}${PLUGIN_POSTFIX}"
	)

	# 3rd: GUI definition files
	separate_arguments(GUI_FILES)
	foreach(gui_file ${GUI_FILES})
		set_property(
			TARGET ${target} APPEND PROPERTY
			LAUNCH_CONFIG_ARGUMENTS "gui:${gui_file}"
		)
	endforeach()

	# 4th: config files
	separate_arguments(CONFIG_FILES)
	foreach(config_file ${CONFIG_FILES})
		set_property(
			TARGET ${target} APPEND PROPERTY
			LAUNCH_CONFIG_ARGUMENTS "config:${config_file}"
		)
	endforeach()

	# Final: add entry to global list of launchable application plugins
	set_property(GLOBAL APPEND PROPERTY CGV_APPLICATION_PLUGIN_TARGETS ${target})
endmacro()

macro(cgv_launchconfig_setup_vs target)
	get_target_property(ARGUMENT_LIST ${target} LAUNCH_CONFIG_ARGUMENTS)

	set(VS_DEBUGGER_STRING "")
	foreach(argument ${ARGUMENT_LIST})
		set(VS_DEBUGGER_STRING "${VS_DEBUGGER_STRING} ${argument}")
	endforeach()

	set_target_properties(${target} PROPERTIES VS_DEBUGGER_COMMAND $<IF:$<CONFIG:Debug>,${VIEWER_DEBUG_EXE},${VIEWER_EXE}>)
	set_target_properties(${target} PROPERTIES VS_DEBUGGER_COMMAND_ARGUMENTS ${VS_DEBUGGER_STRING})
	set_target_properties(${target} PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
endmacro()

macro(cgv_launchconfig_script_sh target)
	if(NOT MSVC)
		get_target_property(ARGUMENT_LIST ${target} LAUNCH_CONFIG_ARGUMENTS)

		set(VIEWER_ARGUMENTS_UNESCAPED "")
		foreach(argument ${ARGUMENT_LIST})
			set(VIEWER_ARGUMENTS_UNESCAPED "${VIEWER_ARGUMENTS_UNESCAPED} ${argument}")
		endforeach()
		string(REPLACE "$<SEMICOLON>" ";" VIEWER_ARGUMENTS ${VIEWER_ARGUMENTS_UNESCAPED})

		if((CMAKE_BUILD_TYPE STREQUAL "") OR (CMAKE_BUILD_TYPE STREQUAL "Release") OR (CMAKE_BUILD_TYPE STREQUAL "MinSizeRel"))
			configure_file(${cgv_DIR}/templates/shell_run.sh.in ${CMAKE_BINARY_DIR}/tmp/${target}.sh @ONLY)
			file(COPY
				${CMAKE_BINARY_DIR}/tmp/${target}.sh
				DESTINATION ${CMAKE_BINARY_DIR}
				FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
			)
			file(REMOVE_RECURSE ${CMAKE_BINARY_DIR}/tmp/${target}.sh)
		elseif((CMAKE_BUILD_TYPE STREQUAL "Debug") OR (CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo"))
			configure_file(${cgv_DIR}/templates/shell_debug.sh.in ${CMAKE_BINARY_DIR}/tmp/${target}_dbg.sh @ONLY)
			file(COPY
				${CMAKE_BINARY_DIR}/tmp/${target}_dbg.sh
				DESTINATION ${CMAKE_BINARY_DIR}
				FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
			)
			file(REMOVE_RECURSE ${CMAKE_BINARY_DIR}/tmp/${target}_dbg.sh)
		endif()
	endif()
endmacro()

macro(cgv_launchconfig_singlefile_vscode)
	# Load file parts
	file(READ "${cgv_DIR}/templates/launch.json.header" LAUNCH_JSON_HEADER)
	file(READ "${cgv_DIR}/templates/launch.json.singleconf" LAUNCH_JSON_SINGLECONF)
	file(READ "${cgv_DIR}/templates/launch.json.footer" LAUNCH_JSON_FOOTER)

	set(LAUNCH_JSON_LOCATION ${CMAKE_SOURCE_DIR}/.vscode/launch.json)
	file(WRITE ${LAUNCH_JSON_LOCATION} ${LAUNCH_JSON_HEADER})
	get_property(TARGET_LIST GLOBAL PROPERTY CGV_APPLICATION_PLUGIN_TARGETS)
	set(TARGET_COUNTER "0")
	foreach(target ${TARGET_LIST})
		set(LAUNCH_TARGET_NAME ${target})
		set(ARGUMENT_LIST "")
		get_target_property(ARGUMENT_LIST ${target} LAUNCH_CONFIG_ARGUMENTS)
		set(LAUNCH_TARGET_ARGS_UNESCAPED "")
		set(ARGS_COUNTER "0")
		foreach(argument ${ARGUMENT_LIST})
			if(ARGS_COUNTER EQUAL 0)
				set(LAUNCH_TARGET_ARGS_UNESCAPED "\"${argument}\"")
			else()
				set(LAUNCH_TARGET_ARGS_UNESCAPED "${LAUNCH_TARGET_ARGS_UNESCAPED}, \"${argument}\"")
			endif()
			math(EXPR ARGS_COUNTER "${ARGS_COUNTER}+1")
		endforeach()
		string(REPLACE "$<SEMICOLON>" ";" LAUNCH_TARGET_ARGS ${LAUNCH_TARGET_ARGS_UNESCAPED})
		set(LAUNCH_JSON_CURRENTCONF "")
		string(CONFIGURE ${LAUNCH_JSON_SINGLECONF} LAUNCH_JSON_CURRENTCONF @ONLY)
		if(TARGET_COUNTER GREATER 0)
			set(LAUNCH_JSON_CURRENTCONF ", "${LAUNCH_JSON_CURRENTCONF})
		endif()
		file(APPEND ${LAUNCH_JSON_LOCATION} ${LAUNCH_JSON_CURRENTCONF})
		math(EXPR TARGET_COUNTER "${TARGET_COUNTER}+1")
	endforeach()
	file(APPEND ${LAUNCH_JSON_LOCATION} ${LAUNCH_JSON_FOOTER})
endmacro()
