#!/bin/bash

#
# Copyright (c) 2015-2018 Samuel Thibault <samuel.thibault@ens-lyon.org>
# 
# 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.
# 

# Make sure we have enough options
if [ $# != 5 -a $# != 6 ]; then
  echo "ERROR: $0 jobid user name nb options [filename]" >&2
  exit 1
fi

NB=$4
OPTIONS=$5
FILE=$6

. @CUPS_DATADIR@/braille/cups-braille.sh

####################
# Liblouis options #
####################
LIBLOUIS_CONFIG=""

echo "DEBUG: Input content type: $CONTENT_TYPE" >&2

# FIXME CONTENT_TYPE contains original document, not document passed as parameter ?!!

setupTextRendering() {
  # Default rendering without translation: just reformat paragraphs
  RENDER_CALL="fmt -$TEXTWIDTH"

  #  Tool to be used for the conversion
  case $CONTENT_TYPE in
    text/plain)
      CONVERT=""
      ;;
    text/html)
      CONVERT=""
      RENDER_CALL="lynx -width=$TEXTWIDTH -dump -stdin"
      checkTool lynx lynx "translating html files"
      ;;
    application/msword)
      CONVERT="antiword -"
      checkTool antiword antiword "translating MS-Word doc files"
      ;;
    application/vnd.openxmlformats-officedocument.wordprocessingml.document)
      CONVERT="docx2txt"
      checkTool docx2txt docx2txt "translating MS-Word docx files"
      ;;
    text/rtf|application/rtf)
      CONVERT="rtf2txt /dev/stdin"
      checkTool rtf2txt rtf2txt "translating RTF files"
      ;;
    application/pdf|application/vnd.cups-pdf-banner)
      CONVERT="pdftotext -raw - -"
      checkTool pdftotext poppler "translating PDF files"
      ;;
    *)
      echo "ERROR: unsupported content type $CONTENT_TYPE" >&2
      exit 1
      ;;
  esac
}

# sometimes we can't filter directly from stdin or the original file because the
# tools need to seek within the file (e.g. unzip), or spaces in the path pose
# problem. This can be called in such case to dump the original content to a
# fresh file
dumptofile() {
  ORIGFILE="$FILE"
  FILE=$(mktemp "${TMPDIR:-/tmp}/texttobrf.tmp.XXXXXX")
  trap -- 'rm -f "$FILE"' EXIT
  if [ -n "$ORIGFILE" ]
  then
    cat "$ORIGFILE" > "$FILE"
  else
    cat > "$FILE"
  fi
}

