cmake_minimum_required(VERSION 3.21)
project(izanagi C)
set(CMAKE_C_STANDARD 11)

#
# Set platform
#
if (WIN32)
  # TODO set arch on target instead of generator
  set(IZ_PLATFORM WINDOWS)
  set(IZ_CRYPTO_LIBRARIES libcrypto libssl)
  set(IZ_GETOPT_DEPENDENCIES dependencies/getopt-for-windows/getopt.h
          dependencies/getopt-for-windows/getopt.c)
  add_definitions(
    -DIZ_WINDOWS
  )
  if (CMAKE_SIZEOF_VOID_P EQUAL 8)
    set(IZ_PROJECT_ARCH x64)
    add_definitions(
      -DIZ_WIN64
    )
  else ()
    set(IZ_PROJECT_ARCH x86)
    add_definitions(
      -DIZ_WIN32
    )
  endif ()
elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
  set(IZ_PLATFORM MACOS)
  set(IZ_CRYPTO_LIBRARIES crypto ssl)
  add_definitions(
    -DIZ_MACOS
  )
else()
  set(IZ_PLATFORM UNIX)
  set(IZ_CRYPTO_LIBRARIES crypto ssl)
  add_definitions(
    -DIZ_UNIX
  )
endif ()

#
# Add configurations
#
add_definitions(
  -DIZ_APP_NAME="Izanagi"
  -DIZ_APP_DESCRIPTION="Run and gun game"
  -DIZ_APP_SERVER_DESCRIPTION="Dedicated server"
  -DIZ_PLAYERS=1
  #-DIZ_LOG_DATE_FUNCTION=IZ_TimerElapsed
  -DIZ_LOG_DATE_FUNCTION=IZ_TimerNow
  -DIZ_CONFIG_GAME_PATH="config-game.ini"
  -DIZ_CONFIG_SERVER_PATH="config-server.ini"
)

if (${CMAKE_BUILD_TYPE} STREQUAL "Debug")
  add_definitions(-DIZ_DEBUG)
endif()

#
# Specify directories
#
include_directories(
  "${PROJECT_SOURCE_DIR}/dependencies/SDL2/include"
  "${PROJECT_SOURCE_DIR}/dependencies/SDL2_image"
  "${PROJECT_SOURCE_DIR}/dependencies/SDL2_image/include"
  "${PROJECT_SOURCE_DIR}/dependencies/SDL2_ttf/include"
  "${PROJECT_SOURCE_DIR}/dependencies/minIni/dev"
  "${PROJECT_SOURCE_DIR}/dependencies/bdd-for-c"
  "${PROJECT_SOURCE_DIR}/dependencies/bdd-for-c-mocks"
  "${PROJECT_SOURCE_DIR}/dependencies/portmidi/pm_common"
  "${PROJECT_SOURCE_DIR}/dependencies/spine-runtimes/spine-c/spine-c/include"
  "${PROJECT_SOURCE_DIR}/dependencies/getopt-for-windows"
  "${PROJECT_SOURCE_DIR}/dependencies/libwebsockets/build/include"
  "${PROJECT_SOURCE_DIR}/dependencies/openssl/${IZ_PROJECT_ARCH}/include"
  "${PROJECT_SOURCE_DIR}/dependencies/sqlite"
)

if (IZ_PLATFORM STREQUAL "WINDOWS")
  link_directories(
    "${PROJECT_SOURCE_DIR}/dependencies/SDL2/lib/${IZ_PROJECT_ARCH}"
    "${PROJECT_SOURCE_DIR}/dependencies/SDL2_image/lib/${IZ_PROJECT_ARCH}"
    "${PROJECT_SOURCE_DIR}/dependencies/SDL2_ttf/lib/${IZ_PROJECT_ARCH}"
    "${PROJECT_SOURCE_DIR}/dependencies/portmidi/Release"
    "${PROJECT_SOURCE_DIR}/dependencies/libwebsockets/build/lib/Release"
    "${PROJECT_SOURCE_DIR}/dependencies/openssl/${IZ_PROJECT_ARCH}/lib"
  )
  if (NOT ${CMAKE_BUILD_TYPE} STREQUAL "Debug")
    set(IZ_EXECUTABLE_TYPE WIN32)
  endif()
