#!/bin/sh
#
# Copyright (c) 2022-2024 by Friedemann Bartels
#
# This file may be distributed and/or modified under the
# conditions of the LaTeX Project Public License, either
# version 1.3c of this license or (at your option) any later
# version.  The latest version of this license is in:
#
#    http://www.latex-project.org/lppl.txt
#
# and version 1.3c or later is part of all distributions of
# LaTeX version 2008/05/04 or later.
#

version=1.1.1

_convert() {
  turbo=$1
  filename=$2
  filenamecache=$3
  fileextcache=$4
  originalwidthsp=$5
  originalheightsp=$6
  originalcropleftsp=$7
  originalcroprightsp=$8
  originalcroptopsp=$9
  originalcropbottomsp=${10}
  density=${11}
  displaywidth=${12}
  displayheight=${13}
  resizethreshold=${14}
  unsharp=${15}
  quality="${16}"

  mkdir -p cache/"$filenamecache"
  originalwidth=$( magick identify -ping -format %w "$filename" )
  originalheight=$( magick identify -ping -format %h "$filename" )
  width=$(( (10 * originalwidth * (originalwidthsp - originalcropleftsp - originalcroprightsp) / originalwidthsp + 5) / 10 ))
  height=$(( (10 * originalheight * (originalheightsp - originalcroptopsp - originalcropbottomsp) / originalheightsp + 5) / 10 ))
  cropleft=$(( (10 * originalwidth * originalcropleftsp / originalwidthsp + 5) / 10 ))
  croptop=$(( (10 * originalheight * originalcroptopsp / originalheightsp + 5) / 10 ))
  resizewidth=$(( (10 * displaywidth * 100 * density / 473628672 + 5) / 10 ))
  if [ $(( resizewidth * resizethreshold / 100 )) -gt $width ]; then
    resizewidth=$width
    resizeheight=$height
  else
    resizeheight=$(( resizewidth * height / width + 1 ))
  fi

  x="x"
  if [ $turbo = 1 ]; then
    export MAGICK_THREAD_LIMIT=1
  fi
  if [ "$quality" != "" ]; then
    quality="-quality $quality"
  fi
  if [ "$unsharp" != "" ]; then
    unsharp="-unsharp $unsharp"
  fi

  magick "$filename" -crop $width$x$height+$cropleft+$croptop -resize $resizewidth$x$resizeheight $unsharp $quality "cache/$filenamecache/.g$fileextcache"
  mv "cache/$filenamecache/.g$fileextcache" "cache/$filenamecache/g$fileextcache"
}

_startbatchprocess() {
  success=0
  for file in cache/*; do
    if [ -f "$file" ]; then
      success=1
      name=$( basename "${file}" )
      mv "$file" "cache/.$name" 2> /dev/null
      if [ $? -eq 0 ]; then
        line=$(head -n 1 "cache/.$name")

        IFS="%"
        set -- $line
        IFS=" "
        _convert 1 "$@"

        rm "cache/.$name"
        break
      fi
    fi
  done

  if [ $success -eq 1 ]; then
    _startbatchprocess
  fi
}

getwidth() {
  if command -v magick >/dev/null 2>&1; then
    filename=$1

    originalwidth=$( magick identify -ping -format %w "$filename" )
    echo $originalwidth
  else
    echo errormagicknotinstalled
  fi
}

getheight() {
  if command -v magick >/dev/null 2>&1; then
    filename=$1

    originalheight=$( magick identify -ping -format %h "$filename" )
    echo $originalheight
  else
    echo errormagicknotinstalled
  fi
}

optimize() {
  if command -v magick >/dev/null 2>&1; then
    filenamecache=$2
    fileextcache=$3

    if [ -f cache/"$filenamecache" ]; then
      mv cache/"$filenamecache" cache/."$filenamecache" 2> /dev/null
      if [ $? -eq 0 ]; then
        line=$(head -n 1 "cache/.$filenamecache")

        IFS="%"
        set -- $line
        IFS=" "
        _convert 1 "$@"

        rm "cache/.$filenamecache"
      else
        while [ ! -f cache/"$filenamecache"/g"$fileextcache" ]; do
          sleep 0.05
        done
      fi
    elif [ -d cache/"$filenamecache" ]; then
      while [ ! -f cache/"$filenamecache"/g"$fileextcache" ]; do
        sleep 0.05
      done
    else
      _convert 0 "$@"
    fi

    echo ok
  else
    echo errormagicknotinstalled
  fi
}

makeshadow() {
  if command -v inkscape >/dev/null 2>&1; then
    filename=$1
    stdDeviation=$2
    opacity=$3
    fill=$4
    width=$5
    height=$6
    framewidth=$7
    frameheight=$8
    frameborder=$9
    frameradius=${10}

    [ ! -d cache ] && mkdir cache
    mkdir -p cache/$filename
    echo "<?xml version='1.0' encoding='UTF-8' standalone='no'?>
      <svg
        width='$width'
        height='$height'
        version='1.1'
        xmlns='http://www.w3.org/2000/svg'
        xmlns:svg='http://www.w3.org/2000/svg'>
        <defs>
          <filter
            style='color-interpolation-filters:sRGB'
            id='blur'
            x='-4'
            y='-4'
            width='8'
            height='8'>
            <feGaussianBlur
              stdDeviation='$stdDeviation' />
          </filter>
        </defs>
        <rect
          style='filter:url(#blur);opacity:$opacity;fill:rgb($fill)'
          width='$framewidth'
          height='$frameheight'
          x='$frameborder'
          y='$frameborder'
          rx='$frameradius'
          ry='$frameradius' />
      </svg>
    " > cache/$filename/s.svg
    inkscape cache/$filename/s.svg --export-dpi=600 --export-filename cache/$filename/s.pdf
    rm cache/$filename/s.svg

    echo ok
  else
    echo errorinkscapenotinstalled
  fi
}

import() {
  if [ -d import ]; then
    importdir=import
  elif [ "$PAGELAYOUT_IMPORT_DIRECTORY" != "" ]; then
    if [ -d "$PAGELAYOUT_IMPORT_DIRECTORY" ]; then
      importdir="$PAGELAYOUT_IMPORT_DIRECTORY"
    else
      echo $PAGELAYOUT_IMPORT_DIRECTORY
      exit
    fi
  else
    echo errornoimportdir
    exit
  fi

  defaultdirectory=$( echo $1 | sed -e 's/^{//g' | sed -e 's/}{.*//g' )
  directorylist=$( echo $1 | sed -e 's/^{//g' | sed -e 's/}$//g' | sed -e 's/}{/$/g' )

  for entry in "$importdir"/*.*
  do
    if [ -f "$entry" ]; then
      name=$( basename "${entry}" )
      if [ "$directorylist" != "" ]; then
        echo "$directorylist" | tr '$' '\n' | while read directory; do
          if [ -f "$directory$name" ]; then
            mv "$entry" "$directory"
          fi
        done
      fi
      if [ -f "$entry" ]; then
        if [ -d "$defaultdirectory" ]; then
          mv "$entry" "$defaultdirectory"
        else
          mv "$entry" .
        fi
      fi
      cachename=$( echo "$name" | sed -e 's/\.[a-zA-Z]*$//g' )
      rm -rf cache/"$cachename"*
    fi
  done
}

startturbo() {
  file="$(echo $1 | sed -e 's/\.pdflatex$//g')"
  if [ -f $file.tex ]; then
    tmpdir=$( mktemp -d 2>/dev/null )/pagelayoutturbo$( date "+%Y%m%d%H%M%S" )$RANDOM
    mkdir $tmpdir

    cp $file.tex $tmpdir/pagelayoutturbobatchoptimizexyz.tex

    command=$(echo $(ps -p $PPID -o command ))
    engine=$(echo $command | sed -e 's/^[A-Z ]*//g' | sed -e 's/ .*//g' | tr -d '\n')

    case "$command" in
      *-shell-escape*)
        shellescape="--shell-escape"
        ;;
    esac

    if [ "$engine" = "xelatex" ]; then
      nopdf="-no-pdf"
    fi

    $engine $shellescape -interaction=batchmode $nopdf --output-directory $tmpdir $tmpdir/pagelayoutturbobatchoptimizexyz.tex > /dev/null

    rm -rf $tmpdir
  fi
}

