# Copyright 2020 The Dawn & Tint Authors
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
#    list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
#    this list of conditions and the following disclaimer in the documentation
#    and/or other materials provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names of its
#    contributors may be used to endorse or promote products derived from
#    this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

find_package(Python3 REQUIRED)
message(STATUS "Dawn: using python at ${Python3_EXECUTABLE}")

# Check for Jinja2
if (NOT DAWN_JINJA2_DIR)
    message(STATUS "Dawn: Using system jinja2")
    execute_process(
        COMMAND ${Python3_EXECUTABLE} -c "import jinja2"
        RESULT_VARIABLE RET
    )
    if (NOT RET EQUAL 0)
        message(FATAL_ERROR "Dawn: Missing dependencies for code generation, please ensure you have python-jinja2 installed.")
    endif()
else()
    message(STATUS "Dawn: using jinja2 at ${DAWN_JINJA2_DIR}")
    message(STATUS "Dawn: using markupsafe at ${DAWN_MARKUPSAFE_DIR}")
endif()

# Function to invoke a generator_lib.py generator.
#  - SCRIPT is the name of the script to call
#  - ARGS are the extra arguments to pass to the script in addition to the base generator_lib.py arguments
#  - PRINT_NAME is the name to use when outputting status or errors
#  - RESULT_VARIABLE will be modified to contain the list of files generated by this generator
function(DawnGenerator)
    set(oneValueArgs SCRIPT RESULT_VARIABLE PRINT_NAME)
    set(multiValueArgs ARGS)
    cmake_parse_arguments(G "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})

    # Build the set of args common to all invocation of that generator.
    set(BASE_ARGS
        ${Python3_EXECUTABLE}
        ${G_SCRIPT}
        --template-dir
        "${DAWN_TEMPLATE_DIR}"
        --root-dir
        "${Dawn_SOURCE_DIR}"
        --output-dir
        "${DAWN_BUILD_GEN_DIR}"
        ${G_ARGS}
    )
    if (DAWN_JINJA2_DIR)
        list(APPEND BASE_ARGS --jinja2-path ${DAWN_JINJA2_DIR})
    endif()
    if (DAWN_MARKUPSAFE_DIR)
        list(APPEND BASE_ARGS --markupsafe-path ${DAWN_MARKUPSAFE_DIR})
    endif()

    # Call the generator to get the list of its dependencies.
    execute_process(
        COMMAND ${BASE_ARGS} --print-cmake-dependencies
        OUTPUT_VARIABLE DEPENDENCIES
        RESULT_VARIABLE RET
    )
    if (NOT RET EQUAL 0)
        message(FATAL_ERROR "Dawn: Failed to get the dependencies for ${G_PRINT_NAME}. Base args are '${BASE_ARGS}'.")
    endif()

    # Ask CMake to re-run if any of the dependencies changed as it might modify the build graph.
    set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${DEPENDENCIES})

    # Call the generator to get the list of its outputs.
    execute_process(
        COMMAND ${BASE_ARGS} --print-cmake-outputs
        OUTPUT_VARIABLE OUTPUTS
        RESULT_VARIABLE RET
    )
    if (NOT RET EQUAL 0)
        message(FATAL_ERROR "Dawn: Failed to get the outputs for ${G_PRINT_NAME}. Base args are '${BASE_ARGS}'.")
    endif()

    # Add the custom command that calls the generator.
    add_custom_command(
        COMMAND ${BASE_ARGS}
        DEPENDS ${DEPENDENCIES}
        OUTPUT ${OUTPUTS}
        COMMENT "Dawn: Generating files for ${G_PRINT_NAME}."
    )

    # Prior to CMake 3.20 the GENERATED property is local to a directory which means that putting
    # generated headers in INTERFACE properties causes dependent targets to complain that they
    # cannot find the file. (because they don't see it as generated and want to check is is
    # actually on the filesystem).
    # Work around this by creating empty files placeholder generated files so that the build
    # configuration process can success.
    foreach(path ${OUTPUTS})
        if (NOT EXISTS ${path})
            string(FIND "${path}" "/" foundIndex REVERSE)
            string(SUBSTRING "${path}" 0 ${foundIndex} dir)
            file(MAKE_DIRECTORY ${dir})
            file(TOUCH ${path})
            # Also touch the generator script to make a dependency of the generated file dirty,
            # ensuring that it gets generated and not used while it is an empty file.
            file(TOUCH ${G_SCRIPT})
        endif()
    endforeach()

    # Return the list of outputs.
    set(${G_RESULT_VARIABLE} ${OUTPUTS} PARENT_SCOPE)
endfunction()

# Helper function to call dawn_generator.py:
#  - TARGET is the generator target to build
#  - PRINT_NAME and RESULT_VARIABLE are like for DawnGenerator
function(DawnJSONGenerator)
    set(oneValueArgs TARGET RESULT_VARIABLE)
    cmake_parse_arguments(G "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})

    DawnGenerator(
        SCRIPT "${Dawn_SOURCE_DIR}/generator/dawn_json_generator.py"
        ARGS --dawn-json
             "${Dawn_SOURCE_DIR}/src/dawn/dawn.json"
             --wire-json
             "${Dawn_SOURCE_DIR}/src/dawn/dawn_wire.json"
             --targets
             ${G_TARGET}
        RESULT_VARIABLE RET
        ${G_UNPARSED_ARGUMENTS}
    )

    # Forward the result up one more scope
    set(${G_RESULT_VARIABLE} ${RET} PARENT_SCOPE)
endfunction()
