# Copyright (C) 2010-2023 Duncan Deveaux
#
# This file is part of Hikou no mizu.
#
# Hikou no mizu is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Hikou no mizu is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Hikou no mizu.  If not, see <http://www.gnu.org/licenses/>.

cmake_minimum_required(VERSION 3.10)

set(VERSION_MAJOR 1)
set(VERSION_MINOR 0)
set(VERSION_PATCH 0)

project(hikounomizu VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH})

######################
### Define sources ###
######################
set(PROJECT_SERVER_NAME hikounomizud)

set(HNM_SRCDIR src)
set(HNM_DATASRCDIR datasrc)

set(HNM_DATADIR data)

# descbuild utility: converts an abstract animation description tag
# into a game readable format (datasrc->data build process)
set(HNM_DESCBUILD hnm_descbuild)
set(SRCS_DESCBUILD
    ${HNM_DATASRCDIR}/descbuild.cpp
    ${HNM_SRCDIR}/Configuration/ConfReader.cpp)

set(SRCS
    ${HNM_SRCDIR}/main.cpp

    ${HNM_SRCDIR}/Configuration/Configuration.cpp
    ${HNM_SRCDIR}/Configuration/ConfWriter.cpp
    ${HNM_SRCDIR}/Configuration/ConfReader.cpp

    ${HNM_SRCDIR}/Tools/BitTools.cpp
    ${HNM_SRCDIR}/Tools/ByteTools.cpp
    ${HNM_SRCDIR}/Tools/Filesystem.cpp
    ${HNM_SRCDIR}/Tools/Log.cpp
    ${HNM_SRCDIR}/Tools/Timer.cpp
    ${HNM_SRCDIR}/Tools/Utf8.cpp

    ${HNM_SRCDIR}/Tools/Input/Key.cpp
    ${HNM_SRCDIR}/Tools/Input/KeyboardKey.cpp
    ${HNM_SRCDIR}/Tools/Input/JoyButtonKey.cpp
    ${HNM_SRCDIR}/Tools/Input/JoyHatKey.cpp
    ${HNM_SRCDIR}/Tools/Input/JoyAxisKey.cpp
    ${HNM_SRCDIR}/Tools/Input/InputMonitor.cpp
    ${HNM_SRCDIR}/Tools/Input/Joystick.cpp

    ${HNM_SRCDIR}/Graphics/Window.cpp
    ${HNM_SRCDIR}/Graphics/Camera.cpp
    ${HNM_SRCDIR}/Graphics/Resources/Texture.cpp
    ${HNM_SRCDIR}/Graphics/Resources/Font.cpp
    ${HNM_SRCDIR}/Graphics/Resources/Glyph.cpp
    ${HNM_SRCDIR}/Graphics/Drawable/Drawable.cpp
    ${HNM_SRCDIR}/Graphics/Drawable/Text.cpp
    ${HNM_SRCDIR}/Graphics/Drawable/Polygon.cpp
    ${HNM_SRCDIR}/Graphics/Drawable/Sprite.cpp
    ${HNM_SRCDIR}/Graphics/Drawable/AnimationDrawer.cpp
    ${HNM_SRCDIR}/Graphics/Drawable/ArenaDrawer.cpp
    ${HNM_SRCDIR}/Graphics/Drawable/AttackDrawer.cpp
    ${HNM_SRCDIR}/Graphics/Drawable/PlayerDrawer.cpp
    ${HNM_SRCDIR}/Graphics/Drawable/WeaponEtherDrawer.cpp

    ${HNM_SRCDIR}/Audio/Audio.cpp
    ${HNM_SRCDIR}/Audio/Music.cpp
    ${HNM_SRCDIR}/Audio/Playlist.cpp
    ${HNM_SRCDIR}/Audio/SoundBuffer.cpp
    ${HNM_SRCDIR}/Audio/Sound.cpp

    ${HNM_SRCDIR}/Engines/GameEngine.cpp
    ${HNM_SRCDIR}/Engines/Physics/PhysicsWorld.cpp
    ${HNM_SRCDIR}/Engines/Physics/PhysicsObject.cpp
    ${HNM_SRCDIR}/Engines/Physics/PhysicsRoutines.cpp
    ${HNM_SRCDIR}/Engines/Sound/PlaylistPlayer.cpp
    ${HNM_SRCDIR}/Engines/Sound/AmbientPlayer.cpp
    ${HNM_SRCDIR}/Engines/Sound/SoundEngine.cpp
    ${HNM_SRCDIR}/Engines/Sound/SoundEffectsList.cpp
    ${HNM_SRCDIR}/Engines/Resources/TextureManager.cpp
    ${HNM_SRCDIR}/Engines/Resources/FontManager.cpp
    ${HNM_SRCDIR}/Engines/Resources/SoundBufferManager.cpp
    ${HNM_SRCDIR}/Engines/Resources/JoystickManager.cpp

    ${HNM_SRCDIR}/Screens/MainMenu/MainMenu.cpp
    ${HNM_SRCDIR}/Screens/MainMenu/MainMenuTab.cpp

    ${HNM_SRCDIR}/Screens/Options/Options.cpp
    ${HNM_SRCDIR}/Screens/Options/OptionsTab.cpp
    ${HNM_SRCDIR}/Screens/Options/GeneralOptions.cpp
    ${HNM_SRCDIR}/Screens/Options/ControlsOptions.cpp
    ${HNM_SRCDIR}/Screens/Options/KeyBindTab.cpp
    ${HNM_SRCDIR}/Screens/Options/MultipleKeyBinder.cpp

    ${HNM_SRCDIR}/Screens/CharactersMenu/CharactersMenu.cpp
    ${HNM_SRCDIR}/Screens/CharactersMenu/CharacterChooser.cpp
    ${HNM_SRCDIR}/Screens/CharactersMenu/CharacterSelectionPanel.cpp

    ${HNM_SRCDIR}/Screens/ArenaMenu/ArenaMenu.cpp
    ${HNM_SRCDIR}/Screens/ArenaMenu/ArenaChooser.cpp

    ${HNM_SRCDIR}/Screens/LocalGame/LocalGame.cpp
    ${HNM_SRCDIR}/Screens/LocalGame/LocalFightController.cpp
    ${HNM_SRCDIR}/Screens/LocalGame/PauseTab.cpp
    ${HNM_SRCDIR}/Screens/LocalGame/EndTab.cpp

    ${HNM_SRCDIR}/Screens/NetworkedGame/NetworkedGame.cpp

    ${HNM_SRCDIR}/Network/Host/ClientHost.cpp
    ${HNM_SRCDIR}/Network/Host/Address.cpp
    ${HNM_SRCDIR}/Network/Client/Client.cpp
    ${HNM_SRCDIR}/Network/Client/ClientLobby.cpp
    ${HNM_SRCDIR}/Network/Client/ClientGame.cpp
    ${HNM_SRCDIR}/Network/Client/ClientFightController.cpp
    ${HNM_SRCDIR}/Network/Client/ClientPauseTab.cpp
    ${HNM_SRCDIR}/Network/Message/ClientHandshakeMessage.cpp
    ${HNM_SRCDIR}/Network/Message/ServerHandshakeMessage.cpp
    ${HNM_SRCDIR}/Network/Message/GameStateMessage.cpp
    ${HNM_SRCDIR}/Network/Message/PlayerActionMessage.cpp
    ${HNM_SRCDIR}/Network/Message/ServerEventMessage.cpp
    ${HNM_SRCDIR}/Network/Message/PeerPingMessage.cpp
    ${HNM_SRCDIR}/Network/Serialization/GameMetadata.cpp
    ${HNM_SRCDIR}/Network/Serialization/EtherStatus.cpp
    ${HNM_SRCDIR}/Network/Serialization/InventoryStatus.cpp
    ${HNM_SRCDIR}/Network/Serialization/PhysicsObjectStatus.cpp
    ${HNM_SRCDIR}/Network/Serialization/WeaponStatus.cpp
    ${HNM_SRCDIR}/Network/Serialization/DamageStatus.cpp
    ${HNM_SRCDIR}/Network/Serialization/PlayerStatus.cpp
    ${HNM_SRCDIR}/Network/Serialization/PlayerAction.cpp
    ${HNM_SRCDIR}/Network/Serialization/ServerEvent.cpp
    ${HNM_SRCDIR}/Network/Serialization/MatchmakingStrategy.cpp

    ${HNM_SRCDIR}/Arena/Arena.cpp
    ${HNM_SRCDIR}/Arena/Platform.cpp

    ${HNM_SRCDIR}/Fight/FightRules.cpp
    ${HNM_SRCDIR}/Fight/FightState.cpp
    ${HNM_SRCDIR}/Fight/Referee.cpp
    ${HNM_SRCDIR}/Fight/FightScene.cpp
    ${HNM_SRCDIR}/Fight/ClientFightScene.cpp
    ${HNM_SRCDIR}/Fight/FightCameraHandler.cpp
    ${HNM_SRCDIR}/Fight/DamageDealer.cpp
    ${HNM_SRCDIR}/Fight/VersusController.cpp

    ${HNM_SRCDIR}/Player/Attack.cpp
    ${HNM_SRCDIR}/Player/StateDescription.cpp
    ${HNM_SRCDIR}/Player/Player.cpp
    ${HNM_SRCDIR}/Player/PlayerMoves.cpp
    ${HNM_SRCDIR}/Player/PlayerKeys.cpp
    ${HNM_SRCDIR}/Player/Control/PlayerController.cpp
    ${HNM_SRCDIR}/Player/Control/InputReadingController.cpp
    ${HNM_SRCDIR}/Player/Control/Local/HumanController.cpp
    ${HNM_SRCDIR}/Player/Control/Local/AIController.cpp
    ${HNM_SRCDIR}/Player/Control/Remote/NetClientController.cpp

    ${HNM_SRCDIR}/Animation/Animation.cpp
    ${HNM_SRCDIR}/Animation/CallbackAnimation.cpp

    ${HNM_SRCDIR}/Weapon/WeaponEther.cpp
    ${HNM_SRCDIR}/Weapon/Weapon.cpp
    ${HNM_SRCDIR}/Weapon/WeaponInventory.cpp
    ${HNM_SRCDIR}/Weapon/Shuriken.cpp

    ${HNM_SRCDIR}/GUI/SectionHeader.cpp
    ${HNM_SRCDIR}/GUI/PlaylistNotifier.cpp
    ${HNM_SRCDIR}/GUI/CharacterPreview.cpp
    ${HNM_SRCDIR}/GUI/LobbyCharacter.cpp
    ${HNM_SRCDIR}/GUI/TextInputEnabler.cpp
    ${HNM_SRCDIR}/GUI/ShadowText.cpp
    ${HNM_SRCDIR}/GUI/Fight/PeerInfoLayer.cpp
    ${HNM_SRCDIR}/GUI/Fight/RoundAnnouncer.cpp
    ${HNM_SRCDIR}/GUI/Fight/RoundResultInfo.cpp
    ${HNM_SRCDIR}/GUI/Fight/FightInterface.cpp
    ${HNM_SRCDIR}/GUI/Fight/PlayerInfo.cpp
    ${HNM_SRCDIR}/GUI/Fight/PlayerResults.cpp
    ${HNM_SRCDIR}/GUI/Fight/NameTags.cpp
    ${HNM_SRCDIR}/GUI/Fight/EventLogger.cpp
    ${HNM_SRCDIR}/GUI/Fight/FpsCounter.cpp
    ${HNM_SRCDIR}/GUI/Widget/Tab.cpp
    ${HNM_SRCDIR}/GUI/Widget/Button.cpp
    ${HNM_SRCDIR}/GUI/Widget/TextButton.cpp
    ${HNM_SRCDIR}/GUI/Widget/Chooser.cpp
    ${HNM_SRCDIR}/GUI/Widget/ContinuousChooser.cpp
    ${HNM_SRCDIR}/GUI/Widget/Checkbox.cpp
    ${HNM_SRCDIR}/GUI/Widget/Dialog.cpp
    ${HNM_SRCDIR}/GUI/Widget/KeyBinder.cpp
    ${HNM_SRCDIR}/GUI/Widget/TextInput.cpp)

