#!/bin/bash
#                       /usr/local/bin/triweekly
# https://crystalfaeries.net/posix/bin/triweekly
# celeste:crystalfaery TRIWEEKLY 2021-04-27 04:50:23+00:00

# calendar is unable to utilize an "every 3 weeks" schedule...
# therefore, we assist it with this script,
# which is EXECUTED NIGHTLY by cron if always powered:
# 00	00	 *	 *	*	/usr/local/bin/triweekly
# OR if your computer isn't gonna be on all night, then HOURLY:
# 00	 *	 *	 *	*	/usr/local/bin/triweekly

# We maintain event timestamps, for which,
# if our timestamp is 21 days old,
# we notify by e-mail, and reset the timestamp,
# for three weeks from this notification, and
# we also update the invoking user's ~/.calendar/calendar

# invocation to list timestamps being tracked:
# triweekly -l				or
# triweekly --list

# invocation to initiate a new, or reset timer of existing, item(s):
# triweely alpha beta

let help=24	# line number of this line - 1

cd -P	 "${HOME}/.calendar" || exit $?		# where the timestamps live
  events="${HOME}/.calendar/triweekly.txt"	# TriWeekly events
  header="${HOME}/.calendar/header.txt"		# anything more than LANG selection?
calendar="${HOME}/.calendar/calendar"		# user's calendar
unhardlink		"${calendar}"-		# ensure separate from ~/.calendar/calendar

#	if called with arguments, those are the names of the events we are timing
#	meanwhile, what options precede those event names?
if [ "$1" == "-v" ]
then
	echo	"`ls -Flad $0`"
	head	-n 4	   $0 | tail -n 1
	exit	0
fi
if [ "$1" == "--version" ]
then
	echo	"`ls -Flad $0`"
	head	-n 4	   $0 | tail -n 1
	exit	0
fi
if [ "$1" == "-h" ]
then
	head -n $help $0
	exit	0
fi
if [ "$1" == "--help" ]
then
	head -n $help $0
	exit	0
fi
let	list=1	# false
if [ "${1}" == "-l" ]
then
	let	list=0	# true
	shift
fi
if [ "$1" == "--list" ]
then
	let	list=0	# true
	shift
fi

# Having handled all the options we know, process into calendar file

while [[ $# -gt 0 ]] 
do
	/usr/local/bin/now	 >>	 ."$1".triweekly.txt	# UTC Timestamp inside file
	shift	# we time-stamped our named event, will notify in 3 weeks
done	# have {cre,upd}ated each event named in an argument to invocation
#	now we have to enter the triweekly events into our calendar file

#	delete old TriWeekly events from Calendar
grep	'^LANG='	"${HOME}"/.calendar/calendar		> "${header}"
grep -v	'^LANG='	"${HOME}"/.calendar/calendar	|	\
grep -vi TriWeekly						> "${calendar}"-

#	append all TriWeekly events onto Calendar
    for item in ".*.triweekly.txt"
    do
	it="$(echo ${item} | sed 's/^\.//;s/\.triweekly\.txt$//')"
	echo "$(date -u --rfc-3339=date  -r ${item} | sed 's/^[0-9][0-9][0-9][0-9]-//;s/-/\//g')	TriWeekly ${it}" >> "${calendar}"-
    done

#	install newly sorted Calendar file
mv		"${header}"			"${HOME}"/.calendar/calendar
sort -n	<	"${calendar}"- | uniq >>	"${HOME}"/.calendar/calendar

if [[ $list -eq 0 ]]
then	# Just List the TimeStamps
	grep -i TriWeekly	"${HOME}"/.calendar/calendar	# What {was,is} scheduled?
else	# Check for expired Timers
    # now find any timestamp three weeks old and notify
    find . -maxdepth 1 -iname '.*.triweekly.txt' -daystart -mtime +20 | sed 's/^\.\/\.//;s/.triweekly.txt$//' \
	| sort		>	${events}

    if [ -s				${events} ]
    then	# a 3 week timer expired, therefore notify in multiple ways
	#	delete old TriWeekly events from Calendar
	grep	'LANG='		"${HOME}"/.calendar/calendar		> "${header}"
	grep -v	'LANG='		"${HOME}"/.calendar/calendar	|	\
	grep -vi TriWeekly						> "${calendar}"-

	for item in `cat	${events}`
	do #	append new TriWeekly events onto Calendar
		it="$(echo ${item} | sed 's/^\.//;s/\.triweekly\.txt$//')"
		echo "$(date -u --rfc-3339=date  -r .${item} | sed 's/^[0-9][0-9][0-9][0-9]-//g;s/-/ /g')	TriWeekly ${it}" \
		>> "${calendar}-"
		/usr/local/bin/now				 >>	.$item.triweekly.txt && \
		mail -s "TriWeekly ${it}" `/usr/bin/whoami`	 <	.$item.triweekly.txt & disown %1	# in background
	done

	#	install new Calendar file
	mv		"${header}"			"${HOME}"/.calendar/calendar
	sort -n <	"${calendar}"- | uniq >>	"${HOME}"/.calendar/calendar
    fi
fi

exit	$?	# pau
