include(CMakeDependentOption)

# version override

set(
        ASY_VERSION_OVERRIDE "" CACHE STRING
        "Overriding asymptote version. If left blank, version is determined from configure.ac."
)

# Perl

set(PERL_INTERPRETER "" CACHE STRING "Perl interpreter. If left empty, will try to determine interpreter automatically")

if(NOT PERL_INTERPRETER)
    message(STATUS "No Perl interpreter specified, attempting to find perl")
    find_program(
            PERL_INTERPRETER_FOUND
            perl
            REQUIRED
    )
    message(STATUS "Found perl at ${PERL_INTERPRETER_FOUND}")
    set(PERL_INTERPRETER ${PERL_INTERPRETER_FOUND} CACHE STRING "" FORCE)
endif()

execute_process(COMMAND ${PERL_INTERPRETER} -e "print \"$]\"" OUTPUT_VARIABLE PERL_VERSION)
message(STATUS "Perl version: ${PERL_VERSION}")

# Python

set(PY3_INTERPRETER "" CACHE STRING "Python 3 interpreter. If left empty, will try to determine Python automatically")

function(verify_py3_interpreter_is_py3 validator_result_var py_interpreter)
    execute_process(
            COMMAND ${py_interpreter} -c "import sys; print(int(sys.version[0])>=3,end='')"
            OUTPUT_VARIABLE PY3_INTERPRETER_VERSION_RESULT)
    if (NOT PY3_INTERPRETER_VERSION_RESULT STREQUAL "True")
        set(${validator_result_var} FALSE PARENT_SCOPE)
    endif()
endfunction()

if(NOT PY3_INTERPRETER)
    message(STATUS "No Python3 interpreter specified, attempting to find python")
    find_program(
            PY3_INTERPRETER_FOUND
            NAMES python3 python
            VALIDATOR verify_py3_interpreter_is_py3
            REQUIRED
    )
    message(STATUS "Found python3 at ${PY3_INTERPRETER_FOUND}")
    set(PY3_INTERPRETER ${PY3_INTERPRETER_FOUND} CACHE STRING "" FORCE)
else()
    set(PY_INTERPRETER_IS_PY3 TRUE)
    set(VARIABLE_RESULT_VAR PY_INTERPRETER_IS_PY3)
    verify_py3_interpreter_is_py3(VARIABLE_RESULT_VAR ${PY3_INTERPRETER})

    if (NOT PY_INTERPRETER_IS_PY3)
        message(FATAL_ERROR "Specified python interpreter cannot be used as python3 interpreter!")
    endif()
endif()

execute_process(COMMAND ${PY3_INTERPRETER} --version OUTPUT_VARIABLE PY3_VERSION)
message(STATUS "Version: ${PY3_VERSION}")

# windows flex + bison
set(
        WIN32_FLEX_BINARY "" CACHE STRING
        "Flex binary for windows. If not specified, downloads from winflexibson. This option is inert on UNIX systems"
)
set(
        WIN32_BISON_BINARY "" CACHE STRING
        "Bison binary for windows. If not specified, downloads from winflexbison. This option is inert on UNIX systems"
)

# feature libraries

option(ENABLE_GC "enable boehm gc support" true)
option(ENABLE_CURL "enable curl support" true)
option(ENABLE_READLINE "libreadline" true)
option(ENABLE_THREADING "enable threading support" true)
option(ENABLE_GSL "Enable GSL support" true)
option(ENABLE_EIGEN3 "Enable eigen3 support" true)
option(ENABLE_FFTW3 "Enable fftw3 support" true)
option(
        ENABLE_VULKAN
        "Enable Vulkan rendering support. When disabled, neither Vulkan, glslang, glfw3,
nor VulkanMemoryAllocator are required, and the resulting asy binary has no Vulkan renderer.
This option is intended primarily for environments where Vulkan/glslang/glfw3 cannot be provided
(e.g. constrained CI sandboxes); production builds should leave this enabled."
        true)

if (CMAKE_BUILD_TYPE IN_LIST cmake_release_build_types)
    set(default_vk_validation_opt false)
else()
    set(default_vk_validation_opt true)
endif()

