#!/bin/sh

# Based on https://github.com/cirala/vifmimg, licensed under GPL-3.0
# All changes are licensed under GPL-3.0
# Authors: cirala, L. Abramovich

# Description
# Convert (if necessary) and preview images via an already running
# instance of ueberzug (executed by the 'clifmrun' script) or the kitty
# image protocol. Thumbnails are cached (in $CACHE_DIR) using file hashes
# as names.
#
# The first parameter tells what kind of file is to be converted/displayed
# The second one is the file name to be converted/displayed.

# NOTE: Since the original ueberzug is unmaintained, we recommend using this
# fork instead: https://github.com/ueber-devel/ueberzug.

######################
# Usage
######################
# This script is intended to be used by shotgun, clifm's built-in previewer,
# to generate and display image previews for several file types.
# Follow these steps to enable it:
#
# 1) Copy both this script and 'clifmrun' somewhere in you $PATH (say
# /usr/local/bin) (otherwise, just replace 'clifmimg' in point 2 below
# by 'path/to/clifmimg').
#
# 2) Edit shotgun's config file (F7) and add the following lines at the top
# of the file (to make sure they won't be overriden by previous lines):
#
#X:^application/.*(officedocument|msword|ms-excel|opendocument).*=clifmimg doc;
#X:^text/rtf$=clifmimg doc;
#X:N:.*\.epub$=clifmimg epub;
#X:.*/pdf$=clifmimg pdf
#X:^image/vnd.djvu=clifmimg djvu
#X:^image/svg\+xml$=clifmimg svg;
#X:^image/.*=clifmimg image;
#X:^video/.*=clifmimg video;
#X:^audio/.*=clifmimg audio;
#X:^application/postscript$=clifmimg postscript;
#X:N:.*\.otf$=clifmimg font;
#X:font/.*=clifmimg font;
#
# This instructs clifm to use this script to generate previews for the
# specified files.
# In case you don't want image preview for some of these files types, just
# comment out the corresponding line or change its value to your preferred
# previewing application.
#
# 4) Run clifm via the 'clifmrun' script (which takes care of running an
# instance of ueberzug and set the appropriate values so that it can be used
# by clifm via shotgun, which calls this script to generate previews).

# Dependencies:
# ueberzug (of course, this one is used to display images)
# md5sum or md5 (generate file hashes)
#
# The following applications are used to generate thumbnails:
# ffmpegthumbnailer (Video files)
# epub-thumbnailer (ePub files)
# pdftoppm (PDF files, provided by the poppler package)
# ddjvu (DjVu files, provided by the djvulibre package)
# ffmpeg (Audio files)
# fontpreview (Font files)
# libreoffice (Office files: odt, docx, xlsx, etc)
# gs (Postscript files, provided by the ghostscript package)
# convert (SVG files, provided by the imagemagick package)
#
# Note: The exact package names provinding these programs vary depending
# on your OS/distribution, but ususally they have the same name as the program

type="$1"
file="$2"

CACHE_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/clifm/previews"

# Use hashes instead of file names for cached files to generate unique file names
hash_file() {
	! [ -d "$CACHE_DIR" ] && mkdir -p "$CACHE_DIR"
	if type md5sum > /dev/null 2>&1; then
		PCACHE="$CACHE_DIR/$(md5sum "$1" | cut -d' ' -f1)"
	elif type md5 > /dev/null 2>&1; then
		PCACHE="$CACHE_DIR/$(md5 -q "$1")"
	else
		printf "clifm: No hashing application found.\nEither md5sum or md5 \
are required.\n" >&2
		exit 1
	fi
}