set(SRCS_SERVER
    ${HNM_SRCDIR}/server.cpp

    ${HNM_SRCDIR}/Configuration/ServerConfiguration.cpp
    ${HNM_SRCDIR}/Configuration/ConfWriter.cpp
    ${HNM_SRCDIR}/Configuration/ConfReader.cpp

    ${HNM_SRCDIR}/Tools/ArgumentParser.cpp
    ${HNM_SRCDIR}/Tools/BitTools.cpp
    ${HNM_SRCDIR}/Tools/ByteTools.cpp
    ${HNM_SRCDIR}/Tools/Filesystem.cpp
    ${HNM_SRCDIR}/Tools/Log.cpp
    ${HNM_SRCDIR}/Tools/Timer.cpp
    ${HNM_SRCDIR}/Tools/Utf8.cpp

    ${HNM_SRCDIR}/Network/Host/ServerHost.cpp
    ${HNM_SRCDIR}/Network/Host/Address.cpp
    ${HNM_SRCDIR}/Network/Server/Server.cpp
    ${HNM_SRCDIR}/Network/Server/PeerList.cpp
    ${HNM_SRCDIR}/Network/Server/PeerActivity.cpp
    ${HNM_SRCDIR}/Network/Server/ServerFightController.cpp
    ${HNM_SRCDIR}/Network/Server/ArenaRotation.cpp
    ${HNM_SRCDIR}/Network/Server/Matchmaking.cpp
    ${HNM_SRCDIR}/Network/Message/ServerHandshakeMessage.cpp
    ${HNM_SRCDIR}/Network/Message/ClientHandshakeMessage.cpp
    ${HNM_SRCDIR}/Network/Message/GameStateMessage.cpp
    ${HNM_SRCDIR}/Network/Message/PlayerActionMessage.cpp
    ${HNM_SRCDIR}/Network/Message/ServerEventMessage.cpp
    ${HNM_SRCDIR}/Network/Message/PeerPingMessage.cpp
    ${HNM_SRCDIR}/Network/Serialization/GameMetadata.cpp
    ${HNM_SRCDIR}/Network/Serialization/EtherStatus.cpp
    ${HNM_SRCDIR}/Network/Serialization/InventoryStatus.cpp
    ${HNM_SRCDIR}/Network/Serialization/PhysicsObjectStatus.cpp
    ${HNM_SRCDIR}/Network/Serialization/WeaponStatus.cpp
    ${HNM_SRCDIR}/Network/Serialization/DamageStatus.cpp
    ${HNM_SRCDIR}/Network/Serialization/PlayerStatus.cpp
    ${HNM_SRCDIR}/Network/Serialization/PlayerAction.cpp
    ${HNM_SRCDIR}/Network/Serialization/ServerEvent.cpp
    ${HNM_SRCDIR}/Network/Serialization/MatchmakingStrategy.cpp

    ${HNM_SRCDIR}/Engines/Physics/PhysicsWorld.cpp
    ${HNM_SRCDIR}/Engines/Physics/PhysicsObject.cpp
    ${HNM_SRCDIR}/Engines/Physics/PhysicsRoutines.cpp

    ${HNM_SRCDIR}/Arena/Arena.cpp
    ${HNM_SRCDIR}/Arena/Platform.cpp

    ${HNM_SRCDIR}/Fight/FightRules.cpp
    ${HNM_SRCDIR}/Fight/FightState.cpp
    ${HNM_SRCDIR}/Fight/Referee.cpp
    ${HNM_SRCDIR}/Fight/FightScene.cpp
    ${HNM_SRCDIR}/Fight/ServerFightScene.cpp
    ${HNM_SRCDIR}/Fight/DamageDealer.cpp
    ${HNM_SRCDIR}/Fight/VersusController.cpp

    ${HNM_SRCDIR}/Player/Attack.cpp
    ${HNM_SRCDIR}/Player/StateDescription.cpp
    ${HNM_SRCDIR}/Player/Player.cpp
    ${HNM_SRCDIR}/Player/PlayerMoves.cpp
    ${HNM_SRCDIR}/Player/Control/PlayerController.cpp
    ${HNM_SRCDIR}/Player/Control/Remote/NetServerController.cpp

    ${HNM_SRCDIR}/Animation/Animation.cpp
    ${HNM_SRCDIR}/Animation/CallbackAnimation.cpp

    ${HNM_SRCDIR}/Weapon/WeaponEther.cpp
    ${HNM_SRCDIR}/Weapon/Weapon.cpp
    ${HNM_SRCDIR}/Weapon/WeaponInventory.cpp
    ${HNM_SRCDIR}/Weapon/Shuriken.cpp)

