#!/bin/sh

# Created by jiaqiang.ye@lnxall.com
# Simpile firmware upgrade for LNXALL packages
# 2023/07/18

TAGINST=/tmp/.elf-pkg-installed
export PATH=/opt/lnxall_app/bin:/usr/local/bin:/usr/bin:/usr/sbin:/bin:/sbin

FWFILE=''
KEEP_CFGS=1
WAN_MACADDR="$(uci get network.wan.macaddr 2>/dev/null)"

check_system() {
	if [ "$(uname -m)" != "x86_64" ] ; then
		echo "Error, not x86_64 gateway, cannot install lnxall_app" 1>&2
		return 1
	fi

	return 0
}

check_args() {
	FWFILE="$1"
	if [ "${FWFILE}" = "-n" ] ; then
		KEEP_CFGS=0
		FWFILE="$2"
	fi

	[ "${FWFILE}" = "/dev/NULL" ] && return 0
	if [ -z "${FWFILE}" ] ; then
		echo "Error, Lnxall package firmware not specified" 1>&2
		return 1
	fi

	if [ ! -f "${FWFILE}" ] ; then
		echo "Error, Lnxall package firmware not found: '${FWFILE}'" 1>&2
		return 2
	fi
	return 0
}

check_md5sum() {
	local file="$1"
	local md5="$2"

	[ "$file" = "/dev/NULL" ] && return 0
	if [ -z "${md5}" ] ; then
		echo "Error, expected MD5SUM not specified for '${file}'" 1>&2
		return 1
	fi

	local md5val="$(md5sum ${file} 2>/dev/null | awk '{print $1}')"
	if [ "${md5val}" != "${md5}" ] ; then
		echo "Error, invalid MD5SUM: '${md5val}', expected: '${md5}'" 1>&2
		return 2
	fi

	echo "LNXALL package upgrade firmware MD5SUM check OK."
	return 0
}

# intermediate variable for function `get_md5sum
MD5SUM_VAL=''
get_md5sum() {
	local file="$1"
	if [ ! -f "${file}" ] ; then
		MD5SUM_VAL=''
		return 1
	fi

	local md5val="$(md5sum ${file} 2>/dev/null | awk '{print $1}')"
	if [ -z "${md5val}" ] ; then
		MD5SUM_VAL=''
		return 2
	fi
	MD5SUM_VAL="${md5val}"
	return 0
}

inst_systemd() {
	local svrname="$1"
	local destdir="/usr/lib/systemd/system"

	get_md5sum "platspec/${svrname}"
	local md5_0="${MD5SUM_VAL}"
	if [ -z "${md5_0}" ] ; then
		echo "Installing '${svrname}'..."
		cp -v -f "platspec/${svrname}" "${destdir}/${svrname}" && \
			systemctl enable "${svrname}" && systemctl start "${svrname}"
		return $?
	fi

	get_md5sum "${destdir}/${svrname}"
	local md5_1="${MD5SUM_VAL}"
	if [ "${md5_0}" != "${md5_1}" ] ; then
		echo "Installing '${svrname}'..."
		if cp -v -f "platspec/${svrname}" "${destdir}/" ; then
			systemctl daemon-reload
			systemctl enable "${svrname}"
			systemctl start "${svrname}"
		fi
	fi
	return 0
}

post_install() {
	local profile='/root/.profile'
	if [ ! -f "${profile}" ] ; then
		rm -rf "${profile}"
		# create ${profile}
		echo '#!/bin/sh' > "${profile}"
	fi

	local APPDIR='/opt/lnxall_app'
	local BATH='/usr/local/bin:/usr/bin:/usr/sbin:/bin:/sbin'
	# setup new PATH environment variable
	export PATH="${APPDIR}/bin:${APPDIR}/sbin:${BATH}"

	# update ${profile} if necessary
	if [ -z "$(grep -e ${APPDIR} ${profile})" ] ; then
		echo "Updating '${profile}'..."
		echo "export PATH=${PATH}" >> "${profile}"
	fi

	cd "${APPDIR}" || return 1
	# install XXX.service for systemd based system
	inst_systemd 'linit.service'

	sync # OK, flush filesystem before return
	return 0
}

