#!/bin/bash

# Copyright (C) 2009-2010 Nokia Corporation. All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:

# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.

# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.


function allow_unset() {
    if set +o | grep -q '\-o nounset' ; then
	_WAS_NOUNSET=1
    else
	_WAS_NOUNSET=0
    fi
    set +u
}


function restore_nounset() {
    [ ${_WAS_NOUNSET} -eq 1 ] && set -u
}


YES="yes"
NO="no"

WRITE_LOG=${NO}

COMMON_INCLUDED=${YES}

TOOLCHAIN_VERSION="0.2.6"

MAEMO_RELEASE_NAME=Fremantle
MAEMO_RELEASE_VERSION=5.0

HIGHLIGHT=${YES}

allow_unset
[ -z ${MAEMO_TMP} ] && TMPDIR=${MAEMO_TMP}
[ -z "${WORK_PATH}" ] && WORK_PATH=$( mktemp -d -t "maemodoc-XXXXXX" )
restore_nounset

ORIG_PATH=${PWD}
SCRIPT_PATH=$( dirname ${0} )
SCRIPT_PATH="${ORIG_PATH}/${SCRIPT_PATH}"

SELF=$( basename ${0} )

SNIPPETS_USED=${NO}
SNIPPETS_LONG_USED=${NO}

HTML_PATH=""
HTML_INDEX=""

DOC_ORIG_PATH=""
REL_PATH=""

MENU=${NO}

ALL_CHAPTERS="ALL"
GENERATE_ALL=${NO}
NO_CLEANUP=${NO}

MIN_RUNS=3
EXTRA_RUNS=1

NO_INCLUDES="!!NO!INCLUDES!!"


# Common funcs

function version() {
    echo ${TOOLCHAIN_VERSION}
}


# Only define if no tool-specific usage
if ! type -t usage >> /dev/null ; then
    function usage() {
	spcr=$( echo ${SELF} | sed 's/./ /g' )
	cat <<EOF
MaemoDoc toolchain version ${TOOLCHAIN_VERSION} (c) 2009-2010 Nokia Corporation.

Usage:
        ${SELF}  <document_name>  [ <chapter_name> <chapter_name> ... ]
        ${spcr}  [ --docpath <document_tree_path> ]  
        ${spcr}  [ --out <output_path> ]
        ${spcr}  [ --help | -H ]   [ --version | -V ]
        ${spcr}  [ --write-log ]
        ${spcr}  [ --no-highlight ]
        ${spcr}  [ --<number_of_latex_runs> ]
EOF
	exit 0
    }
fi


function invalid_option() {
    echo "$( basename ${SELF} ): Invalid option '${1}'"
    exit 42
}


function parse_args() {
    allow_unset
    [ -z "${1}" ] && usage

    MENU=${NO}

    while [ ! -z "${1}" ] ; do	
	case ${1} in
            "menu")
		MENU=${YES}
		shift
		;;
	    
	    "--docpath")
		DOC_ORIG_PATH=${2}
		PARM_DOC_PATH=${2}
		shift 2
		;;
	    
	    "--out")
		REL_PATH=${2}
		PARM_REL_PATH=${2}
		shift 2
		;;
	    
	    "--help")
		usage
		;;
	    
	    "-H")
		usage
		;;
	    
	    "-V")
		version
		exit 0
		;;
	    
	    "--version")
		version
		exit 0
		;;

	    "--write-log")
		WRITE_LOG=${YES}
		shift
		;;

	    "--no-cleanup")
		NO_CLEANUP=${YES}
		shift
		;;

	    "--no-highlight")
		HIGHLIGHT=${NO}
		shift
		;;

	    "--"[0-9])
	        runs=${1/--/}
		EXTRA_RUNS=$(( ${runs} - ${MIN_RUNS} ))
		shift
		;;
	    
	    *)
		[ "${1/--*/plep}" == "plep" ] && invalid_option "${1/--/}"

		[ "${1/-*/plep}" == "plep" ] && invalid_option "${1/-/}"

		if [ -z "${NAME}" ] ; then 
		    NAME=${1}
		    shift

		else
		    SELECTED_CHAPTERS="${SELECTED_CHAPTERS} ${1}"
		    shift
		fi
		;;
	esac
    done

    if [ ${EXTRA_RUNS} -lt 0 ] ; then
	echo "$( basename ${0} ): Can't do less than" \
	    "${MIN_RUNS} latex runs!"
	exit 42
    fi

    [ -z "${NAME}" ] && [ ${MENU} == ${NO} ] && usage
    [ -z "${SELECTED_CHAPTERS}" ] && [ ${MENU} == ${NO} ] && \
	GENERATE_ALL=${YES}


    [ -z ${DOC_ORIG_PATH} ] && DOC_ORIG_PATH=${PWD}
    [ -z ${REL_PATH} ] && REL_PATH="${PWD}/releases"
    if [ -z "${LOG_PATH}" ] ; then
	if [ ${WRITE_LOG} == ${YES} ] ; then
	    LOG_PATH="${REL_PATH}/log"
	    if ! echo ${LOG_PATH} | grep -q "^\/" ; then
		LOG_PATH="${PWD}/${LOG_PATH}"
	    fi
	else
	    LOG_PATH=$( mktemp -d /tmp/maemodoc-logs.XXXXXXXX )
	fi
    fi

    [ -z "${DOC_PATH}" ] && DOC_PATH="${WORK_PATH}"
    [ -z "${TEX}" ] && TEX="${DOC_PATH}/${NAME}.tex"
    [ -z "${SKELETON}" ] && SKELETON="${DOC_PATH}/${NAME}-skeleton.tex"
    [ -z "${SNIPPETS}" ] && SNIPPETS="snippets"
    [ -z "${SNIPPETS_LONG}" ] && SNIPPETS_LONG="snippets_long"
    [ -z "${SNIP_PATH}" ] && SNIP_PATH="${DOC_PATH}/${SNIPPETS}"
    [ -z "${SNIP_LONG_PATH}" ] && SNIP_LONG_PATH="${DOC_PATH}/${SNIPPETS_LONG}"

    restore_nounset
}



