#!/bin/bash

# version 23329

ARCH=$(uname -m)

if [ "$ARCH" != "aarch64" ]; then
	echo <<ARMW

***** WARNING - RASPBERRY PI OS (RASPBIAN) *****
Current releases of Raspbian are now 64-bit architecture. You are running on
a 32-bit OS. This may mean that future releases of Reactor will not operate
on your installed OS because updates for supporting packages are not offered
for this older OS. It is already the case that nodejs current LTS (v20) does
not run on Raspbian Buster. Please consider updating your RPi to a 64-bit OS.
See https://www.raspberrypi.com/software/

ARMW
NODEVER="18.18.2"
NODERV=1818
NODENV=1800
else
# 64-bit OS
NODEVER="20.9.0"   # if we install nodejs, this version (LTS as of 2023-11-21)
NODERV=2009        # NODEVER as MMmm (Major*100 + minor)
NODENV=1818        # minimum compatible version
fi

askyn() {
	local __ans
	local __resultvar
	__resultvar="${1:-ans}"
	while true; do
		echo -e -n "${2:-}"
		read __ans
		case "$__ans" in
			[Yy]* )
				eval "${__resultvar}=Y"
				break
				;;
			[Nn]* )
				eval "${__resultvar}=N"
				break
				;;
		esac
		echo "Please answer Y or N."
	done
}

function die {
	echo -e "$*"
	exit 255
}

function usage {
	cat <<USAGE
Usage: $0 [options]
	-N <nodejs-download-file>   Install nodejs from the package/download file given
	-a <ip-address>             Specify the IP address of this hosts's primary interface
	-S                          Install standalone (not as a daemon)
USAGE
	exit 255
}

# Pre-flight checks.
[ $(id -u) -eq 0 ] && die "Please do not run this script under 'sudo' or as root.";
[ ! -f "/etc/debian_version" ] && die "This script is intended to run on Raspbian/Debian 10 and 11 only";
[ ! -f "tools/rpi-install.sh" ] && die "Please run this script from your Reactor install directory";
[ ! -d "./server/lib" ] && die "Please run this script from your Reactor install directory";

MEM=$( fgrep MemTotal /proc/meminfo | awk '{ print $2; }' )
MEM=$(( $MEM / 1024 ))
[ $MEM -le 1500 ] && {
	echo "***********************************************************************"
	echo "* WARNING: The system RAM configuration is below the recommended 2GB. *"
	echo "***********************************************************************"
	echo ""
}

instnode=""
ipaddr=""
use_systemd="Y"
while getopts "N:a:Sh" arg; do
	case ${arg} in
		N)
			instnode="$OPTARG"
			;;
		a)
			ipaddr="$OPTARG"
			;;
		S)
			use_systemd="N"
			;;
		h)
			usage
			;;
		?)
			echo "Invalid option ${arg}"
			usage
			;;
	esac
done

# Figure out the node situation.
doinst=1
nodeexec="$( which node )"
if which node >/dev/null; then
	if [ -n "$instnode" ]; then
		echo "You specified a nodejs package on the command line: ${instnode}"
		echo "This version will be installed for the local user (only)."
	else
		nodever=$(node -v)
		nv=${nodever:1}
		xv=$( echo $nv | cut -d . -f 2 )
		nv=${nv/.*/}
		zv=$(( $nv * 100 + $xv ))
		# echo "Found nodejs $nv . $xv ($zv) at $(which node)"
		if [ $zv -ge $NODERV ]; then
			echo "The version of nodejs currently installed is ${nodever} (compatible)."
			doinst=0
		elif [ $zv -ge $NODENV ]; then
			echo "The version of nodejs currently installed ${nodever} is below the recommended"
			echo "version ${NODEVER}, but it is believed to be compatible."
			askyn ans "Do you want me to install a local upgrade of ${NODEVER} for this user only? "
			if [ "$ans" == "N" ]; then
				doinst=0
			fi
		else
			echo "The version of nodejs currently installed ${nodever} is not compatible with Reactor."
			askyn ans "Do you want me to install the recommended version ($NODEVER) locally (for this user only)? "
			if [ "$ans" == "N" ]; then
				echo "OK. Please install a compatible version of nodejs manually."
				exit 1
			fi
		fi
	fi
elif [ -z "$instnode" ]; then
	echo "Nodejs does not appear to be installed, or is not in your PATH."
fi
NODEPKG=""
if [ $doinst -ne 0 ]; then
	if [ -z "$instnode" ]; then
		if [ "$ARCH" == "aarch64" ]; then
			NODEPKG="node-v${NODEVER}-linux-arm64.tar.xz"
		else
			NODEPKG="node-v${NODEVER}-linux-armv7l.tar.xz"
		fi
		echo "I can download a compatible version (v${NODEVER}) and install it locally"
		echo "(for this user account only -- not system-wide)."
		askyn ans "Do you want me to download and install ${NODEPKG} now? "
		if [ "$ans" == "Y" ]; then
			instnode=/tmp/${NODEPKG}
			curl -L -o "${instnode}" "https://nodejs.org/dist/v${NODEVER}/${NODEPKG}" || die "The download failed; please try again or download/install node manually.";
		else
			die "OK. Download a version you like better, and re-run: $0 -N <path-to-nodejs-download>"
		fi
	fi