elseif(IZ_PLATFORM STREQUAL "MACOS")
  include_directories(
    /usr/local/include
    /usr/local/include/SDL2
    /usr/local/include/openssl
  )

  link_directories(
    /usr/local/lib
  )
elseif(IZ_PLATFORM STREQUAL "UNIX")
  include_directories(
    /usr/local/include
    /usr/local/include/SDL2
    /usr/local/include/openssl
  )

  link_directories(
    /usr/local/lib
  )
endif()

#
# Define executables
#
add_executable(
  game
    ${IZ_EXECUTABLE_TYPE}
    dependencies/minIni/dev/minIni.h
    dependencies/minIni/dev/minIni.c
    ${IZ_GETOPT_DEPENDENCIES}
    src/packages/game/output/video/IZ_video.h
    src/packages/game/output/video/IZ_video.c
    src/packages/common/IZ_common.h
    src/packages/game/input/IZ_action.h
    src/packages/game/IZ_app.h
    src/packages/game/IZ_app.c
    src/packages/game/main.c
    src/packages/game/input/IZ_joystick.c
    src/packages/game/input/IZ_joystick.h
    src/packages/game/input/IZ_keyboard.c
    src/packages/game/input/IZ_keyboard.h
    src/packages/config/IZ_config.c
    src/packages/config/IZ_config.h
    src/packages/game/geometry/IZ_vector2d.c
    src/packages/game/geometry/IZ_vector2d.h
    src/packages/game/geometry/IZ_rect.c
    src/packages/game/geometry/IZ_rect.h
    src/packages/game/core/IZ_object.c
    src/packages/game/core/IZ_object.h
    src/packages/game/core/IZ_creature.c
    src/packages/game/core/IZ_creature.h
    src/packages/game/core/IZ_entity.c
    src/packages/game/core/IZ_entity.h
    src/packages/game/memory/IZ_pool.c
    src/packages/game/memory/IZ_pool.h
    src/packages/game/input/IZ_input.c
    src/packages/game/input/IZ_input.h
    src/packages/game/input/IZ_midi.c
    src/packages/game/input/IZ_midi.h
    src/packages/game/data/IZ_list.c
    src/packages/game/data/IZ_list.h
    src/packages/net/svc/IZ_wsclient.c
    src/packages/net/svc/IZ_wsclient.h
    src/packages/log/IZ_intercept.c
    src/packages/log/IZ_intercept.h
    src/packages/midi/IZ_midi.c
    src/packages/midi/IZ_midi.h
    src/packages/net/core/IZ_websocket.h
    src/packages/net/core/IZ_websocket.c
    src/packages/net/IZ_net_client.c
    src/packages/net/IZ_net_client.h
    src/packages/game/IZ_app_net.c
    src/packages/game/IZ_app_net.h
    src/packages/game/IZ_app_video.c
    src/packages/game/IZ_app_video.h
    src/packages/game/IZ_subsystem.h
    src/packages/game/IZ_app_input.c
    src/packages/game/IZ_app_input.h
    src/packages/game/IZ_app_config.c
    src/packages/game/IZ_app_config.h
    src/packages/game/asset/IZ_asset.c
    src/packages/game/asset/IZ_asset.h
    src/packages/stdinc/IZ_string.c
    src/packages/stdinc/IZ_string.h
    src/packages/io/IZ_io.c
    src/packages/io/IZ_io.h
    src/packages/log/IZ_log.c
    src/packages/log/IZ_log.h
    src/packages/timer/IZ_timer.c
    src/packages/timer/IZ_timer.h
        src/packages/compat/IZ_compat.h
    src/packages/stdinc/IZ_stdlib.c
    src/packages/stdinc/IZ_stdlib.h
)

target_link_libraries(
  game
    SDL2main
    SDL2
    SDL2_image
    SDL2_ttf
    portmidi
    ${IZ_CRYPTO_LIBRARIES}
    websockets
)

add_executable(
  game-test-geometry
    dependencies/bdd-for-c/bdd-for-c.h
    dependencies/bdd-for-c-mocks/bdd-for-c-mocks.h

    src/packages/game/geometry/IZ_rect.h
    src/packages/game/geometry/IZ_rect.c
    src/packages/game/geometry/IZ_vector2d.h
    src/packages/game/geometry/IZ_vector2d.c
    src/packages/game/geometry/geometry.test.c
)

