#[=======================================================================[.rst:
Papyrus
-------

Compile Papyrus scripts

Usage:

.. code-block:: cmake

  add_papyrus(<target> GAME <game_path>
              IMPORTS <import> ...
              SOURCES <source> ...
              [OPTIMIZE] [ANONYMIZE])

Using this command will populate the variable ``<target>_OUTPUT`` with the
files that will be generated by the Papyrus compiler.

Example:

.. code-block:: cmake

  add_papyrus("Papyrus"
              GAME $ENV{Skyrim64Path}
              IMPORTS $ENV{SKSE64Path}/Scripts/Source
                      ${CMAKE_CURRENT_SOURCE_DIR}/scripts
              SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/scripts/MOD_Script1.psc
                      ${CMAKE_CURRENT_SOURCE_DIR}/scripts/MOD_Script2.psc
              OPTIMIZE ANONYMIZE)
#]=======================================================================]

macro(find_pexanon)
	find_program(PEXANON_COMMAND "AFKPexAnon" PATHS "tools/AFKPexAnon")

	if(NOT PEXANON_COMMAND)
		set(PEXANON_DOWNLOAD "${CMAKE_CURRENT_BINARY_DIR}/download/AFKPexAnon-1.1.0-x64.7z")

		file(DOWNLOAD
			"https://github.com/namralkeeg/AFKPexAnon/releases/download/v1.1.0/AFKPexAnon-1.1.0-x64.7z"
			"${PEXANON_DOWNLOAD}"
			EXPECTED_HASH MD5=79d646d42bd4d5a1a4cfc63ef00d004a
			STATUS PEXANON_STATUS
		)

		list(GET PEXANON_STATUS 0 PEXANON_ERROR_CODE)
		if(PEXANON_ERROR_CODE)
			list(GET PEXANON_STATUS 1 PEXANON_ERROR_MESSAGE)
			message(FATAL_ERROR "${PEXANON_ERROR_MESSAGE}")
		endif()

		file(ARCHIVE_EXTRACT
			INPUT "${PEXANON_DOWNLOAD}"
			DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/tools/AFKPexAnon"
		)

		set(PEXANON_COMMAND "${CMAKE_CURRENT_BINARY_DIR}/tools/AFKPexAnon/AFKPexAnon.exe")
	endif()
endmacro()

function(add_papyrus PAPYRUS_TARGET)
	set(options OPTIMIZE ANONYMIZE)
	set(oneValueArgs GAME)
	set(multiValueArgs IMPORTS SOURCES)
	cmake_parse_arguments(PAPYRUS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})

	if(EXISTS "${PAPYRUS_GAME}/SkyrimSE.exe")
		set(PAPYRUS_IMPORT_DIR "${PAPYRUS_GAME}/Data/Source/Scripts")
	else()
		set(PAPYRUS_IMPORT_DIR "${PAPYRUS_GAME}/Data/Scripts/Source")
	endif()
	set(PAPYRUS_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/Scripts")

	foreach(SOURCE IN ITEMS ${PAPYRUS_SOURCES})
		cmake_path(GET SOURCE STEM LAST_ONLY SOURCE_FILENAME)
		cmake_path(REPLACE_EXTENSION SOURCE_FILENAME LAST_ONLY "pex" OUTPUT_VARIABLE OUTPUT_FILENAME)
		cmake_path(APPEND PAPYRUS_OUTPUT_DIR "${OUTPUT_FILENAME}" OUTPUT_VARIABLE OUTPUT_FILE)
		list(APPEND PAPYRUS_OUTPUT "${OUTPUT_FILE}")

		add_custom_command(
			OUTPUT "${OUTPUT_FILE}"
			COMMAND "${PAPYRUS_GAME}/Papyrus Compiler/PapyrusCompiler.exe"
				"${SOURCE}"
				"-import=${PAPYRUS_IMPORTS};${PAPYRUS_IMPORT_DIR}"
				"-output=${PAPYRUS_OUTPUT_DIR}"
				"-flags=${PAPYRUS_IMPORT_DIR}/TESV_Papyrus_Flags.flg"
				"$<$<BOOL:${PAPYRUS_OPTIMIZE}>:-optimize>"
			DEPENDS "${SOURCE}"
			VERBATIM
		)
	endforeach()

	set(_DUMMY "${CMAKE_CURRENT_BINARY_DIR}/_Papyrus/${PAPYRUS_TARGET}.stamp")
	add_custom_command(
		OUTPUT "${_DUMMY}"
		DEPENDS ${PAPYRUS_OUTPUT}
		COMMAND "${CMAKE_COMMAND}" -E touch "${_DUMMY}"
		VERBATIM
	)

	if (PAPYRUS_ANONYMIZE)
		find_pexanon()

		add_custom_command(
			OUTPUT "${_DUMMY}"
			COMMAND "${PEXANON_COMMAND}" -s "${PAPYRUS_OUTPUT_DIR}"
			VERBATIM
			APPEND
		)
	endif()

	add_custom_target(
		"${PAPYRUS_TARGET}"
		ALL
		DEPENDS "${_DUMMY}"
		SOURCES ${PAPYRUS_SOURCES}
	)

	set("${PAPYRUS_TARGET}_OUTPUT" ${PAPYRUS_OUTPUT} PARENT_SCOPE)
endfunction()