if (HNMSERVER_DRAW)

    # Build the server with drawing ability for development
    set(SRCS_SERVER ${SRCS_SERVER}
                    ${HNM_SRCDIR}/Engines/Resources/TextureManager.cpp
                    ${HNM_SRCDIR}/Graphics/Window.cpp
                    ${HNM_SRCDIR}/Graphics/Camera.cpp
                    ${HNM_SRCDIR}/Graphics/Resources/Texture.cpp
                    ${HNM_SRCDIR}/Graphics/Drawable/Drawable.cpp
                    ${HNM_SRCDIR}/Graphics/Drawable/Polygon.cpp
                    ${HNM_SRCDIR}/Graphics/Drawable/Sprite.cpp
                    ${HNM_SRCDIR}/Graphics/Drawable/AnimationDrawer.cpp
                    ${HNM_SRCDIR}/Graphics/Drawable/ArenaDrawer.cpp
                    ${HNM_SRCDIR}/Graphics/Drawable/AttackDrawer.cpp
                    ${HNM_SRCDIR}/Graphics/Drawable/PlayerDrawer.cpp
                    ${HNM_SRCDIR}/Graphics/Drawable/WeaponEtherDrawer.cpp)

    message(STATUS ${PROJECT_SERVER_NAME} " will be built with drawing support")

