# Copyright (c) 2025 Dominic Masters
# 
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT

# Setup
cmake_minimum_required(VERSION 3.13)

set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules)
cmake_policy(SET CMP0079 NEW)
set(FETCHCONTENT_UPDATES_DISCONNECTED ON)

option(DUSK_BUILD_TESTS "Enable tests" OFF)

# Prep cache
set(DUSK_CACHE_TARGET "dusk-target")

# Build variables
set(DUSK_ROOT_DIR "${CMAKE_SOURCE_DIR}")
set(DUSK_BUILD_DIR "${CMAKE_BINARY_DIR}")
set(DUSK_SOURCES_DIR "${DUSK_ROOT_DIR}/src")
set(DUSK_TEST_DIR "${DUSK_ROOT_DIR}/test")
set(DUSK_TEMP_DIR "${DUSK_BUILD_DIR}/temp")
set(DUSK_TOOLS_DIR "${DUSK_ROOT_DIR}/tools")
set(DUSK_DATA_DIR "${DUSK_ROOT_DIR}/data")
set(DUSK_ASSETS_DIR "${DUSK_ROOT_DIR}/assets")
set(DUSK_BUILT_ASSETS_DIR "${DUSK_BUILD_DIR}/built_assets" CACHE INTERNAL ${DUSK_CACHE_TARGET})
set(DUSK_GENERATED_HEADERS_DIR "${DUSK_BUILD_DIR}/generated")
set(DUSK_BUILD_BINARY ${DUSK_BUILD_DIR}/Dusk CACHE INTERNAL ${DUSK_CACHE_TARGET})
set(DUSK_ASSETS "" CACHE INTERNAL ${DUSK_CACHE_TARGET})
set(DUSK_LIBRARY_TARGET_NAME "DuskCore" CACHE INTERNAL ${DUSK_CACHE_TARGET})
set(DUSK_BINARY_TARGET_NAME "Dusk" CACHE INTERNAL ${DUSK_CACHE_TARGET})
set(DUSK_ASSETS_ZIP "${DUSK_BUILD_DIR}/dusk.dsk" CACHE INTERNAL ${DUSK_CACHE_TARGET})

if(NOT DEFINED DUSK_TARGET_SYSTEM)
  set(DUSK_TARGET_SYSTEM "linux")
endif()

# Create directories
file(MAKE_DIRECTORY ${DUSK_GENERATED_HEADERS_DIR})
file(MAKE_DIRECTORY ${DUSK_TEMP_DIR})
file(MAKE_DIRECTORY ${DUSK_BUILT_ASSETS_DIR})

# Required build packages
find_package(Python3 COMPONENTS Interpreter REQUIRED)

# Init Project.
project(${DUSK_LIBRARY_TARGET_NAME}
  VERSION 1.0.0
  LANGUAGES C
)

# Either, create library and binary separately (used for tests), or make them
# one in the same so all code is in the binary only.
# Binary Executable
add_executable(${DUSK_BINARY_TARGET_NAME} ${DUSK_SOURCES_DIR}/dusk/null.c)

if(DUSK_BUILD_TESTS)
  # MainLibrary
  add_library(${DUSK_LIBRARY_TARGET_NAME} STATIC)

  # Link library to binary
  target_link_libraries(${DUSK_BINARY_TARGET_NAME}
    PUBLIC
      ${DUSK_LIBRARY_TARGET_NAME}
  )
else()
  set(DUSK_LIBRARY_TARGET_NAME "${DUSK_BINARY_TARGET_NAME}" CACHE INTERNAL ${DUSK_CACHE_TARGET})
endif()

# Definitions
target_compile_definitions(${DUSK_LIBRARY_TARGET_NAME}
  PUBLIC
    DUSK_TARGET_SYSTEM="${DUSK_TARGET_SYSTEM}"
)

# Toolchains
include(cmake/targets/${DUSK_TARGET_SYSTEM}.cmake)

# Add tools
add_subdirectory(tools)

# Include generated headers from tools.
target_include_directories(${DUSK_LIBRARY_TARGET_NAME} PUBLIC
  ${DUSK_GENERATED_HEADERS_DIR}
)

# Add main code
add_subdirectory(${DUSK_SOURCES_DIR})

# Include generated headers
target_include_directories(${DUSK_LIBRARY_TARGET_NAME} PUBLIC
  ${DUSK_GENERATED_HEADERS_DIR}
)

# Handle tests
if(DUSK_BUILD_TESTS)
  enable_testing()
  add_subdirectory(test)
endif()

# Build assets
file(GLOB_RECURSE DUSK_ASSET_FILES CONFIGURE_DEPENDS "${DUSK_ASSETS_DIR}/*")
add_custom_command(
  OUTPUT "${DUSK_ASSETS_ZIP}"
  COMMAND ${CMAKE_COMMAND} -E make_directory "${DUSK_ASSETS_DIR}"
  COMMAND ${CMAKE_COMMAND} -E rm -f "${DUSK_ASSETS_ZIP}"
  COMMAND ${CMAKE_COMMAND} -E tar "cf" "${DUSK_ASSETS_ZIP}" --format=zip -- .
  WORKING_DIRECTORY "${DUSK_ASSETS_DIR}"
  DEPENDS ${DUSK_ASSET_FILES}
  VERBATIM
)
add_custom_target(DUSK_ASSETS_BUILT DEPENDS "${DUSK_ASSETS_ZIP}")
add_dependencies(${DUSK_LIBRARY_TARGET_NAME} DUSK_ASSETS_BUILT)
