#.rst:
# FindBoostBook
# -------------
#
# FindModule for BoostBook tools.
#
# IMPORTED Targets
# ^^^^^^^^^^^^^^^^
#
# ``Boost::quickbook``
#  Defined if the system has Boost's quickbook executable.
#
# Result Variables
# ^^^^^^^^^^^^^^^^
#
# This module sets the following variables:
#
# ``BoostBook_FOUND``
#  True, if the system has clang-format.
# ``BoostBook_XSL_PATH``
#  Path to the BoostBook XSL files.
# ``BoostBook_DTD_PATH``
#  Path to the BoostBook DTD files.
#

set(_BoostBook_FIND_ARGS)
if(BoostBook_QUIET)
    list(APPEND _BoostBook_FIND_ARGS QUIET)
endif()

find_package(BoostQuickbook ${_BoostBook_FIND_ARGS})
find_package(Doxygen ${_BoostBook_FIND_ARGS})

find_program(LIBXSLT_XSLTPROC_EXECUTABLE
    DOC "Path to the xsltproc executable"
    NAMES xsltproc
)
mark_as_advanced(LIBXSLT_XSLTPROC_EXECUTABLE)

find_path(BoostBook_XSL_PATH
    NAMES xsl/docbook.xsl
    PATH /usr/share/boost ${BOOST_ROOT} ENV BOOST_ROOT
    PATH_SUFFIXES boostbook/xsl tools/boostbook/xsl
    DOC "Path to BoostBooks's xsl directory."
)
mark_as_advanced(BoostBook_XSL_PATH)

find_path(BoostBook_DTD_PATH
    NAMES dtd/boostbook.dtd
    PATH /usr/share/boost ${BOOST_ROOT} ENV BOOST_ROOT
    PATH_SUFFIXES boostbook/dtd tools/boostbook/dtd
    DOC "Path to BoostBooks's DTD directory."
)
mark_as_advanced(BoostBook_DTD_PATH)

find_path(BoostBook_ASSETS_PATH
    NAMES src/boostbook.css
    PATH /usr/share/boost/doc ${BOOST_ROOT} ENV BOOST_ROOT
    PATH_SUFFIXES boostbook/dtd tools/boostbook/dtd
    DOC "Path to BoostBooks's assets directory."
)
mark_as_advanced(BoostBook_ASSETS_PATH)

include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(BoostBook
    FOUND_VAR BoostBook_FOUND
    REQUIRED_VARS
        BoostBook_XSL_PATH
        BoostBook_DTD_PATH
        BoostBook_ASSETS_PATH
        BoostQuickbook_EXECUTABLE
        LIBXSLT_XSLTPROC_EXECUTABLE
)