add_executable(
  game-test-input
    dependencies/bdd-for-c/bdd-for-c.h
    dependencies/bdd-for-c-mocks/bdd-for-c-mocks.h

    __mocks__/dependencies/minIni/minIni.mock.h
    __mocks__/dependencies/SDL2/SDL_keyboard.mock.h
    __mocks__/dependencies/SDL2/SDL_events.mock.h
    __mocks__/dependencies/SDL2/SDL_joystick.mock.h
    __mocks__/dependencies/SDL2/SDL_stdinc.mock.h
    __mocks__/dependencies/portmidi/portmidi.mock.h

    src/packages/config/IZ_config.h

    src/packages/game/input/IZ_keyboard.h
    src/packages/game/input/IZ_keyboard.c

    src/packages/game/input/IZ_joystick.h
    src/packages/game/input/IZ_joystick.c

    src/packages/game/input/IZ_midi.h
    src/packages/game/input/IZ_midi.c

    src/packages/midi/IZ_midi.c
    src/packages/midi/IZ_midi.h

    src/packages/stdinc/IZ_string.h
    __mocks__/src/packages/stdinc/IZ_string.mock.h

    src/packages/stdinc/IZ_stdlib.h
    __mocks__/src/packages/stdinc/IZ_stdlib.mock.h

    src/packages/game/input/input.test.c
        __mocks__/src/packages/config/IZ_config.mock.h)

target_link_libraries(
  game-test-input
    SDL2main
    SDL2
)

add_executable(
  game-test-output
    dependencies/bdd-for-c/bdd-for-c.h
    dependencies/bdd-for-c-mocks/bdd-for-c-mocks.h

    __mocks__/dependencies/minIni/minIni.mock.h
    __mocks__/dependencies/SDL2/SDL_stdinc.mock.h
    __mocks__/dependencies/SDL2/SDL_render.mock.h

    src/packages/config/IZ_config.h
    src/packages/game/output/video/IZ_video.h
    src/packages/game/output/video/IZ_video.c
    src/packages/game/output/output.test.c
)

add_executable(
  game-test-memory
    dependencies/bdd-for-c/bdd-for-c.h
    dependencies/bdd-for-c-mocks/bdd-for-c-mocks.h

    src/packages/timer/IZ_timer.h
    src/packages/timer/IZ_timer.c

    src/packages/stdinc/IZ_stdlib.h
    __mocks__/src/packages/stdinc/IZ_stdlib.mock.h

    src/packages/stdinc/IZ_string.h
    __mocks__/src/packages/stdinc/IZ_string.mock.h

    src/packages/log/IZ_log.h
    __mocks__/src/packages/log/IZ_log.mock.h

    src/packages/game/data/IZ_list.c
    src/packages/game/data/IZ_list.h
    src/packages/game/memory/IZ_pool.h
    src/packages/game/memory/IZ_pool.c
    src/packages/game/memory/memory.test.c
)

target_link_libraries(
  game-test-memory
    SDL2main
    SDL2
)

add_executable(
  game-test-data
    dependencies/bdd-for-c/bdd-for-c.h
    dependencies/bdd-for-c-mocks/bdd-for-c-mocks.h

    src/packages/stdinc/IZ_stdlib.h
    __mocks__/src/packages/stdinc/IZ_stdlib.mock.h

    src/packages/game/data/IZ_list.h
    src/packages/game/data/IZ_list.c
    src/packages/game/data/data.test.c
)

target_link_libraries(
  game-test-data
    SDL2main
    SDL2
)

add_executable(
  server
    dependencies/sqlite/sqlite3.h
    dependencies/sqlite/sqlite3.c
    dependencies/minIni/dev/minIni.h
    dependencies/minIni/dev/minIni.c
    src/packages/log/IZ_intercept.h
    src/packages/log/IZ_intercept.c
    src/packages/server/main.c
    src/packages/server/IZ_app.c
    src/packages/server/IZ_app.h
    src/packages/server/IZ_app_config.h
    src/packages/server/IZ_app_config.c
    src/packages/net/svc/IZ_wsserver.c
    src/packages/net/svc/IZ_wsserver.h
    src/packages/net/core/IZ_websocket.h
    src/packages/net/core/IZ_websocket.c
    src/packages/config/IZ_config.h
    src/packages/config/IZ_config.c
    src/packages/net/IZ_net_server.c
    src/packages/net/IZ_net_server.h
    src/packages/server/db/IZ_repo.c
    src/packages/server/db/IZ_repo.h
    src/packages/server/IZ_subsystem.h
    src/packages/stdinc/IZ_string.c
    src/packages/stdinc/IZ_string.h
    src/packages/io/IZ_io.c
    src/packages/io/IZ_io.h
    src/packages/log/IZ_log.c
    src/packages/log/IZ_log.h
    src/packages/timer/IZ_timer.c
    src/packages/timer/IZ_timer.h
)

