#*******************************************************************************
# Copyright (c) 2025-2026 ZF Friedrichshafen AG
#
# This program and the accompanying materials are made available under the 
# terms of the Apache License Version 2.0 which is available at
# https://www.apache.org/licenses/LICENSE-2.0
#
# SPDX-License-Identifier: Apache-2.0 
#*******************************************************************************


# Based on CMakeLists.txt from https://github.com/modelica/Reference-FMUs
# only FMI 2.0, only CoSimulation
# without fumsim


# Only valid for Windows
if ( WIN32 )

   # Enforce CMake version 3.20 or newer needed for path function
   cmake_minimum_required (VERSION 3.20)

   # Use new policy for project version settings and default warning level
   cmake_policy(SET CMP0048 NEW)   # requires CMake 3.14
   cmake_policy(SET CMP0092 NEW)   # requires CMake 3.15

   project (Doors4ExampleFMUProject)

   # Use C++17 support
   set(CMAKE_CXX_STANDARD 17)

   # Library symbols are hidden by default
   set(CMAKE_CXX_VISIBILITY_PRESET hidden)

   # Set the SDV_FRAMEWORK_DEV_INCLUDE if not defined yet
   if (NOT DEFINED SDV_FRAMEWORK_DEV_INCLUDE)
       if (NOT DEFINED ENV{SDV_FRAMEWORK_DEV_INCLUDE})
           message( FATAL_ERROR "The environment variable SDV_FRAMEWORK_DEV_INCLUDE needs to be pointing to the SDV V-API development include files location!")
       endif()
       set (SDV_FRAMEWORK_DEV_INCLUDE "$ENV{SDV_FRAMEWORK_DEV_INCLUDE}")
   endif()

   # Include link to export directory of SDV V-API development include files location
   include_directories(${SDV_FRAMEWORK_DEV_INCLUDE})
   set(VAPI_CORE_SDV_BINARY_DIR ${CMAKE_BINARY_DIR}/bin)
   set(MODEL_NAME Doors4ExampleFMU)
   set(TARGET_NAME ${MODEL_NAME})
   set(FMU_FULL_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/fmus/${MODEL_NAME}.fmu")    

   FUNCTION(cat IN_FILE OUT_FILE)
       file(READ ${IN_FILE} CONTENTS)
       file(APPEND ${OUT_FILE} "${CONTENTS}")
   ENDFUNCTION()

   set(FMI_VERSION 2 CACHE STRING "FMI Version")
   set_property(CACHE FMI_VERSION PROPERTY STRINGS 2)

   set(FMI_TYPE CS CACHE STRING "FMI Version")
   set_property(CACHE FMI_TYPE PROPERTY STRINGS CS)
   set(FMI_TYPE "")

   set (FMI_PLATFORM win32)
   if ("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
       set (FMI_PLATFORM win64)
   endif ()

   SET(HEADERS
       ${MODEL_NAME}/config.h
       include/cosimulation.h
       include/model.h
   )

   SET(HEADERS
       ${HEADERS}
       include/fmi2Functions.h
       include/fmi2FunctionTypes.h
       include/fmi2TypesPlatform.h
   )

   SET(SOURCES
       ${MODEL_NAME}/model.cpp
       src/fmi${FMI_VERSION}Functions.c
       src/cosimulation.c
   )

   add_library(${TARGET_NAME} SHARED
       ${HEADERS}
       ${SOURCES}
       ${MODEL_NAME}/FMI${FMI_VERSION}${FMI_TYPE}.xml
       ${MODEL_NAME}/buildDescription.xml
   )

   file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/fmus)

   set(FMU_BUILD_DIR temp/${MODEL_NAME})
   target_compile_definitions(${TARGET_NAME} PRIVATE
       FMI_VERSION=${FMI_VERSION}
       DISABLE_PREFIX
   )

   #[[
   if (MSVC)
       set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
   else()
       set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libstdc++ -static-libgcc")
       set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libstdc++ -static-libgcc")
   endif()
   ]]

   target_compile_definitions(${TARGET_NAME} PRIVATE FMI_COSIMULATION)
   target_include_directories(${TARGET_NAME} PRIVATE include ${MODEL_NAME})
   target_link_libraries(${TARGET_NAME} Winmm Ws2_32 Rpcrt4.lib)

   set_target_properties(${TARGET_NAME} PROPERTIES
       RUNTIME_OUTPUT_DIRECTORY         "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}"
       RUNTIME_OUTPUT_DIRECTORY_DEBUG   "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}"
       RUNTIME_OUTPUT_DIRECTORY_RELEASE "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}"
       LIBRARY_OUTPUT_DIRECTORY         "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}"
       LIBRARY_OUTPUT_DIRECTORY_DEBUG   "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}"
       LIBRARY_OUTPUT_DIRECTORY_RELEASE "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}"
       ARCHIVE_OUTPUT_DIRECTORY         "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}"
       ARCHIVE_OUTPUT_DIRECTORY_DEBUG   "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}"
       ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}"
   )

   set_target_properties(${TARGET_NAME} PROPERTIES PREFIX "")
   set_target_properties(${TARGET_NAME} PROPERTIES OUTPUT_NAME ${MODEL_NAME})

   # modelDescription.xml
   add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy
       ${CMAKE_CURRENT_SOURCE_DIR}/${MODEL_NAME}/FMI${FMI_VERSION}${FMI_TYPE}.xml
       "${FMU_BUILD_DIR}/modelDescription.xml"
   )
   
   set(ARCHIVE_FILES "modelDescription.xml" "binaries")
   if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${MODEL_NAME}/resources")
       add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory
           "${CMAKE_CURRENT_SOURCE_DIR}/${MODEL_NAME}/resources"
           "${FMU_BUILD_DIR}/resources/"
       )
       set(ARCHIVE_FILES ${ARCHIVE_FILES} "resources")
   endif()

   # When windows robocopy command (using cmd.exe) is used to copy files its important to set the dependencies
   # to assure that the copy command is finished before the next custom action to avoid copy/file access failures

   # Copy sdv binaries of this FMU 
   set(DEST_DIR "${FMU_BUILD_DIR}/resources")
   set(SOURCE_DIR_EXAMPLES_BIN "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}")
   add_custom_target(copy_function_sdv_files_${TARGET_NAME} DEPENDS ${TARGET_NAME}) 
   add_custom_command(TARGET copy_function_sdv_files_${TARGET_NAME} 
       COMMAND cmd /C "robocopy \"${SOURCE_DIR_EXAMPLES_BIN}\" \"${DEST_DIR}\" *.pdb *.sdv /NP /R:3 /W:5 || exit /b 0"
       COMMENT "Copying contents from ${SOURCE_DIR_EXAMPLES_BIN} to ${DEST_DIR}, include only *.pdb *.sdv files"
   )  
   add_dependencies(copy_function_sdv_files_${TARGET_NAME} ${TARGET_NAME})



   # Copy framework sdv binaries
   set(SOURCE_DIR_CORE_BIN "${SDV_FRAMEWORK_RUNTIME}")
   add_custom_target(copy_framework_sdv_files_${TARGET_NAME} DEPENDS copy_function_sdv_files_${TARGET_NAME}) 
   add_custom_command(TARGET copy_framework_sdv_files_${TARGET_NAME}
       COMMAND cmd /C "robocopy \"${SOURCE_DIR_CORE_BIN}\" \"${DEST_DIR}\" *.pdb *.sdv /NP /R:3 /W:5 || exit /b 0"
       COMMENT "Copying contents from ${SOURCE_DIR_CORE_BIN} to ${DEST_DIR}, include only *.pdb *.sdv files"
   )  
   add_dependencies(copy_framework_sdv_files_${TARGET_NAME} copy_function_sdv_files_${TARGET_NAME})



   # FMU content created, all files copied
   # to zip the files create a new target 'create_zip' which is build after all files have been copied
   add_custom_target(create_zip_${TARGET_NAME} ALL DEPENDS copy_framework_sdv_files_${TARGET_NAME} ) 
   add_custom_command(TARGET create_zip_${TARGET_NAME} POST_BUILD
       COMMAND ${CMAKE_COMMAND} -E tar "cfv" ${FMU_FULL_FILE_NAME} --format=zip ${ARCHIVE_FILES}
       WORKING_DIRECTORY ${FMU_BUILD_DIR}
       COMMENT "Creating ZIP ${FMU_FULL_FILE_NAME}"
   )  
   add_dependencies(create_zip_${TARGET_NAME} copy_framework_sdv_files_${TARGET_NAME}) 

#TODO
   #add_dependencies(${TARGET_NAME} <add_cmake_target_this_depends_on>)
endif ()

