#!/bin/bash

readonly CONFIG="$HOME/.config/mimi/mime.conf"

find_in_config() {
	[[ -f "$CONFIG" ]] || return
	grep -m 1 "^$1: " "$CONFIG" | cut -d ' ' -f 2-
}

need_terminal() {
	grep -m 1 -q '^Terminal=true$'
}

find_exec_in_desktop_file() {
	awk -F '[= ]' '$1 == "Exec" {print $2; exit}'
}

find_desktop_file_by() {
	local path=(/usr/share/applications/)
	[[ -d "$HOME/.local/share/applications" ]] && path+=("$HOME/.local/share/applications")
	grep -m 1 "^$1=.*$2" -R "${path[@]}" | awk -F : -v pat="$2" '{ print index($2, pat), length($2), $1 }' | sort -t ' ' -k1,1n -k2,2nr | awk '{ print $3; exit }'
}

url_decode() {
	echo -e "$(sed 's/%\([a-f0-9A-F]\{2\}\)/\\x\1/g')"
}

fork_run() {
	echo "$*"
	"$@" &>/dev/null &
	exit 0
}

exist() {
	type "$@" &>/dev/null
}

usage() {
	cat <<-EOF

	Usage: xdg-open [file|directory|protocol]

	It opens a file according to the extension
	To setup the extension, create $CONFIG

	mimi :)
	EOF
	exit 1
}

# config
# 1. ext
# 2. protocol
# 3. mime
# 4. general mime
# .desktop (mime and general mime)
# 5. ask

[[ ! "$*" ]] && usage

arg="$*"
ext=''
protocol=''
mime=''
general_mime=''

# fix file://
if [[ "$arg" =~ ^file://(.*)$ ]]; then
	# strip file://
	arg="$(url_decode <<<"${BASH_REMATCH[1]}")"
	protocol=file
fi

if [[ -e "$arg" ]]; then
	# file or dir
	mime="$(file -ib "$arg" | cut -d';' -f1)"
	if [[ -f "$arg" ]]; then
		ext="$(tr '[:upper:]' '[:lower:]' <<< "${arg##*.}")"
	fi
fi

# protocol to mime ext
if [[ "$arg" =~ ^([a-zA-Z]+): ]]; then
	# use protocol to guess mime ext
	protocol="${BASH_REMATCH[1]}"
	case "$protocol" in
		http|https)
			mime=text/html
			ext=html
			;;
		magnet)
			mime=application/x-bittorrent
			ext=torrent
			;;
		irc)
			mime=x-scheme-handler/irc
			;;
	esac
fi


# application mime is specific
[[ "$mime" =~ ^(audio|image|text|video)/ ]] && general_mime="${BASH_REMATCH[1]}/"

exist "$TERM" || TERM="$(find_in_config TERM)"

# config
for search in $ext $protocol $mime $general_mime; do
	app=($(find_in_config "$search"))
	[[ "${app[0]}" == TERM ]] && exist "$TERM" && app[0]="$TERM"
	[[ "${app[*]}" ]] && fork_run "${app[@]}" "$arg"
done

# .desktop
for search in $mime $general_mime; do
	desktop="$(find_desktop_file_by MimeType "$search")"
	if [[ "$desktop" ]]; then
		echo "$desktop"
		app=($(find_exec_in_desktop_file <"$desktop"))
		if need_terminal <"$desktop"; then
			echo "term: $TERM"
			exist "$TERM" && fork_run "$TERM" -e "${app[@]}" "$arg"
		else
			fork_run "${app[@]}" "$arg"
		fi
	fi
done

# ask
if exist dmenu; then
	app=($(IFS=: stest -flx $PATH | sort -u | dmenu -p "how to open $arg"))
	[[ "${app[*]}" ]] && fork_run "${app[@]}" "$arg"
fi