if(BoostBook_FOUND AND NOT COMMAND add_boostbook)
    function(add_boostbook _target)
        include(CMakeParseArguments)
                cmake_parse_arguments(_arg
            "ALL"
            "STRIP_FROM_PATH"
            "SOURCES"
            ${ARGN}
        )
        find_program(SED_EXECUTABLE sed)
        function(copy _output _input)
            get_filename_component(_dir "${_output}" DIRECTORY)
            add_custom_command(OUTPUT "${_output}"
                DEPENDS "${_input}"
                COMMAND ${CMAKE_COMMAND} -E make_directory "${_dir}"
                COMMAND ${CMAKE_COMMAND} -E copy
                    "${_input}"
                    "${_output}"
            )
        endfunction()
        function(xsltproc _output)
            cmake_parse_arguments(_arg
                "DIR"
                "STYLESHEET;WORKING_DIRECTORY"
                "INPUT;DEPENDS"
                ${ARGN}
            )
            get_filename_component(_workdir "${_arg_WORKING_DIRECTORY}" ABSOLUTE)
            if(_arg_DIR)
                get_filename_component(_out "${_output}" DIRECTORY)
                set(_out "${_out}/")
            else()
                set(_out ${_output})
            endif()
            add_custom_command(OUTPUT "${_output}"
                DEPENDS ${_arg_STYLESHEET} ${_arg_INPUT} ${_arg_DEPENDS}
                COMMAND ${LIBXSLT_XSLTPROC_EXECUTABLE}
                    --xinclude
                    --output "${_out}"
                    ${_arg_STYLESHEET}
                    ${_arg_INPUT}
                COMMAND ${CMAKE_COMMAND} -E touch_nocreate "${_output}"
                WORKING_DIRECTORY "${_workdir}"
            )
        endfunction()
        function(doxygen _output)
            # Generate doxygen configuration
            cmake_parse_arguments(_arg
                ""
                "WORKING_DIRECTORY"
                "INPUT;DEPENDS"
                ${ARGN}
            )
            get_filename_component(_workdir "${_arg_WORKING_DIRECTORY}" ABSOLUTE)
            string(REPLACE ";" " " _doxinput "${_arg_INPUT}")
            file(WRITE "${_workdir}/Doxyfile.in"
                "# Generated by add_boostbook CMake command\n"
                "GENERATE_HTML=NO\n"
                "GENERATE_LATEX=NO\n"
                "GENERATE_XML=YES\n"
                "INPUT=${_doxinput}\n"
                "OUTPUT_DIRECTORY=\"${_workdir}/doxygen\"\n"
                "QUIET=YES\n"
                "WARN_IF_UNDOCUMENTED=NO\n"
                "STRIP_FROM_INC_PATH=@PROJECT_SOURCE_DIR@\n"
                "STRIP_FROM_PATH=@PROJECT_SOURCE_DIR@\n"
                "\n"
            )
            configure_file(
                "${_workdir}/Doxyfile.in"
                "${_workdir}/Doxyfile"
                @ONLY
            )
            set_property(DIRECTORY APPEND PROPERTY
                ADDITIONAL_MAKE_CLEAN_FILES
                    "${_workdir}/doxygen"
            )

            # Run doxygen to generate xml doc from source
            add_custom_command(OUTPUT "${_workdir}/doxygen/xml/index.xml"
                DEPENDS ${_doxysrc} "${_workdir}/Doxyfile"
                COMMAND ${DOXYGEN_EXECUTABLE} "${_workdir}/Doxyfile"
                WORKING_DIRECTORY "${_workdir}/doxygen"
            )
        endfunction()

        set(_bin_dir "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${_target}.dir")
        set(_doc_assets
            boostbook.css
            docutils.css
            images/alert.png
            images/blank.png
            images/callouts/1.png
            images/callouts/2.png
            images/callouts/3.png
            images/callouts/4.png
            images/callouts/5.png
            images/callouts/6.png
            images/callouts/7.png
            images/callouts/8.png
            images/callouts/9.png
            images/callouts/10.png
            images/callouts/11.png
            images/callouts/12.png
            images/callouts/13.png
            images/callouts/14.png
            images/callouts/15.png
            images/caution.png
            images/draft.png
            images/home.png
            images/important.png
            images/next.png
            images/next_disabled.png
            images/note.png
            images/prev.png
            images/prev_disabled.png
            images/smiley.png
            images/tip.png
            images/toc-blank.png
            images/toc-minus.png
            images/toc-plus.png
            images/up.png
            images/up_disabled.png
            images/warning.png
            minimal.css
            reference.css
        )

        set(_doxsrc)
        set(_qbksrc)
        set(_qbkdeps)
        set(_xmlsrc)
        set(_xmldeps)
        set(_htmldeps)
        foreach(_file IN LISTS _arg_SOURCES)
            get_filename_component(_absfile "${_file}" ABSOLUTE)
            if(_absfile MATCHES "\\.(c|C|cc|cpp|cxx|h|H|hh|hpp|hxx)$")
                list(APPEND _doxsrc ${_absfile})
            elseif(_absfile MATCHES "\\.(qbk)$")
                if(NOT _qbksrc)
                    list(APPEND _qbksrc ${_absfile})
                else()
                    list(APPEND _qbkdeps ${_absfile})
                endif()
            elseif(_absfile MATCHES "\\.(xml)$")
                list(APPEND _xmlsrc ${_absfile})
            else()
                message(AUTHOR_WARNING "Unrecognized file format for file `${_file}'")
            endif()
        endforeach()

        if(_doxsrc)
            doxygen("${_bin_dir}/doxygen/xml/index.xml"
                INPUT ${_doxsrc}
                WORKING_DIRECTORY "${_bin_dir}"
            )
            # collect doxygen's xml files
            xsltproc("${_bin_dir}/autodoc.doxygen.xml"
                STYLESHEET "${BoostBook_XSL_PATH}/doxygen/collect.xsl"
                INPUT "${_bin_dir}/doxygen/xml/index.xml"
                WORKING_DIRECTORY "${_bin_dir}"
            )
            # turon doxygen xml into boostbook xml
            xsltproc("${_bin_dir}/autodoc.xml"
                STYLESHEET "${BoostBook_XSL_PATH}/doxygen/doxygen2boostbook.xsl"
                INPUT "${_bin_dir}/autodoc.doxygen.xml"
                WORKING_DIRECTORY "${_bin_dir}"
            )
            if(SED_EXECUTABLE AND _arg_STRIP_FROM_PATH)
                add_custom_command(OUTPUT "${_bin_dir}/autodoc.xml" APPEND
                    COMMAND ${SED_EXECUTABLE} -i "'s!name=\"${_arg_STRIP_FROM_PATH}!name=\"!g'" "${_bin_dir}/autodoc.xml"
                )
            endif()

            list(APPEND _xmldeps "${_bin_dir}/autodoc.xml")
        endif()

        # Run quickbook to turn qbk files into boostbook
        if(_qbksrc)
            get_filename_component(_name "${_qbksrc}" NAME_WE)
            set(_outxml "${_bin_dir}/${_name}.xml")
            quickbook_process("${_outxml}"
                INPUT "${_qbksrc}"
                DEPENDS ${_qbkdeps}
                WORKING_DIRECTORY "${_bin_dir}"
            )
            list(APPEND _xmlsrc "${_outxml}")
        endif()

        # Turn boostbook to docbook
        xsltproc("${_bin_dir}/docbook.xml"
            STYLESHEET "${BoostBook_XSL_PATH}/docbook.xsl"
            INPUT ${_xmlsrc}
            DEPENDS ${_xmldeps}
            WORKING_DIRECTORY "${_bin_dir}"
        )

        # Turn docbook to html
        xsltproc("${CMAKE_CURRENT_BINARY_DIR}/${_target}/index.html" DIR
            STYLESHEET "${BoostBook_XSL_PATH}/html.xsl"
            INPUT "${_bin_dir}/docbook.xml"
            WORKING_DIRECTORY "${_bin_dir}"
        )

        # Copy assets
        foreach(_asset IN LISTS _doc_assets)
            set(_out "${CMAKE_CURRENT_BINARY_DIR}/${_target}/${_asset}")
            copy("${_out}" "${BoostBook_ASSETS_PATH}/${_asset}")
            list(APPEND _htmldeps "${_out}")
        endforeach()

        # Final target to trigger the boostbook toolchain
        set(_all)
        if(_arg_ALL)
            set(_all "ALL")
        endif()
        add_custom_target(${_target} ${_all}
            DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/${_target}/index.html" ${_htmldeps}
            SOURCES ${_arg_SOURCES}
        )
    endfunction()
endif()

