cmake_minimum_required(VERSION 3.24)

project(video_shader LANGUAGES C CXX)

include(CTest)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

set(SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src")
set(TEST_DIR "${CMAKE_CURRENT_SOURCE_DIR}/tests")
set(SLANG_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/3rdParty/slang-2026.8-windows-x86_64" CACHE PATH "Path to a Slang binary release containing bin/slangc.exe")
set(MSDF_ATLAS_GEN_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/3rdParty/msdf-atlas-gen" CACHE PATH "Path to msdf-atlas-gen binary release")

set(VIDEO_SHADER_INCLUDE_DIRS
	"${SRC_DIR}"
	"${SRC_DIR}/app"
	"${SRC_DIR}/control"
	"${SRC_DIR}/control/http"
	"${SRC_DIR}/frames"
	"${SRC_DIR}/json"
	"${SRC_DIR}/logging"
	"${SRC_DIR}/platform"
	"${SRC_DIR}/preview"
	"${SRC_DIR}/render"
	"${SRC_DIR}/render/readback"
	"${SRC_DIR}/render/thread"
	"${SRC_DIR}/render/runtime"
	"${SRC_DIR}/runtime"
	"${SRC_DIR}/runtime/catalog"
	"${SRC_DIR}/runtime/layers"
	"${SRC_DIR}/runtime/shader"
	"${SRC_DIR}/runtime/state"
	"${SRC_DIR}/runtime/text"
	"${SRC_DIR}/shader"
	"${SRC_DIR}/telemetry"
	"${SRC_DIR}/video"
)

function(video_shader_target_defaults target)
	target_include_directories(${target} PRIVATE ${VIDEO_SHADER_INCLUDE_DIRS})
	target_compile_definitions(${target} PRIVATE _UNICODE UNICODE)
	if(MSVC)
		target_compile_options(${target} PRIVATE /W3)
	endif()
endfunction()

function(video_shader_files_exist out_var)
	set(missing_files)
	foreach(file IN LISTS ARGN)
		if(NOT EXISTS "${file}")
			list(APPEND missing_files "${file}")
		endif()
	endforeach()
	set(${out_var} "${missing_files}" PARENT_SCOPE)
endfunction()

function(add_video_shader_test name)
	add_executable(${name} ${ARGN})
	video_shader_target_defaults(${name})
	add_test(NAME ${name} COMMAND ${name})
endfunction()

set(RUNTIME_JSON_SOURCES
	"${SRC_DIR}/runtime/state/RuntimeJson.cpp"
)

set(RUNTIME_PARAMETER_SOURCES
	${RUNTIME_JSON_SOURCES}
	"${SRC_DIR}/runtime/state/RuntimeParameterUtils.cpp"
)

set(RUNTIME_STATE_SOURCES
	${RUNTIME_JSON_SOURCES}
	"${SRC_DIR}/runtime/state/RuntimeStatePersistence.cpp"
)

set(RUNTIME_LAYER_SOURCES
	"${SRC_DIR}/runtime/layers/RuntimeLayerModel.cpp"
	"${SRC_DIR}/runtime/layers/RuntimeLayerReload.cpp"
	"${SRC_DIR}/runtime/layers/RuntimeLayerSnapshot.cpp"
	"${SRC_DIR}/runtime/layers/RuntimeLayerStateRestore.cpp"
)

set(RUNTIME_TEXT_SOURCES
	"${SRC_DIR}/runtime/text/FontAtlasBuilder.cpp"
	"${SRC_DIR}/runtime/text/FontAtlasImageLoader.cpp"
	"${SRC_DIR}/runtime/text/FontAtlasMetadata.cpp"
	"${SRC_DIR}/runtime/text/FontAtlasProcess.cpp"
	"${SRC_DIR}/runtime/text/RuntimeTextTextureComposer.cpp"
)

set(RUNTIME_CATALOG_SOURCES
	"${SRC_DIR}/runtime/catalog/SupportedShaderCatalog.cpp"
)

set(SHADER_MANIFEST_SOURCES
	"${SRC_DIR}/shader/ShaderManifestAssets.cpp"
	"${SRC_DIR}/shader/ShaderManifestParameters.cpp"
	"${SRC_DIR}/shader/ShaderManifestParser.cpp"
	"${SRC_DIR}/shader/ShaderPackageRegistry.cpp"
)

set(SLANG_RUNTIME_FILES
	"${SLANG_ROOT}/bin/slangc.exe"
	"${SLANG_ROOT}/bin/slang-compiler.dll"
	"${SLANG_ROOT}/bin/slang-glslang.dll"
)
set(SLANG_LICENSE_FILE "${SLANG_ROOT}/LICENSE")
set(MSDF_ATLAS_GEN_EXE_FILE "${MSDF_ATLAS_GEN_ROOT}/msdf-atlas-gen.exe")
file(GLOB MSDF_ATLAS_GEN_DLL_FILES CONFIGURE_DEPENDS
	"${MSDF_ATLAS_GEN_ROOT}/*.dll"
)
set(MSDF_ATLAS_GEN_RUNTIME_FILES
	"${MSDF_ATLAS_GEN_EXE_FILE}"
	${MSDF_ATLAS_GEN_DLL_FILES}
)
set(MSDF_ATLAS_GEN_LICENSE_FILE "${MSDF_ATLAS_GEN_ROOT}/LICENSE.txt")
set(MSDF_ATLAS_GEN_README_FILE "${MSDF_ATLAS_GEN_ROOT}/README.md")

set(RENDER_CADENCE_APP_REQUIRED_FILES
	"${SRC_DIR}/RenderCadenceCompositor.cpp"
	"${SRC_DIR}/video/DeckLinkAPI_i.c"
	"${SRC_DIR}/video/DeckLinkAPI_h.h"
)

video_shader_files_exist(RENDER_CADENCE_APP_MISSING_FILES ${RENDER_CADENCE_APP_REQUIRED_FILES})
if(RENDER_CADENCE_APP_MISSING_FILES)
	message(STATUS "RenderCadenceCompositor target skipped; required app entry or external DeckLink SDK shim files are missing:")
	foreach(missing_file IN LISTS RENDER_CADENCE_APP_MISSING_FILES)
		message(STATUS "  ${missing_file}")
	endforeach()
else()
	file(GLOB_RECURSE RENDER_CADENCE_APP_SOURCES CONFIGURE_DEPENDS
		"${SRC_DIR}/*.c"
		"${SRC_DIR}/*.cpp"
		"${SRC_DIR}/*.h"
	)
	list(REMOVE_ITEM RENDER_CADENCE_APP_SOURCES
		"${SRC_DIR}/video/VideoBackend.cpp"
		"${SRC_DIR}/video/VideoBackend.h"
	)

	add_executable(RenderCadenceCompositor ${RENDER_CADENCE_APP_SOURCES})
	video_shader_target_defaults(RenderCadenceCompositor)
	target_link_libraries(RenderCadenceCompositor PRIVATE
		opengl32
		Ole32
		Windowscodecs
		Ws2_32
	)
	source_group(TREE "${SRC_DIR}" FILES ${RENDER_CADENCE_APP_SOURCES})
endif()

if(BUILD_TESTING)
	add_subdirectory(tests)
endif()

if(TARGET RenderCadenceCompositor)
	install(TARGETS RenderCadenceCompositor
		RUNTIME DESTINATION "."
	)
endif()

foreach(slang_runtime_file IN LISTS SLANG_RUNTIME_FILES)
	if(EXISTS "${slang_runtime_file}")
		install(FILES "${slang_runtime_file}"
			DESTINATION "3rdParty/slang/bin"
		)
	else()
		message(STATUS "Slang runtime file not found and will not be installed: ${slang_runtime_file}")
	endif()
endforeach()

foreach(msdf_runtime_file IN LISTS MSDF_ATLAS_GEN_RUNTIME_FILES)
	if(EXISTS "${msdf_runtime_file}")
		install(FILES "${msdf_runtime_file}"
			DESTINATION "3rdParty/msdf-atlas-gen"
		)
	else()
		message(STATUS "msdf-atlas-gen runtime file not found and will not be installed: ${msdf_runtime_file}")
	endif()
endforeach()

if(EXISTS "${MSDF_ATLAS_GEN_LICENSE_FILE}")
	install(FILES "${MSDF_ATLAS_GEN_LICENSE_FILE}"
		DESTINATION "third_party_notices"
		RENAME "MSDF_ATLAS_GEN_LICENSE.txt"
	)
else()
	message(STATUS "msdf-atlas-gen license file not found: ${MSDF_ATLAS_GEN_LICENSE_FILE}")
endif()

if(EXISTS "${MSDF_ATLAS_GEN_README_FILE}")
	install(FILES "${MSDF_ATLAS_GEN_README_FILE}"
		DESTINATION "third_party_notices"
		RENAME "MSDF_ATLAS_GEN_README.md"
	)
else()
	message(STATUS "msdf-atlas-gen readme file not found: ${MSDF_ATLAS_GEN_README_FILE}")
endif()

if(EXISTS "${SLANG_LICENSE_FILE}")
	install(FILES "${SLANG_LICENSE_FILE}"
		DESTINATION "third_party_notices"
		RENAME "SLANG_LICENSE.txt"
	)
else()
	message(STATUS "Slang license file not found and will not be installed: ${SLANG_LICENSE_FILE}")
endif()

install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/shaders/SHADER_CONTRACT.md"
	DESTINATION "."
)

install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/config/"
	DESTINATION "config"
)

install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/shaders/"
	DESTINATION "shaders"
)

install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/runtime/templates/"
	DESTINATION "runtime/templates"
)

install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/runtime/README.md"
	DESTINATION "runtime"
)

install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/ui/dist/"
	DESTINATION "ui/dist"
	OPTIONAL
)

install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/docs/"
	DESTINATION "docs"
	OPTIONAL
)