endif ()


############################################
### Setup build options and dependencies ###
############################################

# Define CXX standard and targets
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

# Look for dependencies
find_package(pugixml REQUIRED)

if (NOT HNM_NOSERVER)

    find_package(PkgConfig REQUIRED)
    pkg_check_modules(ENET REQUIRED IMPORTED_TARGET libenet)

endif ()

if (NOT HNM_NOCLIENT)

    if (HNM_NOSERVER) #pkg-config and enet are not included yet
        find_package(PkgConfig REQUIRED)
        pkg_check_modules(ENET REQUIRED IMPORTED_TARGET libenet)
    endif ()

    set(OpenGL_GL_PREFERENCE GLVND)
    find_package(OpenGL REQUIRED)
    find_package(Freetype REQUIRED)
    pkg_check_modules(SDL2 REQUIRED IMPORTED_TARGET sdl2)
    pkg_check_modules(SDL2IMG REQUIRED IMPORTED_TARGET SDL2_image>=2.0.0)
    pkg_check_modules(OPENAL REQUIRED IMPORTED_TARGET openal)
    pkg_check_modules(OGG REQUIRED IMPORTED_TARGET ogg)
    pkg_check_modules(VORBIS REQUIRED IMPORTED_TARGET vorbis)
    pkg_check_modules(VORBISFILE REQUIRED IMPORTED_TARGET vorbisfile)