option(ENABLE_VK_VALIDATION_LAYERS "Whether to enable Vulkan validation layer" ${default_vk_validation_opt})
option(
        ENABLE_RPC_FEATURES
        "Whether to enable XDR/RPC features. Also enables V3D. If compiling on UNIX systems, requires libtirpc to be installed."
        true)

# Additional options

option(DEBUG_GC_ENABLE "Enable debug mode for gc" false)
option(DEBUG_GC_BACKTRACE_ENABLE "Enable backtrace for gc" false)
# CTAN_BUILD is no longer a CMake cache variable; it's a compile definition applied per-target.

option(
        ENABLE_COMPACT_ZERO_BUILD "\
Set COMPACT flag to 0. \
Unless if building for debugging/testing with an explicit need for additional type verification, \
this option should be turned off."
        false)

# additional optimization options

if (CMAKE_BUILD_TYPE IN_LIST cmake_release_build_types)
    set(default_lto true)
else()
    set(default_lto false)
endif()

option(OPTIMIZE_LINK_TIME "Enable link-time optimization. Enabled by default in release build types" ${default_lto})

# testing
option(ENABLE_ASY_CXXTEST "Enable C++-side testing. This option is inert for final asy libraries and binaries" true)
option(
        DOWNLOAD_GTEST_FROM_SRC "Download google test from googletest's github repo. Otherwise use system libraries."
        true)

# msvc-specific
# The only reason this option is here is because msvc compiler (cl.exe) does not partial preprocessing
# (e.g. ignore missing headers and treat them as generated files or depfile generation with missing headers)
# We use MSVC compiler for all C++ compilation/linking
set(GCCCOMPAT_CXX_COMPILER_FOR_MSVC
        "" CACHE STRING
        "gcc-compatible C++ compiler for preprocessing with MSVC toolchain. This option is inert if not using MSVC.
This option is only used for preprocessing, it is not used for compilation."
)

# CUDA + asy cuda reflect
include(CheckLanguage)
check_language(CUDA)

if (CMAKE_CUDA_COMPILER)
    set(CAN_COMPILE_CUDA_REFLECT true)
endif()

cmake_dependent_option(
    ENABLE_CUDA_ASY_REFLECT
    "Enable target for reflect excutable for generating IBL lighting data.
Requires CUDA installed and a CUDA-compatible NVIDIA Graphics card"
    true "CAN_COMPILE_CUDA_REFLECT" false
)

# Language server protocol
option(
    ENABLE_LSP
    "Enable Language Server Protocol support."
    true
)