#  Selected braille table
if [ -n "$LIBLOUIS_TABLES" ]
then
  if type file2brl > /dev/null
  then
    # Good, we can use liblouisutdml
    case $CONTENT_TYPE in
      text/plain)
	LIBLOUIS_TOOL="file2brl"
	CONVERT=""
	;;
      text/html)
	LIBLOUIS_TOOL="file2brl -t"
	CONVERT=""
	;;
      text/xml|application/xml|application/xhtml+xml|application/sgml)
	LIBLOUIS_TOOL="file2brl"
	CONVERT=""
	;;
      application/msword)
	LIBLOUIS_TOOL="file2brl"
	CONVERT="antiword -x db -"
	checkTool antiword antiword "translating MS-Word doc files"
	;;
      application/vnd.oasis.opendocument*)
	LIBLOUIS_TOOL="file2brl"
	dumptofile
	CONVERT="unzip -p $FILE content.xml"
	CHARSET=utf-8
	checkTool unzip unzip "translating LibreOffice/OpenOffice OpenDocument files"
	;;
      application/vnd.openxmlformats-officedocument*)
	LIBLOUIS_TOOL="file2brl"
	dumptofile
	CONVERT="unzip -p $FILE word/document.xml"
	CHARSET=utf-8
	checkTool unzip unzip "translating MS-Word docx files"
	;;
      text/rtf|application/rtf)
	LIBLOUIS_TOOL="file2brl"
	CONVERT="rtf2xml /dev/stdin"
	checkTool rtf2xml rtf2xml "translating RTF files"
	;;
      application/pdf|application/vnd.cups-pdf-banner)
	LIBLOUIS_TOOL="file2brl -p"
	CONVERT="pdftotext -raw - -"
	CHARSET=utf-8
	checkTool pdftotext poppler "translating PDF files"
	;;
      *)
	echo "ERROR: unsupported content type $CONTENT_TYPE" >&2
	exit 1
	;;
    esac

    #
    # text encoding
    #
    if [ "$CHARSET" = utf-8 ]
    then
      LIBLOUIS_CONFIG+=" -CinputTextEncoding=UTF8"
    else
      LIBLOUIS_CONFIG+=" -CinputTextEncoding=ascii8"
    fi

    #
    # Page numbers options
    #
    BRAILLEPAGENUMBER=$(getOption BraillePageNumber)
    case "$BRAILLEPAGENUMBER" in
      None) LIBLOUIS_CONFIG+=" -CbraillePages=no";;
      TopMargin) LIBLOUIS_CONFIG+=" -CbraillePages=yes -CbraillePageNumberAt=top -CpageNumberTopSeparateLine=yes";;
      BottomMargin) LIBLOUIS_CONFIG+=" -CbraillePages=yes -CbraillePageNumberAt=bottom -CpageNumberBottomSeparateLine=yes";;
      TopInline) LIBLOUIS_CONFIG+=" -CbraillePages=yes -CbraillePageNumberAt=top -CpageNumberTopSeparateLine=no";;
      BottomInline) LIBLOUIS_CONFIG+=" -CbraillePages=yes -CbraillePageNumberAt=bottom -CpageNumberBottomSeparateLine=no";;
      *)
	printf "ERROR: Unknown braille page number option '%s'\n" "$BRAILLEPAGENUMBER" >&2
	exit 1
	;;
    esac

    PRINTPAGENUMBER=$(getOption PrintPageNumber)
    case "$PRINTPAGENUMBER" in
      None) LIBLOUIS_CONFIG+=" -CprintPages=no";;
      TopMargin) LIBLOUIS_CONFIG+=" -CprintPages=yes -CprintPageNumberAt=top -CpageNumberTopSeparateLine=yes";;
      BottomMargin) LIBLOUIS_CONFIG+=" -CprintPages=yes -CprintPageNumberAt=bottom -CpageNumberBottomSeparateLine=yes";;
      TopInline) LIBLOUIS_CONFIG+=" -CprintPages=yes -CprintPageNumberAt=top -CpageNumberTopSeparateLine=no";;
      BottomInline) LIBLOUIS_CONFIG+=" -CprintPages=yes -CprintPageNumberAt=bottom -CpageNumberBottomSeparateLine=no";;
      *)
	printf "ERROR: Unknown print page number option '%s'\n" "$PRINTPAGENUMBER" >&2
	exit 1
	;;
    esac

    # Page numbering in top or bottom margin actually reduce the given margin
    if [ "$BRAILLEPAGENUMBER" = TopMargin -o "$PRINTPAGENUMBER" = TopMargin ]
    then
      TOPMARGIN=$((TOPMARGIN - 1))
      TEXTHEIGHT=$((TEXTHEIGHT + 1))
    fi
    if [ "$BRAILLEPAGENUMBER" = BottomMargin -o "$PRINTPAGENUMBER" = BottomMargin ]
    then
      BOTTOMMARGIN=$((BOTTOMMARGIN - 1))
      TEXTHEIGHT=$((TEXTHEIGHT + 1))
    fi

    PAGESEPARATOR=$(getOption PageSeparator)
    case "$PAGESEPARATOR" in
      True|true) LIBLOUIS_CONFIG+=" -CpageSeparator=yes";;
      False|false) LIBLOUIS_CONFIG+=" -CpageSeparator=no";;
      *)
	printf "ERROR: Unknown page separator option '%s'\n" "$PAGESEPARATOR" >&2
	exit 1
	;;
    esac

    PAGESEPARATORNUMBER=$(getOption PageSeparatorNumber)
    case "$PAGESEPARATORNUMBER" in
      True|true) LIBLOUIS_CONFIG+=" -CpageSeparatorNumber=yes";;
      False|false) LIBLOUIS_CONFIG+=" -CpageSeparatorNumber=no";;
      *)
	printf "ERROR: Unknown page separator number option '%s'\n" "$PAGESEPARATORNUMBER" >&2
	exit 1
	;;
    esac

    CONTINUEPAGES=$(getOption ContinuePages)
    case "$CONTINUEPAGES" in
      True|true) LIBLOUIS_CONFIG+=" -CcontinuePages=yes";;
      False|false) LIBLOUIS_CONFIG+=" -CcontinuePages=no";;
      *)
	printf "ERROR: Unknown page separator number option '%s'\n" "$CONTINUEPAGES" >&2
	exit 1
	;;
    esac

    LIBLOUIS_CONFIG+=" -CcellsPerLine=$TEXTWIDTH -ClinesPerPage=$TEXTHEIGHT "

    RENDER_CALL="$LIBLOUIS_TOOL -Chyphenate=yes -CliteraryTextTable=en-us-brf.dis,$LIBLOUIS_TABLES,braille-patterns.cti $LIBLOUIS_CONFIG"
  elif type lou_translate > /dev/null
  then
    # Only liblouis, but better than nothing
    setupTextRendering
    printf "WARN: The liblouisutdml package is required for translating braille better\n" >&2
    TRANSLATE="lou_translate en-us-brf.dis,$LIBLOUIS_TABLES,braille-patterns.cti"
  else
    printf "ERROR: The liblouisutdml package is required for translating braille\n" >&2
    exit 1
  fi
else
  # No translation, only text rendering
  printf "WARN: No braille table translation was selected\n" >&2
  setupTextRendering
fi

# Now proceeed
cd $TMPDIR
echo "INFO: Reformating text" >&2

(
set -o pipefail
set -e
if [ -z "$CONVERT" ]
then
  printf "DEBUG: Calling $RENDER_CALL on '%s'\n" "$FILE" >&2
  if [ -z "$FILE" ]
  then
    $RENDER_CALL 2> /dev/null | addmargins
  else
   < "$FILE" $RENDER_CALL 2> /dev/null | addmargins
  fi
elif [ -z "$TRANSLATE" ]
then
  printf "DEBUG: Calling $CONVERT | $RENDER_CALL on '%s'\n" "$FILE" >&2
  if [ -z "$FILE" ]
  then
    $CONVERT | $RENDER_CALL 2> /dev/null | addmargins
  else
  < "$FILE" $CONVERT | $RENDER_CALL 2> /dev/null | addmargins
  fi
else
  printf "DEBUG: Calling $CONVERT | $RENDER_CALL | $TRANSLATE on '%s'\n" "$FILE" >&2
  if [ -z "$FILE" ]
  then
    $CONVERT | $RENDER_CALL 2> /dev/null | $TRANSLATE | addmargins
  else
  < "$FILE" $CONVERT | $RENDER_CALL 2> /dev/null | $TRANSLATE | addmargins
  fi
fi
) || {
  printf "ERROR: text conversion pipeline $CONVERT | $RENDER_CALL | $TRANSLATE | addmargins failed\n" >&2
  exit 1
}

echo "INFO: Ready" >&2
