#!/bin/sh
# SPDX-License-Identifier: AGPL-3.0-only
# Copyright 2022 Sxmo Contributors
# shellcheck disable=SC3045

# include common definitions
# shellcheck source=scripts/core/sxmo_common.sh
. sxmo_common.sh

info() {
	sxmo_log "$*"
	printf "%s\n" "$*"
}

err() {
	info "$*"
	exit 1
}

usage() {
	printf "Usage: %s number|contact [-|message]\n" "$(basename "$0")"
	exit 1
}

[ 0 -eq $# ] && usage
NUMBER="$1"

make_attachments_arg() {
	LOGDIRNUM="$1"
	MAX_SIZE="$(grep "^TotalMaxAttachmentSize" "$MMS_BASE_DIR/mms" | cut -d'=' -f2)"
	MAX_NUMBER="$(grep "^MaxAttachments" "$MMS_BASE_DIR/mms" | cut -d'=' -f2)"
	[ -z "$MAX_NUMBER" ] && MAX_NUMBER="25"
	[ -z "$MAX_SIZE" ] && MAX_SIZE="1100000"

	ATT_NUM=0
	TOTAL_SIZE=0
	while read -r ATTACHMENT; do
		[ -f "$ATTACHMENT" ] || err "Attachment ($ATTACHMENT) not found!"
		CTYPE=$(file -b --mime-type "$ATTACHMENT")
		# The 'file' command returns longer mime-types than mmsctl
		# likes, so convert those (if any) here. I have only tested mp3
		# (which needs to be converted) and jpeg (which does not).
		case "$CTYPE" in
			"audio/mpegapplication/octet-stream")
				CTYPE="audio/mpeg"
				;;
		esac

		# basic mms error checking (since mmsctl does not do it)
		ATT_NUM="$((ATT_NUM+1))"
		TOTAL_SIZE="$((TOTAL_SIZE+$(wc -c < "$ATTACHMENT")))"
		if [ "$ATT_NUM" -gt "$MAX_NUMBER" ]; then
			err "Number of attachments ($ATT_NUM) greater than MaxAttachments ($MAX_NUMBER)."
		fi
		if [ "$ATT_NUM" -ge 1 ] && [ "$TOTAL_SIZE" -gt "$MAX_SIZE" ]; then
			err "Total size of attachments ($TOTAL_SIZE) greater than TotalMaxAttachmentSize ($MAX_SIZE)."
		fi
		printf " %s '%s' -c '%s'" "-a" "$ATTACHMENT" "$CTYPE"
	done < "$SXMO_LOGDIR/$LOGDIRNUM/draft.attachments.txt"
}

# if number does not start with + assume it is a contact name, and if it isn't
# in our contacts book, then alert the user but continue anyway, e.g., one
# might send a message to "2600" or something.
if ! echo "$NUMBER" | grep -q '^+'; then
	ACTUAL_NUMBER="$(sxmo_contacts.sh --all | grep "^$NUMBER:" | cut -d':' -f2 | sed 's/^ //')"
	if [ -z "$ACTUAL_NUMBER" ]; then
		info "WARNING: $NUMBER does not look like a phone number or a contact."
	else
		NUMBER="$ACTUAL_NUMBER"
	fi
fi

if [ "-" = "$2" ]; then
	TEXT="$(cat)"