fw_install() {
	local fw_file="$1"
	mkdir -p /opt && cd /opt
	[ $? -ne 0 ] && return 1
	touch ${TAGINST}

	# create /usr/lib/systemd/system directory
	mkdir -p /usr/lib/systemd/system

	# stop Lnxall INITialize service, twice
	echo "Stopping Lnxall services..."
	systemctl stop linit.service >/dev/null 2>/dev/null ; sleep 1
	systemctl stop linit.service >/dev/null 2>/dev/null

	local backups='lnxall_backup.tar'
	rm -rf ${backups} # remove backup settings
	if [ ${KEEP_CFGS} -eq 1 ] ; then
		echo "Backing up lnxall configs..."
		local KEEPDIRS='lnxall_app/app/config' # /app/config always exists
		[ -e 'lnxall_app/app/node' ] && KEEPDIRS="${KEEPDIRS} lnxall_app/app/node"
		[ -e 'lnxall_app/app/temp' ] && KEEPDIRS="${KEEPDIRS} lnxall_app/app/temp"
		[ -e 'lnxall_app/app/adapter' ] && KEEPDIRS="${KEEPDIRS} lnxall_app/app/adapter"
		[ -e 'lnxall_app/app/global/template' ] && KEEPDIRS="${KEEPDIRS} lnxall_app/app/global/template"
		[ -e 'lnxall_app/app/global/alarminfo' ] && KEEPDIRS="${KEEPDIRS} lnxall_app/app/global/alarminfo"
		[ -e 'lnxall_app/app/template' ] && [ ! -L 'lnxall_app/app/template' ] && KEEPDIRS="${KEEPDIRS} lnxall_app/app/template"
		[ -e 'lnxall_app/etc/config' ] && KEEPDIRS="${KEEPDIRS} lnxall_app/etc/config"
		[ -e 'lnxall_app/lib/dyiot/appdis' ] && KEEPDIRS="${KEEPDIRS} lnxall_app/lib/dyiot/appdis"
		[ -d 'lnxall_app' ] && tar -cvf "${backups}" ${KEEPDIRS}

		# NOTE: in /opt directory, backup database directory:
		rm -rf db_backup
		if [ -e 'lnxall_app/app/database' ] ; then
			mv -f 'lnxall_app/app/database' db_backup
		fi
	fi

	# create temporary directory and extract everything in it
	rm -rf .tmpextract/*
	mkdir -p .tmpextract
	cd .tmpextract || return 2
	if [ "${fw_file}" = "/dev/NULL" ] ; then
		echo "Extracting from ELF file ..."
		FWLNX_DUMPOUT=STDOUT "${FWLNX_ELFILE}" | xz -d -c | tar -x -f -
	else
		echo "Extracting from lnxall package '${fw_file}'..."
		cat "${fw_file}" | xz -d -c | tar -x -f - # extract only once
	fi
	if [ $? -ne 0 ] ; then
		rm -rf ./* ; cd ..
		echo "Error, failed to extract \"${fw_file}\"" | tee -a ${TAGINST}
		return 3
	fi

	echo "$(date): lnxall_app extracted" | tee -a ${TAGINST}
	# remove /opt/lnxall_app
	rm -rf ../lnxall_app
	rm -rf ../lnxall_app # remove twice
	mv -v -f * ../
	cd .. # go back to upper directory

	rm -rf "${fw_file}" # remove extracted firmware
	if [ ${KEEP_CFGS} -eq 1 ] ; then
		echo "Restoring backups..."
		[ -e "${backups}" ] && tar -x -v -f "${backups}"
		if [ -d 'db_backup' ] ; then
			mkdir -p lnxall_app/app/database
			mv -f db_backup/* lnxall_app/app/database/
		fi
		rm -rf "${backups}" db_backup
	fi

	sync ; post_install
	# Blink LED if no GWSN found:
	nothup lua /opt/lnxall_app/bin/elf-update-blink-no-gwsn.lua
	echo "Restarting Lnxall services..."
	systemctl restart linit.service
	
	return $?
}

umask 022
check_system || exit 1
check_args "$@" || exit 2
check_md5sum "${FWFILE}" "${FW_MD5SUM}" || exit 3
fw_install "${FWFILE}"
exit $?