target_link_libraries(
  server
    SDL2main
    SDL2
    ${IZ_CRYPTO_LIBRARIES}
    websockets
)

add_executable(
  asset-inv
    dependencies/minIni/dev/minIni.h
    dependencies/minIni/dev/minIni.c
    src/packages/common/IZ_common.h
    src/packages/asset-inv/main.c
)

#
# Add DLLs and required assets to the build directory
#
if (IZ_PLATFORM STREQUAL "WINDOWS")
  add_custom_command(TARGET game POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy_if_different
    "${PROJECT_SOURCE_DIR}/dependencies/SDL2/lib/${IZ_PROJECT_ARCH}/SDL2.dll"
    $<TARGET_FILE_DIR:game>)

  add_custom_command(TARGET game POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy_if_different
    "${PROJECT_SOURCE_DIR}/dependencies/SDL2_image/lib/${IZ_PROJECT_ARCH}/SDL2_image.dll"
    $<TARGET_FILE_DIR:game>)

  add_custom_command(TARGET game POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy_if_different
    "${PROJECT_SOURCE_DIR}/dependencies/SDL2_ttf/lib/${IZ_PROJECT_ARCH}/SDL2_ttf.dll"
    $<TARGET_FILE_DIR:game>)

  add_custom_command(TARGET game POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy_if_different
    "${PROJECT_SOURCE_DIR}/dependencies/portmidi/Release/portmidi.dll"
    $<TARGET_FILE_DIR:game>)

  add_custom_command(TARGET game POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy_if_different
    "${PROJECT_SOURCE_DIR}/dependencies/libwebsockets/build/bin/Release/websockets.dll"
    $<TARGET_FILE_DIR:game>)

  add_custom_command(TARGET game POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy_if_different
    "${PROJECT_SOURCE_DIR}/dependencies/openssl/${IZ_PROJECT_ARCH}/bin/libssl-1_1-x64.dll"
    $<TARGET_FILE_DIR:game>)

  add_custom_command(TARGET game POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy_if_different
    "${PROJECT_SOURCE_DIR}/dependencies/openssl/${IZ_PROJECT_ARCH}/bin/libcrypto-1_1-x64.dll"
    $<TARGET_FILE_DIR:game>)

  add_custom_command(TARGET server POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy_if_different
    "${PROJECT_SOURCE_DIR}/dependencies/SDL2/lib/${IZ_PROJECT_ARCH}/SDL2.dll"
    $<TARGET_FILE_DIR:server>)

  add_custom_command(TARGET server POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy_if_different
    "${PROJECT_SOURCE_DIR}/dependencies/libwebsockets/build/bin/Release/websockets.dll"
    $<TARGET_FILE_DIR:server>)

  add_custom_command(TARGET server POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy_if_different
    "${PROJECT_SOURCE_DIR}/dependencies/openssl/${IZ_PROJECT_ARCH}/bin/libssl-1_1-x64.dll"
    $<TARGET_FILE_DIR:server>)

  add_custom_command(TARGET server POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy_if_different
    "${PROJECT_SOURCE_DIR}/dependencies/openssl/${IZ_PROJECT_ARCH}/bin/libcrypto-1_1-x64.dll"
    $<TARGET_FILE_DIR:server>)
endif ()

add_custom_command(TARGET game POST_BUILD
  COMMAND ${CMAKE_COMMAND} -E copy_directory
  "${PROJECT_SOURCE_DIR}/assets"
  $<TARGET_FILE_DIR:game>/assets)

add_custom_command(TARGET asset-inv POST_BUILD
  COMMAND ${CMAKE_COMMAND} -E copy_directory
  "${PROJECT_SOURCE_DIR}/assets"
  $<TARGET_FILE_DIR:game>/assets)