elseif (HNMSERVER_DRAW)

    set(OpenGL_GL_PREFERENCE GLVND)
    find_package(OpenGL REQUIRED)
    pkg_check_modules(SDL2 REQUIRED IMPORTED_TARGET sdl2)
    pkg_check_modules(SDL2IMG REQUIRED IMPORTED_TARGET SDL2_image>=2.0.0)

endif ()

# On Haiku, link libbe.so and libroot.so
# for pthread handling and Storage Kit functions
if (HAIKU)
    find_library(LIBBE be)
    find_library(LIBROOT root)
    if (NOT LIBBE OR NOT LIBROOT)
        message(FATAL_ERROR "libbe or libroot not found")
    endif ()

    set(OS_LIBS ${LIBBE} ${LIBROOT})
else ()
    set(THREADS_PREFER_PTHREAD_FLAG ON)
    find_package(Threads REQUIRED)

    set(THREAD_LIBS Threads::Threads)
endif ()


######################
### Define targets ###
######################

# hikounomizu
if (NOT HNM_NOCLIENT)

    add_executable(${PROJECT_NAME} ${SRCS})

    target_include_directories(${PROJECT_NAME} PUBLIC
        ${CMAKE_SOURCE_DIR}/${HNM_SRCDIR} # Source directory
        ${CMAKE_BINARY_DIR}/build_src)    # Generated source directory

    target_link_libraries(${PROJECT_NAME}
        OpenGL::GL Freetype::Freetype
        PkgConfig::SDL2 PkgConfig::SDL2IMG
        PkgConfig::OPENAL PkgConfig::OGG
        PkgConfig::VORBIS PkgConfig::VORBISFILE
        PkgConfig::ENET pugixml::pugixml ${OS_LIBS} ${THREAD_LIBS})

    target_compile_options(${PROJECT_NAME} PRIVATE
        -Wall -Wextra -Wconversion -Wsign-conversion
        -Wnon-virtual-dtor -Wfloat-equal -pedantic)

    if (WIN32) # Disable GDI which has conflicting macros
        target_compile_definitions(${PROJECT_NAME} PRIVATE NOGDI)
    endif ()