else
	shift
	[ 0 -eq $# ] && usage

	TEXT="$*"
fi

# if multiple recipients or attachment, then send via mmsctl
if [ "$(printf %s "$NUMBER" | xargs pnc find | wc -l)" -gt 1 ] || [ -f "$SXMO_LOGDIR/$NUMBER/draft.attachments.txt" ]; then

	MMS_BASE_DIR="${SXMO_MMS_BASE_DIR:-"$HOME"/.mms/modemmanager}"
	[ -d "$MMS_BASE_DIR" ] || err "MMS not configured."

	# ensure we use the correct LOGDIRNUM (e.g., if multiple recipients, sort numerically)
	NUMBER="$(printf %s "$NUMBER" | xargs pnc find | sort -u | grep . | xargs printf %s)"

	# generate mmsctl arguments
	TMPFILE="$(mktemp)" # we remove this after we attempt run mmsctl
	printf %s "$TEXT" > "$TMPFILE"

	# -a 'filename' -c 'content/type' -a 'filename2' -c 'content/type'
	[ -f "$SXMO_LOGDIR/$NUMBER/draft.attachments.txt" ] && ATTACHMENTS_ARG="$(make_attachments_arg "$NUMBER" | sed 's/^ //')"

	# -a 'tmpfile' for message content
	ATTACHMENTS_ARG="-a '$TMPFILE' $ATTACHMENTS_ARG"

	# -r +123 -r +345
	RECIPIENTS_ARG="$(printf %s "$NUMBER" | sed 's/+/ -r +/g' | sed 's/^ //')"

	# Send it to mmsd-tng via mmsctl.  We can't use dbus-send since
	# dbus-send doesn't recognize a(sss) types.
	info "mmsctl -S $RECIPIENTS_ARG $ATTACHMENTS_ARG"
	MMSCTL_RES="$(eval mmsctl -S "$RECIPIENTS_ARG" "$ATTACHMENTS_ARG")"
	MMSCTL_OK="$?"
	rm "$TMPFILE"
	[ "$MMSCTL_OK" -ne 0 ] && err "mmsctl failed with \"$MMSCTL_RES\""

	# mmsd-tng should immediately add a message of status 'draft' and then
	# after a few beats it will send it and transform that message to
	# 'sent'.
	info "Waiting for mmsd-tng to send..."
	MMS_PIPE="$(mktemp -u)"
	mkfifo "$MMS_PIPE"
	timeout 60 dbus-monitor "interface='org.ofono.mms.Message',type='signal',member='PropertyChanged'" > "$MMS_PIPE" &
	MMS_PIPE_PID="$!"
	while read -r line; do
		if printf %s "$line" | grep -q 'member=PropertyChanged'; then
			MESSAGE_PATH="$(echo "$line" | cut -d'=' -f6 | cut -d';' -f1)"
		fi
		if printf %s "$line" | grep -q "string \"sent\""; then
			SENT_SUCCESS=1
			break
		fi
	done < "$MMS_PIPE"
	rm -f "$NAMED_PIPE"
	kill "$MMS_PIPE_PID"

	[ -z "$SENT_SUCCESS" ] && err "mmsd-tng did not send the draft."

	[ -f "$SXMO_LOGDIR/$NUMBER/draft.attachments.txt" ] && rm -f "$SXMO_LOGDIR/$NUMBER/draft.attachments.txt"

	# process it just like any other mms (this will handle logging it)
	sxmo_mms.sh processmms "$MESSAGE_PATH"

	MMS_FILE="$(basename  "$MESSAGE_PATH")"
	CONTACTNAME="$(sxmo_contacts.sh --name-or-number "$NUMBER")"
	sxmo_hook_sendsms.sh "$CONTACTNAME" "$TEXT" "$MMS_FILE" "$CONTACTNAME"

	info "Sent mms text to $CONTACTNAME."

# we are dealing with a normal sms, so use mmcli
else

	TEXTSIZE="${#TEXT}"

	#mmcli doesn't appear to be able to interpret a proper escape
	#mechanism, so we'll substitute double quotes for two single quotes
	SAFE_TEXT=$(echo "$TEXT" | sed "s/\"/''/g")

	SMSNO="$(
		mmcli -m any --messaging-create-sms="text=\"$SAFE_TEXT\",number=$NUMBER" |
		grep -o "[0-9]*$"
	)"

	SMS_RES="$(mmcli -s "${SMSNO}" --send --timeout="${SXMO_MM_TIMEOUT:-"30"}" 2>&1)"
	SMS_OK="$?"

	if [ "$SMS_OK" = 1 ]; then
		# if we fail to send due to a bad number,
		# clear it from the modem
		if echo "$SMS_RES" | grep -q "Invalid number"; then
			for i in $(mmcli -m any --messaging-list-sms | grep " (unknown)" | cut -f5 -d' '); do
				mmcli -m any -s "$i" -K | grep -q "not requested" && mmcli -m any --messaging-delete-sms="$i" >/dev/null
			done
			err "Couldn't send text message: Invalid number."
		else
			err "Couldn't send text message ($SMS_RES)"
		fi
	fi

	# we sent it successfully, but also clear it from the modem
	for i in $(mmcli -m any --messaging-list-sms | grep " (sent)" | cut -f5 -d' ') ; do
		mmcli -m any --messaging-delete-sms="$i" > /dev/null
	done

	TIME="$(date +%FT%H:%M:%S%z)"
	mkdir -p "$SXMO_LOGDIR/$NUMBER"
	sxmo_hook_smslog.sh "sent" "$NUMBER" "$NUMBER" "$TIME" "$TEXT" >> "$SXMO_LOGDIR/$NUMBER/sms.txt"
	printf "%s\tsent_txt\t%s\t%s chars\n" "$TIME" "$NUMBER" "$TEXTSIZE" >> "$SXMO_LOGDIR/modemlog.tsv"

	CONTACTNAME="$(sxmo_contacts.sh --name-or-number "$NUMBER")"
	sxmo_hook_sendsms.sh "$CONTACTNAME" "$TEXT"
	info "Sent sms text to $CONTACTNAME."
fi