# documentation
set(WIN32_TEXINDEX "WSL" CACHE STRING
        "Location to texindex for windows, or WSL to use internal WSL wrapper.
Inert for non-windows systems.")

function(determine_asymptote_pdf_gen_possible_win32)
    # windows doesn't have an up-to-date
    # texi2dvi release in multiple years, so
    # we are using MikTeX's texify
    find_program(TEXIFY texify)
    if (NOT TEXIFY)
        message(STATUS "texify not found; will not enable docgen by default")
        set(ENABLE_ASYMPTOTE_PDF_DOCGEN_POSSIBLE false PARENT_SCOPE)
        return()
    endif()

    if (NOT WIN32_TEXINDEX)
        message(STATUS "texindex for windows not given; will not enable docgen by default")
        set(ENABLE_ASYMPTOTE_PDF_DOCGEN_POSSIBLE false PARENT_SCOPE)
        return()
    endif()

    # another issue is that
    if (WIN32_TEXINDEX STREQUAL WSL)
        execute_process(
                COMMAND wsl sh -c "which texindex >/dev/null 2>/dev/null && echo OK"
                OUTPUT_VARIABLE TEXINDEX_RESULT
                OUTPUT_STRIP_TRAILING_WHITESPACE
        )
        if (NOT TEXINDEX_RESULT STREQUAL "OK")
            message(STATUS "Cannot execute texindex on wsl; will not enable docgen by default")
            set(ENABLE_ASYMPTOTE_PDF_DOCGEN_POSSIBLE false PARENT_SCOPE)
            return()
        endif()
    endif()
    message(STATUS "Building of asymptote.pdf is possible; enabling")
    set(ENABLE_ASYMPTOTE_PDF_DOCGEN_POSSIBLE true PARENT_SCOPE)
endfunction()

set(ENABLE_BASE_DOCGEN_POSSIBLE false)
set(ENABLE_ASYMPTOTE_PDF_DOCGEN_POSSIBLE false)

# finding latex and other programs needed
# pdflatex
find_package(LATEX COMPONENTS PDFLATEX)

# pdftex
set(PDFTEX_EXEC "" CACHE STRING "pdftex. If left empty, will try to determine interpreter automatically")
if (NOT PDFTEX)
    message(STATUS "No pdftex specified, attempting to find pdftex")
    find_program(
            PDFTEX_EXEC_FOUND
            pdftex
    )
    if (PDFTEX_EXEC_FOUND)
        message(STATUS "Found pdftex at ${PDFTEX_EXEC_FOUND}")
        set(PDFTEX_EXEC ${PDFTEX_EXEC_FOUND} CACHE STRING "" FORCE)
    endif()
endif()

if (LATEX_PDFLATEX_FOUND AND PDFTEX_EXEC)
    set(ENABLE_BASE_DOCGEN_POSSIBLE true)
    message(STATUS "LaTeX and pdftex found; building basic documentation is possible")
    if (WIN32)
        determine_asymptote_pdf_gen_possible_win32()
    elseif(UNIX)
        find_program(TEXI2DVI texi2dvi)
        if (TEXI2DVI)
            set(ENABLE_ASYMPTOTE_PDF_DOCGEN_POSSIBLE true)
            message("Building of asymptote.pdf is possible and enabled")
        endif()
    endif()
endif()

set(
        EXTERNAL_DOCUMENTATION_DIR "" CACHE STRING
        "If specified, installation will use files from this directory as documentation.
In particular,

- if ENABLE_DOCGEN and ENABLE_ASYMPTOTE_PDF_DOCGEN is enabled and the system has the capability to build
all documentation files, this option is inert.
- if ENABLE_DOCGEN is enabled but ENABLE_ASYMPTOTE_PDF_DOCGEN is disabled or if the system cannot produce asymptote.pdf,
only asymptote.pdf will be copied from this directory.
- if ENABLE_DOCGEN is disabled, every documentation file will be copied from this directory.
"
)

cmake_dependent_option(
    ENABLE_DOCGEN
    "Enable basic document generation. Requires pdflatex"
    true
    "ENABLE_BASE_DOCGEN_POSSIBLE"
    false
)

cmake_dependent_option(
        ENABLE_ASYMPTOTE_PDF_DOCGEN
        "Enable asymptote.pdf document generation. Requires texinfo, and additionally WSL + texindex on windows."
        true
        "ENABLE_ASYMPTOTE_PDF_DOCGEN_POSSIBLE;ENABLE_DOCGEN"
        false
)

# misc files
option(
        ENABLE_MISCFILES_GEN
        "Enable generation of non-essential, non-documentation asymptote files (e.g. asy.list, asy-keywords.el) "
        true
)

# warnings if external docs dir is not given
if (NOT EXTERNAL_DOCUMENTATION_DIR)
    if (NOT ENABLE_DOCGEN)
        message(STATUS "Build is not generating documentation.
If you are planning on generating installation files, please make sure you have access to
documentation files in a directory and specify this directory in EXTERNAL_DOCUMENTATION_DIR cache variable.
")
    elseif(NOT ENABLE_ASYMPTOTE_PDF_DOCGEN)
        message(STATUS "Build is not generating asymptote.pdf.
If you are planning on generating installation files, please make sure you have access to asymptote.pdf
in a directory and specify this directory in EXTERNAL_DOCUMENTATION_DIR cache variable.
")
    endif()

    if (NOT ENABLE_MISCFILES_GEN)
        message(STATUS "Build is not generating non-essential, non-documentation asymptote files.
If you are planning on generating installation files, please make sure you have access to asy-keywords.el
in a directory and specify this directory in EXTERNAL_DOCUMENTATION_DIR cache variable.
")
    endif()
endif()

# windows-specific installation
option(
        ALLOW_PARTIAL_INSTALLATION
        "Allow installation to go through, even if not every component is buildable.
        CMake will produce a warning instead of a fatal error."
        false
)


# asygl

option(
        USE_PREBUILT_WEBGL_LIB
        "Use prebuilt asygl library corresponding to asygl-version (asygl-<version>.js in base/webgl directory).
        If this option is turned off, one will need to manually build gl.js in webgl directory to complete the build
        process."
        true
)