batchoptimize() {
  [ ! -d cache ] && mkdir cache

  length=$(( $# / 15 ))
  if command -v nproc >/dev/null 2>&1; then
    cores=$( nproc )
  else
    cores=1
  fi
  [ $cores -gt $length ] && cores=$length

  while [ $length -gt 0 ]; do
    filenamecache="$2"

    if [ ! -e cache/"$filenamecache" ]; then
      index=0
      while [ $index -lt 15 ]; do
        if [ $index -eq 0 ]; then
          item="$1"
        else
          item="$item%$1"
        fi

        shift
        index=$(( index + 1 ))
      done

      echo $item > cache/"$filenamecache"
    else
      shift 15
    fi

    length=$(( length - 1 ))
  done

  cores=$(( cores - 1 ))
  while [ $cores -gt 0 ]; do
    _startbatchprocess &
    sleep 0.01
    cores=$(( cores - 1 ))
  done
}

usage() {
  cat <<HELP_USAGE
usage: pagelayoutapi getwidth % FILE
       pagelayoutapi getheight % FILE
       pagelayoutapi optimize % FILE % FILENAME % EXTENSION % ORIGINALWIDTH
         % ORIGINALHEIGHT % CROPLEFT % CROPRIGHT % CROPTOP % CROPBOTTOM
         % DENSITY % WIDTH % HEIGHT % DOWNSAMPLETHRESHOLD % UNSHARP % QUALITY
       pagelayoutapi makeshadow % FILENAME % STANDARDDEVIATION % OPACITY % COLOR
         % WIDTH % HEIGHT % FRAMEWIDTH % FRAMEHEIGHT % MARGIN % BORDERRADIUS
       pagelayoutapi start [% import % [GRAPHICSPATH]] [% turbo % JOBNAME]
       pagelayoutapi batchoptimize % BATCHLIST

   --help      Prints a help message.
   --version   Prints version information.
HELP_USAGE
}

version() {
  echo pagelayoutapi $version
}

input=$( echo "$@" | sed -e 's/\\//g' | sed -e 's/ %/%/g' | sed -e 's/% /%/g' )
IFS="%"
set -- $input
IFS=" "

case "$1" in
getwidth)
  shift

  getwidth "$1"
  ;;
getheight)
  shift

  getheight "$1"
  ;;
optimize)
  shift

  optimize "$@"
  ;;
makeshadow)
  shift

  makeshadow "$@"
  ;;
start)
  shift

  if [ "$1" = "import" ]; then
    shift

    import "$1"

    shift
  fi

  if [ "$1" = "turbo" ]; then
    shift

    startturbo "$1" &
  fi

  echo ok
  ;;
batchoptimize)
  shift

  batchoptimize "$@" &

  echo ok
  ;;
--version)
  version
  ;;
--help)
  usage
esac