endif ()

# hikounomizud (server)
if (NOT HNM_NOSERVER)

    add_executable(${PROJECT_SERVER_NAME} ${SRCS_SERVER})

    target_include_directories(${PROJECT_SERVER_NAME} PUBLIC
        ${CMAKE_SOURCE_DIR}/${HNM_SRCDIR} # Source directory
        ${CMAKE_BINARY_DIR}/build_src)    # Generated source directory

    target_compile_definitions(${PROJECT_SERVER_NAME} PRIVATE
        CONF_DISABLE_PLAYERKEYS)

    if (HNMSERVER_DRAW)
        target_compile_definitions(${PROJECT_SERVER_NAME} PRIVATE HNMSERVER_DRAW)
        target_link_libraries(${PROJECT_SERVER_NAME}
            PkgConfig::ENET pugixml::pugixml
            OpenGL::GL PkgConfig::SDL2 PkgConfig::SDL2IMG ${OS_LIBS})
    else ()
        target_link_libraries(${PROJECT_SERVER_NAME}
            PkgConfig::ENET pugixml::pugixml ${OS_LIBS})
    endif()

    target_compile_options(${PROJECT_SERVER_NAME} PRIVATE
        -Wall -Wextra -Wconversion -Wsign-conversion
        -Wnon-virtual-dtor -Wfloat-equal -pedantic)

endif ()

# hnm_descbuild (tool for data description builder)
add_executable(${HNM_DESCBUILD} ${SRCS_DESCBUILD})
set_target_properties(${HNM_DESCBUILD} PROPERTIES EXCLUDE_FROM_ALL TRUE)

target_include_directories(${HNM_DESCBUILD} PUBLIC
                            ${CMAKE_SOURCE_DIR}/${HNM_DATASRCDIR}
                            ${CMAKE_SOURCE_DIR}/${HNM_SRCDIR})

target_link_libraries(${HNM_DESCBUILD} pugixml::pugixml)

