#!/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.

######################
# 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/gif$=clifmimg gif;
#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 (GIF, SVG files, and sixel images - 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"

default_width=640
default_height=480

CACHE_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/clifm/previews"
CACHEDIRTAG_FILE="$CACHE_DIR/CACHEDIR.TAG"
CACHEDIRTAG_HEADER="Signature: 8a477f597d28d172789f06886806bc55
# This file is a cache directory tag created by Clifm.
# For information about cache directory tags, see:
#	http://www.brynosaurus.com/cachedir/"

# Use hashes instead of file names for cached files to generate unique file names
hash_file() {
	! [ -d "$CACHE_DIR" ] && mkdir -p "$CACHE_DIR"
	! [ -f "$CACHEDIRTAG_FILE" ] && echo "$CACHEDIRTAG_HEADER" > "$CACHEDIRTAG_FILE"
	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

	if [ -n "$FZF_PREVIEW_LINES" ]; then
		C=$((FZF_PREVIEW_COLUMNS - 2))
		L=$FZF_PREVIEW_LINES
	else
		[ -z $COLUMNS ] && COLUMNS="$(tput cols)"
		[ -z $LINES ] && LINES="$(tput lines)"
		C=$COLUMNS
		L=$LINES
	fi

	if [ -z "$CLIFM_FZF_LINE" ]; then
		CLIFM_FZF_LINE=0
		CLIFM_TERM_COLUMNS=$COLUMNS
	fi

## Uncomment any of the following previewing methods (instead of kitty or ueberzug).
# If using any of these methods, there is no need to run via clifmrun; just run clifm as always.
#
# New: since 0.44, fzf added sixel support (experimental).
#	chafa -f sixel -s "${C}x$((L - 1))" "$1"; exit 0

#	chafa -f symbols -s "${C}x${L}" "$1"; exit 0
#	pixterm -s 2 -tc "${C}" -tr "${L}" "$1"; exit 0
#	img2txt -H"${L}" -W"${C}" "$1"; exit 0
#	viu -b -h"${L}" -w"${C}" "$1"; exit 0
#	catimg -H"${L}" "$1"; exit 0
#	tiv -h "${L}" -w "${C}" "$1"; exit 0
#	timg -g "${C}x${L}" "$1"; exit 0
#	explosion -w "${C}" -h "${L}" "$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 --loop=0 --place "$FZF_PREVIEW_COLUMNS"x"$FZF_PREVIEW_LINES"@"$X"x"$Y" \
		--clear --transfer-mode=stream --stdin=no --align=left -- "$1"
	else
		printf '{"action": "add", "identifier": "clifm-preview", "x": "%s", "y": "%s", "width": "%s", "height": "%s", "scaler" : "contain", "path": "%s"}\n' "$X" "$Y" "$COLUMNS" "$LINES" "$1" > "$CLIFM_FIFO_UEBERZUG"
	fi
}

main() {
	case "$type" in
		"image") display "$file" ;;
		"gif")
			hash_file "$file"
			! [ -f "${PCACHE}.jpg" ] && \
				magick "$file"[0] -resize 640x480\> "${PCACHE}.jpg"
			display "${PCACHE}.jpg"
		;;
		"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 -scale-to 1920 "$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" ] && \
				magick -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 "$@"