display() {
	[ -z "$1" ] && exit 1

## Uncomment any of the following lines to use a character art method (instead of kitty or ueberzug)
#	chafa -f symbols -s "$((FZF_PREVIEW_COLUMNS - 2))x$((FZF_PREVIEW_LINES))" "$1"; exit 0
#	pixterm -s 2 -tc "$((FZF_PREVIEW_COLUMNS - 2))" -tr "$FZF_PREVIEW_LINES" "$1"; exit 0
#   img2txt -H"$FZF_PREVIEW_LINES" -W"$((FZF_PREVIEW_COLUMNS - 2))" "$1"; exit 0
#	viu -b -h"$FZF_PREVIEW_LINES" -w"$((FZF_PREVIEW_COLUMNS - 2))" "$1"; exit 0
#	catimg -H"$FZF_PREVIEW_LINES" "$1"; exit 0
#	tiv -h "$FZF_PREVIEW_LINES" -w "$((FZF_PREVIEW_COLUMNS - 2))" "$1"; exit 0
#	timg -g "$((FZF_PREVIEW_COLUMNS - 2))x$FZF_PREVIEW_LINES" "$1"; exit 0
#	explosion -w "$((FZF_PREVIEW_COLUMNS - 2))" -h "$FZF_PREVIEW_LINES" "$1"; exit 0

	# CLIFM_TERM_COLUMNS: Number of columns of the current terminal
	# window (value exported by clifm)
	# FZF_PREVIEW_COLUMNS: Number of columns of the fzf preview
	# window (value exported by fzf itself)
	# CLIFM_FZF_LINE: Terminal line of the fzf window (exported by clifm)
	X=$((CLIFM_TERM_COLUMNS - FZF_PREVIEW_COLUMNS))
	Y=$CLIFM_FZF_LINE

	if [ -n "$CLIFM_KITTY_IMG" ]; then
		# CLIFM_KITTY_IMG is the path to a temp file created by clifmrun
		# if running on a kitty terminal
		# This is a pretty dirty hack: let's create an empty temp file
		# (CLIFM_KITTY_IMG) to let clifm know that an image is displayed
		# and should be removed
		touch -- "$CLIFM_KITTY_IMG"
		kitty icat --silent --loop=0 \
		--place "$FZF_PREVIEW_COLUMNS"x"$FZF_PREVIEW_LINES"@"$X"x"$Y" \
		--transfer-mode=stream --align=left -- "$1"
	else
		printf '{"action": "add", "identifier": "clifm-preview", "x": "%s", "y": "%s", "width": "%s", "height": "%s", "path": "%s"}\n' "$X" "$Y" "$COLUMNS" "$LINES" "$1" > "$CLIFM_FIFO_UEBERZUG"
	fi
}

main() {
	case "$type" in
		"image") display "$file" ;;
		"video")
			hash_file "$file"
			! [ -f "${PCACHE}.jpg" ] && \
				ffmpegthumbnailer -i "$file" -o "${PCACHE}.jpg" -s 0 -q 5
			display "${PCACHE}.jpg"
			;;
		"epub")
			hash_file "$file"
			! [ -f "${PCACHE}.jpg" ] && \
				epub-thumbnailer "$file" "${PCACHE}.jpg" 1024 >/dev/null 2>&1
			display "${PCACHE}.jpg"
			;;
		"pdf")
			hash_file "$file"
			! [ -f "${PCACHE}.jpg" ] && \
				pdftoppm -jpeg -f 1 -singlefile "$file" "$PCACHE"
			display "${PCACHE}.jpg"
			;;
		"djvu")
			hash_file "$file"
			! [ -f "${PCACHE}.jpg" ] && \
				ddjvu -format=tiff -quality=90 -page=1 "$file" "$PCACHE.jpg"
			display "${PCACHE}.jpg"
			;;
		"audio")
			hash_file "$file"
			! [ -f "${PCACHE}.jpg" ] && \
				ffmpeg -hide_banner -i "$file" "${PCACHE}.jpg" -y >/dev/null 2>&1
			display "${PCACHE}.jpg"
			;;
		"font")
			hash_file "$file"
			! [ -f "${PCACHE}.jpg" ] && \
				fontpreview -i "$file" -o "${PCACHE}.jpg"
			display "${PCACHE}.jpg"
			;;
		"doc")
			hash_file "$file"
			format="png"
			if ! [ -f "${PCACHE}.$format" ]; then
				libreoffice --headless --convert-to "$format" "$file" \
				--outdir "$CACHE_DIR" > /dev/null 2>&1 || exit 1
				f="${file##*/}"
				mv "$CACHE_DIR/${f%.*}.$format" "${PCACHE}.$format"
			fi
			display "${PCACHE}.$format"
		;;
		"postscript")
			hash_file "$file"
			! [ -f "${PCACHE}.jpg" ] && \
				gs -sDEVICE=jpeg -dJPEGQ=100 -dNOPAUSE -dBATCH -dSAFER -r300 \
				-sOutputFile="${PCACHE}.jpg" "$file" > /dev/null 2>&1
			display "${PCACHE}.jpg"
		;;
		"svg")
			hash_file "$file"
			! [ -f "${PCACHE}.png" ] && \
				convert -background none -size 1920x1080 "$file" "${PCACHE}.png"
			display "${PCACHE}.png"
		;;
#		"comic")
#			hash_file "$file"
#			! [ -f "${PCACHE}.png" ] && comicthumb "$file" "$PCACHE" 1024
#			display "${PCACHE}.png"
#		;;
        *)
    esac
}

main "$@"
