#
#    Copyright 2014, 2015, 2017 Kai Pastor
#    
#    This file is part of OpenOrienteering.
# 
#    OpenOrienteering 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.
# 
#    OpenOrienteering 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 OpenOrienteering.  If not, see <http://www.gnu.org/licenses/>.

cmake_policy(SET CMP0007 NEW)

# Splits the frontmatter from the body of the input, and stores these parts
# in the variables with the names given in the frontmatter and body parameters.
function(split_frontmatter frontmatter body input)
	string(REGEX MATCH "\r?\n----*\r?\n.*$" _body "${input}")
	string(REPLACE "${_body}" "" _frontmatter "${input}")
	string(REGEX REPLACE "^----*(\r?\n)(.*)" "\\1\\2" _frontmatter "${_frontmatter}")
	string(REGEX REPLACE "^\r?\n----*\r?\n" "" _body "${_body}")
	set(${frontmatter} "${_frontmatter}" PARENT_SCOPE)
	set(${body} "${_body}" PARENT_SCOPE)
endfunction()

# Gets the value of the given field from the YAML input, and stores it
# in the variable named by result.
function(get_yaml_field result input field)
	string(REGEX MATCH "(^|\r?\n)${field} *:.*" match "${input}")
	if(match)
		string(REGEX REPLACE "\r?\n?${field} *: *" "" value "${match}")
		if(value MATCHES "^\r?\n")
			# list
			string(REGEX REPLACE "\r?\n(---|[^\n\r]*:).*" "" value "${value}")
			string(REGEX REPLACE "\r?\n *- *([^\n\r]*)" "\\1;" value "${value}")
			list(REMOVE_ITEM value "")
		else()
			# single value
			string(REGEX REPLACE "\r?\n.*" "" value "${value}")
		endif()
		set(${result} ${value} PARENT_SCOPE)
	else()
		set(${result} "${field}-NOTFOUND" PARENT_SCOPE)
	endif()
endfunction()



if(NOT EXISTS "markdown-pdflatex")
	file(MAKE_DIRECTORY "markdown-pdflatex")
endif()

if(NOT EXISTS "preprocess-markdown-pdflatex.stamp")
	file(WRITE "preprocess-markdown-pdflatex.stamp")
endif()

set(all_pages )