# Common mangling functions

function make_dirs() {
    echo " * Making directories..."

    [ ${#} -lt 1 ] && (
	echo "make_dir: too few arguments!"
	exit 42
	)
    
    [ "${1}" != "html" ] && [ "${1}" != "pdf" ] && (
	echo "make_dir: illegal argument ${2}"
	exit 42
	)
    
    newdir="${REL_PATH}/${TITLE}/${1}"
    backupdir="${REL_PATH}~/${TITLE}"

    [ -e ${REL_PATH} ] || (
	echo "  - (...)${REL_PATH/${ORIG_PATH}/}"
	mkdir -p ${REL_PATH}
	)

    [ -e ${newdir} ] && (
	echo "  - (...)${backupdir/${ORIG_PATH}/}"
	[ -e ${backupdir} ] && rm -Rf ${backupdir}
	mkdir -p ${backupdir}
	mv ${newdir} ${backupdir}
	)

    [ -e ${LOG_PATH} ] || (
	echo "  - (...)${LOG_PATH/${ORIG_PATH}/}"
	mkdir -p ${LOG_PATH}
	)

    echo "  - (...)${newdir/${ORIG_PATH}/}"
    mkdir -p ${newdir}
}


function resolve_path() {
    pushd . 2>&1 >> /dev/null
    cd ${1}
    pwd
    popd 2>&1 >> /dev/null
}    


function make_temp() {
    path_orig_full=$( resolve_path ${DOC_ORIG_PATH} )
    path_work_full=$( resolve_path ${WORK_PATH} )
    path_orig_sed=$( echo ${path_orig_full} | sed 's/\//\\\//g' );

    for dir_orig in $( find ${path_orig_full} -type d | grep -v '\.svn' ) ; do	
	dir_work=${dir_orig/${path_orig_sed}/${path_work_full}}
	mkdir -p ${dir_work}
	for file in $( find ${dir_orig} -maxdepth 1 -type f ) ; do
#	    if [ "${file}" == "${file%.tex}.tex" ] ; then
#		cp ${file} ${dir_work}
#	    else
	    ln -s ${file} ${dir_work}
#	    fi
	done
    done
}


function _list_chapters() {
    grep -oEe "^[^%]*\\\\include{[^}]*}" ${TEX} \
        | sed -e 's/.include{\([^}]*\)}/\1}/g' \
	| sed 's/}//' 
}

function check_snippets() {
    _list_chapters | while read -r chptr ; do
        grep -q "${SNIPPETS}/" "${DOC_PATH}/${chptr}.tex"  \
	    && SNIPPETS_USED=${YES}
        grep -q "${SNIPPETS_LONG}/" "${DOC_PATH}/${chptr}.tex" \
	    && SNIPPETS_LONG_USED=${YES}
    done
}


function roll_tarball() {
    rm "${REL_PATH}/${NAME}/${NAME}.tar.gz" 1>/dev/null 2>/dev/null
    tar -C ${REL_PATH} -cf ${NAME}.tar ${NAME}

    if [ -d ${DOC_PATH}/files ] ; then
        subdir=$( ls -1 ${DOC_PATH}/files | grep ${NAME} )
        tar -C ${DOC_PATH} -rf "${REL_PATH}/${NAME}.tar" \
	    "files/${subdir}/*"
    fi

    [ ${SNIPPETS_USED} == ${YES} ] \
	&& tar -C ${DOC_PATH} -rf "${REL_PATH}/${NAME}.tar" "${SNIPPETS}/*"
    [ ${SNIPPETS_LONG_USED} == ${YES} ] \
        && tar -C ${DOC_PATH} -rf "${REL_PATH}/${NAME}.tar" "${SNIPPETS_LONG}/*"
    mv "${REL_PATH}/${NAME}.tar" "${REL_PATH}/${NAME}/"
    gzip "${REL_PATH}/${NAME}/${NAME}.tar"
}


function roll_deployment_tarball() {
    tar -C ${REL_PATH} -czf deployment_${NAME}.tar.gz ${NAME}
}


function parse_title() {
    echo " * Parsing document title..."
    TITLE=$( sed -rn '
      /^[^%]*\\title/ {
        : found_title
          /[{].*[}]/ {
            s/.*[{]//
            s/[}].*//
            s/^( )*//
            s/( )*$//
            p
            q
          }
          N
          b found_title
      }' ${TEX} )

    if [ ! -z "${TITLE}" ] ; then
	echo "  - \`${TITLE}'"
	TITLE=$( echo ${TITLE} | sed 's/ /_/g' )
	return
    fi
    echo "!!! No title found"
    exit 42
}


function get_num_txt() {
    num_txt="${1}th"
    case ${1} in
	1) num_txt="First" ;;
	2) num_txt="Second" ;;
	3) num_txt="Third" ;;
	4) num_txt="Fourth" ;;
	5) num_txt="Fifth" ;;
    esac
}