fi

while [ -z "$ipaddr" ]; do
	echo ""
	echo "Please choose the primary IP address used by this system:"
	ips=""
	ix=0
	for l in $(ip -o addr | grep -v '127.0.0.' | awk '/inet4? / { print $2 ":" $4 }'); do
		interface=$(echo $l | awk -F: '{ print $1 }')
		ip=$(echo $l | awk -F: '{ print $2 }' | sed 's/\/.*//')
		ix=$(expr $ix + 1)
		echo "    $ix. ${ip} (${interface})"
		ips[$ix]=$ip
	done
	echo -n "Enter 1-${ix}: "
	read ans
	if [ "${ans:-0}" -ge 1 -a ${ans:-0} -le $ix ]; then
		ipaddr="${ips[$ans]}"
		echo "OK. I will configure the Reactor UI for http://${ipaddr}:8111/"
		break
	fi
done

if [ ! -f /etc/systemd/system/reactor.service ]; then
	if [ -z "$use_systemd" ]; then
		echo ""
		echo "You can install Reactor as a systemd service that starts automatically at"
		echo "boot time and restarts itself if it exits. This is recommended."
		askyn ans "Install Reactor under systemd? "
		use_systemd="${ans}"
	fi
else
	use_systemd=""
fi

# Start the installation.
echo ""
umask 022

if [ -n "$instnode" ]; then
	version=$(basename $instnode)
	dir=${version/.tar.xz/}

	echo "Creating local nodejs installation in ${HOME}/.local"
	mkdir -p $HOME/.local/lib/nodejs
	echo -n "Unpacking nodejs archive... this takes a moment... "
	tar -xJf ${instnode} -C $HOME/.local/lib/nodejs || die "Can't read archive ${instnode}"
	echo ""

	echo "Adding local nodejs to search path (via ${HOME}/.profile)"
	sed -i '/^export PATH=\${HOME}\/\.local\/lib\/nodejs\/.*/d' ${HOME}/.profile
	cat <<EOF >>${HOME}/.profile
export PATH=\${HOME}/.local/lib/nodejs/${dir}/bin:\$PATH
EOF
	nodeexec="${HOME}/.local/lib/nodejs/${dir}/bin/node"
	PATH="$(dirname ${nodeexec}):${PATH}"
fi

# Install package dependencies using script provided in package.json
echo "Checking package dependencies; this may take a minute or two..."
npm run deps

mkdir -p ./config
for d in ./dist-config/*.yaml ; do
	F=$(basename $d)
	if [ ! -f "./config/$F" ]; then
		cp -p $d ./config/
	fi
done
sed -i "/^ \+baseurl:/s|baseurl:.*|baseurl: 'http://${ipaddr}:8111'|" ./config/reactor.yaml

mkdir storage 2>/dev/null
chmod -R u+rwX,o= ./config ./storage
chmod 700 app.sh

cat <<SYSTEMD >tools/reactor.service
# This file allows you to run your Reactor installation under systemd,
# so it can be started at boot. Copy this file (as root or under sudo)
# to /etc/systemd/system, and then run "systemctl daemon-reload". You
# can then able Reactor to start at boot "systemctl enable reactor".
# The usual systemctl subcommands can also be used to start, stop, and
# restart reactor at will (e.g. "systemctl restart reactor").

[Unit]
Description=Multi-Hub Reactor
After=network.target

[Service]
Type=simple
User=${USER}
WorkingDirectory=$( pwd )
Environment=NODE_PATH=$( pwd )
ExecStart=${nodeexec} app -p
Restart=on-failure
RestartSec=5s

[Install]
WantedBy=multi-user.target
SYSTEMD

if [ "${use_systemd}" == "Y" ]; then
	echo "Installing Reactor under systemd. You may be asked for your password, because"
	echo "these steps need to be done with elevated permissions (via sudo)."
	sudo install -m 0644 -o root -g root tools/reactor.service /etc/systemd/system/
	sudo systemctl -q daemon-reload
	sudo systemctl -q enable reactor 2>/dev/null
	echo "Starting Reactor daemon. To restart Reactor (such as after making configuration"
	echo "changes), use the 'Restart' button in the Tools menu, or run this command:"
	echo ""
	echo "    sudo systemctl restart reactor"
	sudo systemctl restart reactor
elif [ -f "/etc/systemd/system/reactor.service" -a -n "${nodeexec}" ]; then
	echo "Restarting Reactor service... you may be asked for your password (sudo)."
	sudo sed -i "/^ExecStart=/ c ExecStart=${nodeexec} app -p" /etc/systemd/system/reactor.service
	sudo systemctl -q daemon-reload
	sudo systemctl -q restart reactor
fi

echo ""
echo "OK. Now please LOG OUT, then log back in and continue the installation procedure"
echo "(see https://reactor.toggledbits.com/docs/Installation/)."

exit 0