target_compile_options(${HNM_DESCBUILD} PRIVATE
    -Wall -Wextra -Wconversion -Wsign-conversion
    -Wnon-virtual-dtor -Wfloat-equal -pedantic)

target_compile_definitions(${HNM_DESCBUILD} PRIVATE
    CONF_DISABLE_PLAYERKEYS CONF_DISABLE_LOGS)

# Data build custom targets
set(HNM_DATABUILD_BINARY ${CMAKE_SOURCE_DIR}/${HNM_DATASRCDIR}/databuild.sh)
set(HNM_DESCBUILD_BINARY ${CMAKE_BINARY_DIR}/${HNM_DESCBUILD})

add_custom_target(data
    COMMAND ${CMAKE_COMMAND} -E echo "Building Hikou no mizu data..."
    COMMAND ${HNM_DATABUILD_BINARY} --descbuild=${HNM_DESCBUILD_BINARY}
                                    --datasrc=${HNM_DATASRCDIR}
                                    --output=${HNM_DATADIR}
    DEPENDS ${HNM_DESCBUILD} # descbuild is required to build datasrc
    WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})

add_custom_target(cfg
    COMMAND ${CMAKE_COMMAND} -E echo "Building Hikou no mizu configuration..."
    COMMAND ${HNM_DATABUILD_BINARY} --descbuild=${HNM_DESCBUILD_BINARY}
                                    --datasrc=${HNM_DATASRCDIR}
                                    --output=${HNM_DATADIR} -c
    DEPENDS ${HNM_DESCBUILD} # descbuild is required to build datasrc
    WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})


############################
### Pass on build values ###
############################
include(GNUInstallDirs)

if (HNM_STANDALONE) #Standalone: relative path to data/
    set(BUILDVALUES_DATAPATH ${HNM_DATADIR})
elseif (HNM_NOINSTALL) #Development build: absolute path to data/
    set(BUILDVALUES_DATAPATH ${CMAKE_SOURCE_DIR}/${HNM_DATADIR})
else ()
    set(BUILDVALUES_DATAPATH ${CMAKE_INSTALL_FULL_DATADIR}/${PROJECT_NAME})
endif()

configure_file(${HNM_SRCDIR}/Tools/BuildValues.hpp.in
               ${CMAKE_BINARY_DIR}/build_src/Tools/BuildValues.hpp @ONLY)


####################
### Installation ###
####################
if (HNM_STANDALONE) # Standalone build requested (relative data path)

    if (NOT HNM_NOCLIENT)
        install(TARGETS ${PROJECT_NAME}
            RUNTIME DESTINATION ${CMAKE_SOURCE_DIR})
    endif()

    if (NOT HNM_NOSERVER)
        install(TARGETS ${PROJECT_SERVER_NAME}
            RUNTIME DESTINATION ${CMAKE_SOURCE_DIR})
    endif()

    message(STATUS "STANDALONE BUILD - Binary path: " ${CMAKE_SOURCE_DIR})

elseif (HNM_NOINSTALL) # No installation (absolute data path, for development)

    message(STATUS "NOINSTALL BUILD - Do not move data path: "
        ${CMAKE_SOURCE_DIR}/${HNM_DATADIR})

else () # Regular build to a system location

    if (NOT HNM_NOCLIENT)
        install(TARGETS ${PROJECT_NAME}
            RUNTIME DESTINATION ${CMAKE_INSTALL_FULL_BINDIR})
    endif ()

    if (NOT HNM_NOSERVER)
        install(TARGETS ${PROJECT_SERVER_NAME}
            RUNTIME DESTINATION ${CMAKE_INSTALL_FULL_BINDIR})
    endif ()

    # Install data
    install(DIRECTORY ${HNM_DATADIR}/ DESTINATION ${BUILDVALUES_DATAPATH})

    message(STATUS "Binary installation path: " ${CMAKE_INSTALL_FULL_BINDIR})
    message(STATUS "Data path: " ${BUILDVALUES_DATAPATH})

endif ()
