#!/usr/bin/env bash
set -euo pipefail

self=$(readlink -f "${BASH_SOURCE[0]}")
assets=${MD_TO_PDF_HOME:-}
if [[ -z $assets ]]; then
    for candidate in \
        "${XDG_DATA_HOME:-$HOME/.local/share}/md_to_pdf" \
        "$(dirname "$self")/../md_to_pdf" \
        "$(dirname "$self")/md_to_pdf"
    do
        if [[ -f $candidate/base.css ]]; then
            assets=$(readlink -f "$candidate")
            break
        fi
    done
fi

die() { printf 'md_to_pdf: %s\n' "$*" >&2; exit 1; }

view() { ((open_after)) && setsid "${MD_TO_PDF_VIEWER:-xdg-open}" "$1" >/dev/null 2>&1 & :; }

[[ -n $assets ]] || die "cannot find assets (base.css); set MD_TO_PDF_HOME"

themes() { find "$assets/themes" -name '*.css' -printf '%f\n' | sed 's/\.css$//' | sort; }

usage() {
    cat <<'USAGE'
md_to_pdf [options] FILE.md [FILE.md ...]

Render markdown to a typeset PDF via pandoc and WeasyPrint.

Output:
  -o, --output PATH     output file (single input only)
  -d, --dir DIR         output directory (default: /tmp)
      --html            also write the intermediate HTML
      --html-only       write only the HTML, skip the PDF
  -O, --open            open the result when done

Style:
  -t, --theme NAME      colour theme (default: paper, or $MD_TO_PDF_THEME)
  -l, --list-themes     list available themes
      --sans            sans-serif body text
      --ragged          ragged-right instead of justified
  -s, --size PT         base font size, e.g. 11pt (default: 10pt)
      --paper SIZE      letter, a4, a5, legal, ... (default: letter)
      --margin CSS      page margin shorthand (default: 0.9in 1in)

Document:
      --toc             include a table of contents
  -n, --number-sections number the headings
      --engine ENGINE   weasyprint (default) or typst, for documents with math

Anything after -- is passed straight to pandoc.
USAGE
}

theme=${MD_TO_PDF_THEME:-paper}
output=""
outdir=""
keep_html=0
html_only=0
open_after=0
paper=letter
margin="0.9in 1in"
fontsize=10pt
sans=0
ragged=0
toc=0
numbered=0
engine=weasyprint
inputs=()
passthrough=()

while (($#)); do
    case $1 in
        -o|--output) output=$2; shift 2 ;;
        -d|--dir) outdir=$2; shift 2 ;;
        --html) keep_html=1; shift ;;
        --html-only) html_only=1; keep_html=1; shift ;;
        -O|--open) open_after=1; shift ;;
        -t|--theme) theme=$2; shift 2 ;;
        -l|--list-themes) themes | paste -sd' '; exit 0 ;;
        --sans) sans=1; shift ;;
        --ragged) ragged=1; shift ;;
        -s|--size) fontsize=$2; shift 2 ;;
        --paper) paper=$2; shift 2 ;;
        --margin) margin=$2; shift 2 ;;
        --toc) toc=1; shift ;;
        -n|--number-sections) numbered=1; shift ;;
        --engine) engine=$2; shift 2 ;;
        -h|--help) usage; exit 0 ;;
        --) shift; passthrough+=("$@"); break ;;
        -*) die "unknown option: $1 (try --help)" ;;
        *) inputs+=("$1"); shift ;;
    esac
done

((${#inputs[@]})) || { usage >&2; exit 1; }
[[ -f $assets/themes/$theme.css ]] || die "no such theme: $theme (have: $(themes | paste -sd' '))"
(( ${#inputs[@]} == 1 )) || [[ -z $output ]] || die "--output takes a single input file"

pandoc_args=(
    --from markdown+smart
    --to html5
    --standalone
    --template "$assets/template.html"
    --highlight-style kate
    --css "file://$assets/base.css"
    --css "file://$assets/themes/$theme.css"
    -V "papersize=$paper"
    -V "margin=$margin"
    -V "fontsize=$fontsize"
)
((sans)) && pandoc_args+=(-V 'bodyfont=var(--font-head)') || :
((ragged)) && pandoc_args+=(-V ragged=1) || :
((toc)) && pandoc_args+=(--toc --toc-depth=3) || :
((numbered)) && pandoc_args+=(--number-sections) || :
pandoc_args+=("${passthrough[@]+"${passthrough[@]}"}")

tmpdir=$(mktemp -d)
trap 'rm -rf "$tmpdir"' EXIT

for src in "${inputs[@]}"; do
    [[ -f $src ]] || die "no such file: $src"
    src=$(readlink -f "$src")
    srcdir=$(dirname "$src")
    stem=$(basename "$src"); stem=${stem%.*}
    dest_dir=${outdir:-/tmp}
    mkdir -p "$dest_dir"
    pdf=${output:-$dest_dir/$stem.pdf}

    if [[ $engine == typst ]]; then
        typst_args=()
        typst_template=${XDG_DATA_HOME:-$HOME/.local/share}/pandoc/templates/default.typst
        [[ -f $typst_template ]] && typst_args=(--template "$typst_template") || :
        pandoc "$src" --standalone --pdf-engine typst "${typst_args[@]}" -o "$pdf"
        printf '%s\n' "$pdf"
        view "$pdf"
        continue
    fi

    html=$tmpdir/$stem.html
    ((keep_html)) && html=$dest_dir/$stem.html || :

    pandoc "${pandoc_args[@]}" -M "pagetitle=$stem" -V "basehref=file://$srcdir/" -o "$html" "$src"

    if ((html_only)); then
        printf '%s\n' "$html"
        continue
    fi

    weasyprint -q "$html" "$pdf"
    printf '%s\n' "$pdf"
    view "$pdf"
done