set(subpage_list index)
file(GLOB input_files RELATIVE "@CMAKE_CURRENT_SOURCE_DIR@/pages" "@CMAKE_CURRENT_SOURCE_DIR@/pages/*.md")
foreach(file ${input_files})
	set(file_remarks )

	string(REGEX REPLACE "[.]md$" "" pagename "${file}")
	string(REPLACE " " "_" pagename_safe   "${pagename}")
	if(NOT "${pagename}" STREQUAL "${pagename_safe}")
		list(APPEND file_remarks "unsafe filename")
	endif()
	list(APPEND subpage_list "${pagename_safe}")

	file(READ "@CMAKE_CURRENT_SOURCE_DIR@/pages/${file}" input)

	# YAML frontmatter
	split_frontmatter(frontmatter output "${input}")
	if(NOT frontmatter)
		message(FATAL_ERROR "${file}:1: Missing frontmatter")
	endif()

	get_yaml_field(title "${frontmatter}" "title")
	if(NOT title)
		message(FATAL_ERROR "${file}:1: No title in frontmatter")
	endif()
	set(output "${title} {#${pagename_safe}}\n===\n\n${output}")

	get_yaml_field(subpages ${frontmatter} "subpages")
	if(subpages)
		string(REPLACE ".md" "" subpages "${subpages}")
		list(INSERT subpages 0 "## More Information\n")
		string(REGEX REPLACE ";" "\n - \\\\subpage " subpages "${subpages}")
		set(output "${output}\n\n${subpages}")
	endif()

	get_yaml_field(keywords ${frontmatter} "keywords")
	if(keywords)
		string(REGEX REPLACE ";" "\n\\\\addindex " keywords "${keywords}")
		# Not working as expected:
		#set(output "${output}\n\n\\addindex ${keywords}")
	endif()
	
	# HTML markup
	string(REGEX MATCH "</?(!DOCTYPE|html|head|title|link|meta|body)[^>]*>" unsupported_element "${output}")
	if(unsupported_element)
		message(FATAL_ERROR "${file}:1: Unsupported HTML element ${unsupported_element}")
	endif()
	string(REGEX REPLACE "<hr */?>\r?\n?" "\n---\n" output "${output}")
	string(REGEX REPLACE "\n?<img [^>]*src=\"([^\"]*)\"[^>]*>[\n ]?" "\n![](\\1)\n" output "${output}")
	
	# SF Markdown
	string(REGEX REPLACE "\\[\\[img +(src=)?([^] ]+) *]]" "![](\\2)" output "${output}")
	string(REGEX REPLACE "\\[\\[img +(src=)?([^] ]+) +alt=\"([^\"]+)\" *]]" "![\\3](\\2)" output "${output}")
	string(REGEX REPLACE "\\[\\[img +(src=)?([^] ]+) +alt=([^]]*) *]]" "![\\3](\\2)" output "${output}")
	
	# Resource paths
	string(REGEX REPLACE "(!\\[[^]]*\\]\\()../mapper-images/" "\\1" output "${output}")
	string(REGEX REPLACE "href=\"attachment/" "href=\"" output "${output}")
	
	# Headlines: workaround doxygen strict hierarchy requirements
	string(REGEX REPLACE "(\r?\n)#(#+ +[^\r\n{]*{#[^\r\n]*})" "\\1\\2" output "${output}")
	
	# Headlines: Add labels when missing (no trailing '{#xxx}')
	string(REGEX REPLACE "([\r\n]#+ +)([^\r\n]*[^\r\n} ]) *([\r\n])" "\\1 \\2 {#LABEL!\\2}\\3" output "${output}")
	string(REGEX MATCHALL "{#LABEL![^\r\n]*}" labels "${output}")
	foreach(label ${labels})
		string(REPLACE " " "-" replacement "${label}")
		string(REPLACE "{#LABEL!" "" replacement "${replacement}")
		string(REGEX REPLACE "[^-_a-zA-Z0-9]" "" replacement "${replacement}")
		string(TOLOWER "${replacement}" replacement)
		string(REPLACE "${label}" "{#${replacement}}" output "${output}")
	endforeach()
	string(REGEX REPLACE "([\r\n]#+ [^\r\n]*){#([^}]*)}" "\n\\\\latexonly\n\\\\hypertarget{${pagename_safe}_\\2}{}\n\\\\label{${pagename_safe}_\\2}\n\\\\endlatexonly\\1" output "${output}")
	
	# Can't use Markdown for images in LaTeX
	set(scale "0.55")
	# 1. All non-inline images
	string(REGEX REPLACE "[\r\n][\t ]*!\\[ *\\]\\( *([^)]*)\\)[\t ]*[\r\n]" "\n\\\\latexonly\n\\\\begin{DoxyImageNoCaption}\n  \\\\mbox{\\\\includegraphics[scale=${scale}]{\\1}}\n\\\\end{DoxyImageNoCaption}\n\\\\endlatexonly\n" output "${output}")
	string(REGEX REPLACE "[\r\n][\t ]*!\\[ *([^]]*)\\]\\( *([^)]*)\\)[\t ]*[\r\n]" "\n\\\\latexonly\n\\\\begin{DoxyImage}\n  \\\\includegraphics[scale=${scale}]{\\2}\n  \\\\caption{\\1}\n\\\\end{DoxyImage}\n\\\\endlatexonly\n" output "${output}")
	# 2. Remaining images are inline
	string(REGEX REPLACE "[\r\n]####?  *([\r\n]*!\\[[^\r\n{]*){#([^}]*)}" "\n\\\\latexonly\n\\\\hypertarget{${pagename_safe}_\\2}{}\\\\subsubsection*{\n\\\\endlatexonly\n\\1\n\\\\latexonly\n}\\\\label{${pagename_safe}_\\2}\n\\\\endlatexonly\n" output "${output}")
	string(REGEX REPLACE "[\r\n]####?  *([\r\n]*!\\[[^\r\n]*)" "\n\\\\latexonly\n\\\\subsubsection*{\n\\\\endlatexonly\n\\1\n\\\\latexonly\n}\n\\\\endlatexonly\n" output "${output}")
	string(REGEX REPLACE "!\\[ *([^]]*)\\]\\(([^)]*)\\)" "\\\\latexonly\n  {\\\\hskip 0.1em}\\\\raisebox{-.15\\\\height}{\\\\includegraphics[height=2ex]{\\2}}{\\\\hskip 0.1em}\n\\\\endlatexonly\n" output "${output}")
	# 3. Common
	string(REGEX REPLACE "\\\\endlatexonly[\r\n\t ]*\\\\latexonly[\r\n]?" "" output "${output}")
	string(REGEX MATCHALL "\\\\includegraphics[^{]*{[^}]*}" graphics "${output}")
	string(REGEX REPLACE "(\\\\includegraphics[^{]*{)[^/}]*/([^}]*)" "\\1\\2" output "${output}")
	if(graphics)
		list(REMOVE_DUPLICATES graphics)
		string(REGEX REPLACE "\\\\includegraphics[^{]*{([^}]*)}" "\\\\image latex \"\\1\"\n" graphics ${graphics})
		string(CONCAT output 
		  "${output}\n"
		  "\\latexonly\n"
		  "% *** Let doxygen copy images ***\n"
		  "\\iffalse\n"
		  "\\endlatexonly\n"
		  ${graphics}
		  "\\latexonly\n"
		  "\\fi\n"
		  "\\endlatexonly\n"
		)
	endif()
	
	# Liquid/Kramdown/Markdown markup
	string(REGEX REPLACE "\r?\n *[-*]  *[^\r\n]*\r?\n{:toc}" "\\\\tableofcontents" output "${output}")
	# For TeX, treat nosubpage like subpage
	# Collect subpage information for sorting files
	string(REGEX MATCHALL "\\[[^]]*\\]\\([^\)]*.md\\){: \\.n?o?subpage}" "subpages_${pagename_safe}" "${output}")
	if(subpages_${pagename_safe})
		string(REGEX REPLACE "\\[[^]]*\\]\\(([^\)]*).md\\){: \\.n?o?subpage}" "\\1" "subpages_${pagename_safe}" "${subpages_${pagename_safe}}")
	endif()
	string(REGEX REPLACE "(\\[[^]\"]*)\\\"([^]\"]*)\\\"([^[)\"]*\\){: \\.n?o?subpage})" "\\1\\\\\"\\2\\\\\"\\3" output "${output}")
	string(REGEX REPLACE "\\[([^]]*)\\]\\(([^\)]*)\\.md\\){: \\.n?o?subpage}" "\\\\subpage \\2 \"\\1\"" output "${output}")
	string(REGEX REPLACE "(\\[[^]]*\\])\\(#([^)]*)\\)" "\\1(${pagename_safe}.md#\\2)" output "${output}")
	string(REGEX REPLACE "(\\[[^]]*\\])\\(([^\)#]*)\\.md#([^\)]*)\\)" "\\1(#\\2_\\3)" output "${output}")
	string(REGEX REPLACE "(\\[[^]]*\\])\\(([^\)#]*)\\.md\\)" "\\1(#\\2)" output "${output}")
	string(REGEX REPLACE "{% [^%]* %}|{:[^}]*}" "" output "${output}")
	
	string(REGEX REPLACE "([\r\n] *\\[[^]]*\\]: *)([^#\r\n]*)\\.md#"      "\\1#\\2_"   output "${output}")
	string(REGEX REPLACE "([\r\n] *\\[[^]]*\\]: *)([^#\r\n]*)\\.md([^#])" "\\1#\\2\\3" output "${output}")
		
	if (APPLE)
		string(REGEX REPLACE "Alt[+]"   "⌥" output "${output}")
		string(REGEX REPLACE "Ctrl[+]"  "⌘" output "${output}")
		string(REGEX REPLACE "Shift[+]" "⇧" output "${output}")
		string(REGEX REPLACE "⌘⇧" "⇧⌘" output "${output}")
	endif()
	
	string(MD5 output_md5 "${output}")
	set(file_md5)
	if(EXISTS "markdown-pdflatex/${file}")
		file(MD5 "markdown-pdflatex/${file}" file_md5)
	endif()
	if(NOT "${output_md5}" STREQUAL "${file_md5}")
		message(STATUS "Updating ${file}")
		file(WRITE "markdown-pdflatex/${file}" "${output}")
		if(EXISTS "preprocess-markdown-pdflatex.stamp")
			file(READ "preprocess-markdown-pdflatex.stamp" markdown_log)
			string(REGEX REPLACE "([.+[\(\)^$*?|]|])" "\\\\\\1" file_esc "${file}")
			string(REGEX REPLACE "(^|\n)[^\n]*: ${file_esc}( \\([^)]*\\))?\r?\n" "\\1" markdown_log "${markdown_log}")
		else()
			set(markdown_log "")
		endif()
		string(TIMESTAMP date "%Y-%m-%d %H:%M:%S")
		if (file_remarks)
			set(file_remarks " (${file_remarks})")
		endif()
		file(WRITE "preprocess-markdown-pdflatex.stamp" "${markdown_log}" "${date}: ${file}${file_remarks}\n")
	endif()