function run_latex() {
    get_num_txt ${1}
    echo -n " - ${num_txt} latex run... "
    pushd . 2>&1 >/dev/null
    cd ${DOC_PATH}
    latex -interaction=nonstopmode ${TEX} 2>&1 > "${LOG_PATH}/latex.${1}.log"
    popd 2>&1 >/dev/null
    echo "done."
}

function execute_latex() {
    runs=$(( ${MIN_RUNS} + ${EXTRA_RUNS} ))
    run_num=1
    run_latex ${run_num}

    echo -n " - Running bibtex... "
    pushd . 2>&1 >/dev/null
    cd ${DOC_PATH}
    bibtex "${TEX%%.*}.aux" 2>&1 > "${LOG_PATH}/bibtex.log"
    popd 2>&1 >/dev/null
    echo "done."

    while [ ${run_num} -lt ${runs} ] ; do
	(( run_num++ ))
	run_latex ${run_num}
    done
}


function parse_skeleton() {
    new_skel=$( grep -m 1 -o '\\input{.*-skeleton}' ${skels/* /} )
    if [ ! -z "${new_skel}" ] ; then
	new_skel=${new_skel/*\{/}
	new_skel=${new_skel/\}*/}
	new_skel="${new_skel}.tex"
	skels="${skels} ${skeldir}/${new_skel}"
	parse_skeleton
    fi
}


function get_skeleton_list() {
    # This is currently not used.
    return
#    skeldir=$( dirname ${TEX} )    
#    skels=${TEX}
#    parse_skeleton
#    SKELETONS=${skels/${TEX}/}
#    if [ -z "${SKELETONS}" ] ; then
#	echo "  ! No skeletons found, exiting."
#	exit 42
#    else
#	echo " * Parsing skeleton names..."
#	for file in ${SKELETONS} ; do
#	    echo "  - \`$( basename ${file} )'"
#	done
#    fi
}


function get_chapter_list() {
    CHAPTERS=""
    includes=$( egrep -o '^( )*\\include{.*}' ${TEX} )
    if [ -z "${includes}" ] ; then
	echo " * No chapters found."
	CHAPTERS=${NO_INCLUDES}
    else
	echo " * Parsing chapter names..."
	for include in ${includes} ; do
	    include=${include/*\{/}
	    include=${include/\}*/}
	    CHAPTERS="${CHAPTERS} ${include}"
	    echo "  - \`${include/chapters\//}'"
	done
    fi
}


function prune_chapters() {
    [ "${CHAPTERS}" == ${NO_INCLUDES} ] && return

    echo " * Selecting chapters..."

    if ( echo "foo${SELECTED_CHAPTERS}" | \
	egrep -q "^foo *${ALL_CHAPTERS}" ) || 
	[ ${GENERATE_ALL} == ${YES} ] ; then
	SELECTED_CHAPTERS=${CHAPTERS}
    fi
    
    if [ -z "${SELECTED_CHAPTERS}" ] ; then
	echo "  - No chapters selected, exiting."
	restore_nounset
	exit
    fi
    restore_nounset
    anyfound=${NO}
    for chapter in ${CHAPTERS} ; do
	found=${NO}
	for selected in ${SELECTED_CHAPTERS} ; do
	    selected=${selected/chapters\//}
	    selected="chapters/${selected}"
	    [ ${selected} == ${chapter} ] && found=${YES}
	done
	if [ ${found} == ${NO} ] ; then
	    chaptersed=$( echo ${chapter} | sed 's/\//\\\//g' )
	    sed -i "/\\include{${chaptersed}}/d" ${TEX}
	else
	    anyfound=${YES}
	    echo "  - \`${chapter/chapters\//}'"
	fi
    done
    if [ ${anyfound} == ${NO} ] ; then
	echo " * No chapters left after pruning, exiting."
	exit 42
    fi
}


function check_paths() {
    if [ ! -d ${DOC_ORIG_PATH} ] ; then 
	echo "Unable to find the document path, please use" \
	    "--docpath <document_path>."
	exit 42
    fi
}