#!/bin/bash

set -e
XDG_DATA_HOME="${XDG_DATA_HOME:-$HOME/.local/share}"

subcommand=""
reminderdir="$XDG_DATA_HOME/reminderfiles"
date=""
before_date=""
after_date=""
description=""
filepath=""
uuid=""
is_json=""

show_help() {
cat <<EOF
Usage: reminderfile <subcommand> <<options>> <bar>

Blubber blah blah ...
EOF
}

while [[ "$#" -gt 0 ]]; do
	case "$1" in
		--date) date="$2"; shift 2;;
		--before) before_date="$2"; shift 2;;
		--after) after_date="$2"; shift 2;;
		--description) description="$2"; shift 2;;
		--file) filepath="$2"; shift 2;;
		--uuid) uuid="$2"; shift 2;;
		--json) is_json="y"; shift;;

		add|remove|today|query|get-file) subcommand="$1"; shift 1;;
		--help) show_help; exit 0;;
		*) printf "Unknown option: %s\n" "$1"; exit 1;;
	esac
done

assert_file() {
	if ! [ -r "$1" ] ; then
		echo "No such file or directory: $1" >&2
		return 1
	fi
}

slugify() {
	sed \
		-e "s/ /_/g" \
		-e "s/[^A-Za-z0-9_.öäüÖÄÜß-]/_/g" \
		-e "s/__*/_/g" \
		-e "s/^_*//" \
		-e "s/_*$//"
}

# name, date, uuid
generate_filename() {
	printf "%s_%s_[%s].reminder" "$(date --date "$2" +%Y-%m-%d)" "$(slugify <<< "$1" | grep -oE '^.{64}')" "$3"
}

# date, filepath, description
add_entry() {
	uuid="$(uuidgen)"
	date="$( date --date "$1" +%s )"
	description="$3"
	[ -z "$2" ] || file="$(realpath "$2")"
	reminderfile="$reminderdir/$(generate_filename "${description:-Reminder}" "@$date" "$uuid" )"
	json="$(
		jq -n --arg uuid "$uuid" --argjson unixtime "$date" --arg file "$file" --arg description "$description" \
		'{uuid:$uuid, unixtime:$unixtime, file:$file, description:$description}'
	)"
	[ -e "$reminderdir" ] || mkdir -p "$reminderdir"
	printf "%s\n" "$json" > "$reminderfile"
	echo "$uuid"
}

# uuid prefix
remove_entry() {
	[ "$(wc -c <<< "$1")" -gt 4 ]
	FILE="$(get_file_by_uuid "$1" | head -n 1)"
	[ -z "$FILE" ] || trash-put -- "$FILE"
}

get_file_by_uuid() {
	cd "$reminderdir" &&
	find . -name "*__\[$1*\].reminder" -type f | xargs -L 1 -r realpath --
}

filter_day() {
	if [ -n "$date" ] ; then
		start_date="$( date --date "$date" +%s )"
		end_date="$(( start_date + 86400 ))"
		jq --argjson start_date "$start_date" --argjson end_date "$end_date" 'map(
		select(
		(.unixtime >= $start_date) and .unixtime < $end_date
		))'
	else
		cat
	fi
}

filter_before() {
	if [ -n "$before_date" ] ; then
		end_date="$(date --date "$before_date" +%s)"
		jq --argjson end_date "$end_date" 'map(select(.unixtime < $end_date))'
	else
		cat
	fi
}

filter_after() {
	if [ -n "$after_date" ] ; then
		start_date="$(date --date "$after_date" +%s)"
		jq --argjson start_date "$start_date" 'map(select(.unixtime >= $start_date))'
	else
		cat
	fi
}

filter_file() {
	if [ -n "$filepath" ] ; then
		case "$filepath" in
			*\*)
				jq --arg file "$(sed 's/\*$//' <<< "$filepath")" 'map(select(.file|startswith($file)))'
				;;
			\**)
				jq --arg file "$(sed 's/^\*//' <<< "$filepath")" 'map(select(.file|endswith($file)))'
				;;
			*)
				jq --arg file "$(realpath "$filepath")" 'map(select(.file == $file))'
				;;
		esac
	else
		cat
	fi
}

unixtime_now="$(date +%s)"

human_readable() {
	if [ -n "$is_json" ] ; then
		cat
		return
	fi
	jq -r '.[] | "\(.uuid | split(" ") | first) \(.unixtime) \(.description | split("\n") | first)"' | while read -r entry ; do
		uuid="$( cut -d' ' -f1 <<< "$entry" | cut -d- -f1)"
		description="$( cut -d' ' -f3- <<< "$entry" | head -n 1 )"
		timestamp="$( cut -d' ' -f2 <<< "$entry" )"
		date="$(date "+%Y-%m-%d" --date "@$timestamp")"
		if [ "$timestamp" -le "$unixtime_now" ] ; then
			date="$date (!)"
		fi
		echo "$uuid | $date | $description"
	done
}

query_json() {
	cat "$reminderdir/"* 2>/dev/null | jq --slurp -c | filter_day | filter_before | filter_after | filter_file || true
}

# arg, message
assert_set() {
	if [ -z "$1" ] ; then
		echo "$2"
		exit 1
	fi
}

case "$subcommand" in
	add)
		assert_set "$date" "Please specify a date!"
		assert_set "$description" "Please specify a description!"
		[ -z "$filepath" ] || assert_file "$filepath"
		add_entry "$date" "$filepath" "$description"
		;;
	remove)
		assert_set "$uuid" "Please specify a uuid!"
		remove_entry "$uuid"
		;;
	today)
		date="${date:-$(date "+%Y-%m-%d")}"
		query_json | human_readable
		;;
	query)
		query_json | human_readable
		;;
	get-file)
		get_file_by_uuid "$uuid"
		;;
esac