endforeach()

while(subpage_list)
	list(GET subpage_list 0 page)
	list(REMOVE_ITEM subpage_list "${page}")
	set(path " \\\n  @CMAKE_CURRENT_BINARY_DIR@/markdown-pdflatex/${page}.md")
	list(FIND page_list "${path}" found)
	if(found EQUAL -1)
		list(APPEND page_list "${path}")
		if(subpages_${page})
			list(INSERT subpage_list 0 "${subpages_${page}}")
		endif()
	endif()
endwhile()
list(REMOVE_DUPLICATES page_list)
string(REPLACE ";" " " page_list "${page_list}")
set(doxygen-input "INPUT = ${page_list}")
string(MD5 output_md5 "${doxygen-input}")
set(file_md5)
if(EXISTS "@CMAKE_CURRENT_BINARY_DIR@/Doxyfile-pdflatex-input.txt")
	file(MD5 "@CMAKE_CURRENT_BINARY_DIR@/Doxyfile-pdflatex-input.txt" file_md5)
endif()
if(NOT "${output_md5}" STREQUAL "${file_md5}")
	file(WRITE "@CMAKE_CURRENT_BINARY_DIR@/Doxyfile-pdflatex-input.txt" "${doxygen-input}")
endif()

file(GLOB output_files RELATIVE "@CMAKE_CURRENT_BINARY_DIR@/markdown-pdflatex" "@CMAKE_CURRENT_BINARY_DIR@/markdown-pdflatex/*.md")
foreach(file ${output_files})
	if(NOT EXISTS "@CMAKE_CURRENT_SOURCE_DIR@/pages/${file}")
		message(STATUS "Removing ${file}")
		file(REMOVE "markdown-pdflatex/${file}")
		if(EXISTS "preprocess-markdown-pdflatex.stamp")
			file(READ "preprocess-markdown-pdflatex.stamp" markdown_log)
			string(REGEX REPLACE "([.+[\(\)^$*?|]|])" "\\\\\\1" file_esc "${file}")
			string(REGEX REPLACE "(^|\n)[^\n]*: ${file_esc}\r?\n" "\\1" markdown_log "${markdown_log}")
		else()
			set(markdown_log "")
		endif()
		file(WRITE "preprocess-markdown-pdflatex.stamp" "${markdown_log}")
	endif()
endforeach()
