if [ -e ~/.config_comb ];then
	. ~/.config_comb
fi;

get_version() {
	if [ ! -d ${FW_PATH} ];then
		echo "Firmware path not found"
		return 1;
	fi;

	APP_VER=$((ssh -p ${2} ${SSH_OPTS} root@${1} "/legato/systems/current/bin/app info combapp" |awk '/app.version/ {print $2}') 2>/dev/null)
	VER=$((ssh -p ${2} ${SSH_OPTS} root@${1} "if [ \"\$(uname -n |cut -d- -f1)\" != \"raspberrypi\" ];then \
			/legato/systems/current/bin/cm info; \
		else \
			 awk -F: '/^Model/ {printf \"%-30s%s\r\n\", \"Device:\", \$2}' /proc/cpuinfo;\
		fi" |awk '/Device:/ {print $2}' |tr '-' '_') 2>/dev/null)
	ROOTFS_VER="$((ssh -p ${2} ${SSH_OPTS} root@${1} "/bin/cat /etc/rootfsver.txt" |awk '{print $1}' |tr '.' '_') 2>/dev/null)"

	case ${VER} in
		"WP7607_1")
			COMB_VER="3.6"
			CPU_VER="wp76xx"
			;;
		"WP8548")
			COMB_VER="3.5"
			CPU_VER="wp85"
			;;
		"Raspberry")
			return 0
			;;
		*)
			return 1
			;;
	esac;

	if [ "${APP_VER}" ] && [ "$(echo ${APP_VER} |cut -d. -f1,2)" != "${COMB_VER}" ];then
		APP_VER="";
	fi;

	FW=${FW_PATH}/factory-${CPU_VER}.spk
	FW_VER=${FW_PATH}/factory-${CPU_VER}.ver

	FW_RESET=${FW_PATH}/reset-${CPU_VER}.cwe

	FW_UPDATE=${FW_PATH}/update-${CPU_VER}-${ROOTFS_VER}.spk
	FW_UPDATE_VER=${FW_PATH}/update-${CPU_VER}-${ROOTFS_VER}.ver

	DEF_MAJ=$(cat ${FW_VER} |cut -d. -f3)
	DEF_MIN=$(cat ${FW_VER} |cut -d. -f4)
	if [ -e ${FW_UPDATE_VER} ];then
		SYS_FW_MAJ=$(awk -F. '{printf "%s",$3}' ${FW_UPDATE_VER})
		SYS_FW_MIN=$(awk -F. '{printf "%s",$4}' ${FW_UPDATE_VER})
		SYS_FW=${SYS_FW_MAJ}.${SYS_FW_MIN}
	fi;

	return 0
}

check_fw_is_upgrade() {
	if [ ! "${1}" ] || [ ! "${2}" ];then
		return 1
	fi;

	if [ $(echo ${2} |cut -d. -f3) -lt $(echo ${1} |cut -d. -f3) ];then
		return 1
	elif [ $(echo ${2} |cut -d. -f3) -eq $(echo ${1} |cut -d. -f3) ];then
		if [ $(echo ${2} |cut -d. -f4) -lt $(echo ${1} |cut -d. -f4) ];then
			return 1;
		fi;

		if [ $(echo ${2} |cut -d. -f5) -lt $(echo ${1} |cut -d. -f5) ];then
			return 1;
		fi;

		if [ $(echo ${2} |cut -d. -f6) -lt $(echo ${1} |cut -d. -f6) ];then
			return 1;
		fi;

		if [ $(echo ${2} |cut -d. -f7) -le $(echo ${1} |cut -d. -f7) ];then
			return 1;
		fi;
	fi

	return 0;
}

fw_is_upgrade() {
	if [ "${APP_VER}"] && ! check_fw_is_upgrade ${APP_VER} $(cat ${FW_VER});then
		return 1;
	fi;
	return 0;
}

update_is_upgrade() {
	if [ "${APP_VER}" ] && ! check_fw_is_upgrade ${APP_VER} $(cat ${FW_UPDATE_VER});then
		return 1;
	fi;
	return 0;
}

get_latest() {
	if [ "${3}" ];then
		CUR_APP=${3}
	else
		CUR_APP=""
	fi;

	if [ "${2}" ];then
		NEW_FW=${2}
	fi;

	if [ ! "${NEW_FW}" ];then
		if [ ${DEF_MAJ} -gt ${SYS_FW_MAJ} ];then
			NEW_FW=${DEF_MAJ}
		else
			NEW_FW=${SYS_FW}
		fi
	fi;

	NEW_FW_MAJ=$(echo ${NEW_FW}. |cut -d. -f1)
	NEW_FW_MIN=$(echo ${NEW_FW}. |cut -d. -f2)

	#If only the maj version is set not minor and majors are same basically ignore
	if [ ! "${NEW_FW_MIN}" ] && [ "${NEW_FW_MAJ}" == "${SYS_FW_MAJ}" ];then
		NEW_FW=${SYS_FW}
		NEW_FW_MAJ=${SYS_FW_MAJ}
		NEW_FW_MIN=${SYS_FW_MIN}
	fi;

	if [ "${SYS_FW}" == "${NEW_FW}" ];then
		FW_UPDATE_TYPE="legato";
	elif [ "${NEW_FW_MIN}" ] && [ "${SYS_FW_MAJ}" == "${NEW_FW_MAJ}" ] && [ "${SYS_FW_MIN}" != "${NEW_FW_MIN}" ];then
		FW_UPDATE_TYPE="rootfs";
	else
		FW_UPDATE_TYPE="full";
	fi

	if [ ! "${NEW_FW_MIN}" ];then
		NEW_FW=${NEW_FW_MAJ}.'*'
	fi;

	FW_ROOT=${1}/${CPU_VER}/comb-firmware-${CPU_VER}-
	UPDATE_VER=$((ls ${FW_ROOT}${COMB_VER}.${NEW_FW}.${CUR_APP}*/comb-${FW_UPDATE_TYPE}*.spk |sort -n |tail -1 |awk -F- '{printf "%s",substr($NF,1,length($NF)-4)}') 2>/dev/null)

	if [ "${APP_VER}" ] && [ "${UPDATE_VER}" ];then
		if [ "${APP_VER}" == "${UPDATE_VER}" ];then
			echo "Update not required"
			return 0
		fi;
		if ! check_fw_is_upgrade ${APP_VER} ${UPDATE_VER};then
			echo "Downgrade not available"
			return 0
		fi;
	fi;

	FW_FILE=${FW_ROOT}${UPDATE_VER}/comb-${FW_UPDATE_TYPE}-${CPU_VER}-${UPDATE_VER}.spk

	if [ ! "${FW_FILE}" ] || [ ! -e ${FW_FILE} ];then
		return 1;
	fi;
	return 0
}

load_firmware() {
	if [ ! "${1}" ] || [ ! -e "${1}" ];then
		echo "Firmware file does not exist"
		return 1;
	fi;

	echo "Loading Firmware File $(basename ${1})"
	if ! dd if=${1} |ssh -p ${3} ${SSH_OPTS} root@${2} "/legato/systems/current/bin/fwupdate downloadOnly -";then
		return 1
	fi;

	ssh -f -n -p ${3} ${SSH_OPTS} root@${2} "if [ -e combapp.db ];then /usr/bin/sqlite3 combapp.db \"update organisationsetup set value='0' where key = 'orgID' AND idx = -1\";fi; \
						 /legato/systems/current/bin/fwupdate install"
	return $?
}

check_firmware() {
	echo "Checking Firmware"
	ssh ${SSH_OPTS} root@${ECM_ADDR} "/bin/ls /legato/systems/current/apps/combapp" > /dev/null 2>&1
	return $?
}

setup_resolv_conf() {
	if ! ssh ${SSH_OPTS} root@${ECM_ADDR} "if [ ! -e /etc/resolv.conf ] || [ ! -s /etc/resolv.conf ];then /bin/echo \"nameserver ${DNS}\" > /etc/resolv.conf;exit 1;fi" > /dev/null 2>&1;then
		echo "Setup Resolv.conf"
	else
		echo "Resolv.conf exists"
	fi
}

add_ecm_route() {
	echo "Set up route"
	ssh ${SSH_OPTS} root@${ECM_ADDR} "/sbin/ip route del default metric 0;/sbin/ip route add default via ${1} metric 0" > /dev/null 2>&1
	return $?
}

setup_network() {
	#Setup routing via ECM
	setup_resolv_conf

	if ! add_ecm_route ${1};then
		echo "Route failed/exits"
	fi;
}

dnf_update() {
	if ! ssh ${SSH_OPTS} -p ${2} root@${1} \
		"ulimit -s unlimited; \
		 if ! /usr/bin/dnf --refresh check-update;then \
		 echo '(/usr/bin/dnf -y --exclude kernel-* --exclude legato* update;dnf -y --exclude kernel-* update) && /usr/bin/comb-ns-update --fix;\
		 /sbin/reboot' |/usr/bin/at now;fi" 2>/dev/null;then
		return $?
	fi;

	return 0
}

system_info() {
	if ! ssh ${SSH_OPTS} -p ${2} root@${1} \
		"echo System info;
		 if [ \"\$(uname -n |cut -d- -f1)\" != \"raspberrypi\" ];then /legato/systems/current/bin/cm info;else \
		 awk -F: '/^Model/ {printf \"%-30s%s\r\n\", \"Device:\", \$2}' /proc/cpuinfo;\
		 awk -F: '/^Serial/ {printf \"%-30s%s\r\n\", \"FSN:\", \$2}' /proc/cpuinfo;fi; \
		 if [ -e /tmp/deviceid.txt ];then printf '%-31s%s\r\n' 'DEVID:' \$(/bin/cat /tmp/deviceid.txt);fi; echo;\
		 if [ -e /etc/lsb-release ];then echo "LSB Info";lsb_release -a;echo;fi; \
		 echo Linux info;/bin/uname -a;echo; \
		 echo Legato info;/legato/systems/current/bin/legato version;echo; \
		 if [ -e /etc/rootfsver.txt ];then echo Root FS info;/bin/cat /etc/rootfsver.txt;echo;fi; \
		 echo Comb App info;/legato/systems/current/bin/app info combapp;echo" 2>/dev/null;then
		return $?
	fi;

	return 0
}

ssh_connect() {
	if [ "${LOCAL_PORT}" ];then
		SSH_OPTS="${SSH_OPTS} -L *:${LOCAL_PORT}:${ECM_ADDR}:22"
	fi;

	ssh ${SSH_OPTS} -p ${2} root@${1}
}

setup_portforward() {
	if [ "${LOCAL_PORT}" ];then
		SSH_OPTS="${SSH_OPTS} -L *:${LOCAL_PORT}:${ECM_ADDR}:22"
	fi;


	ssh -f -N ${SSH_OPTS} root@${ECM_ADDR} > /dev/null 2>&1
}


ssh_test() {
	for test in 1 2 3 4 5 6 7 8 9 10;do
		if ssh ${SSH_TEST_OPTS} -p ${2} root@${1} /bin/true > /dev/null 2>&1;then
			test=0;
			break;
		fi;
		sleep 3
	done

	return ${test}
}

ssh_agent_start() {
	SA_FILE=/tmp/comb-${UID}-ssh-agent

	if [ "${SSH_KEY}" ];then
		SSH_OPTS="-i ${SSH_KEY} ${SSH_OPTS}"
	fi;

	SSH_TEST_OPTS="${SSH_OPTS} -oConnectTimeout=5 -oNumberOfPasswordPrompts=${ASK_TEST_PW}"
	SSH_OPTS="${SSH_OPTS} -oConnectTimeout=30 -oNumberOfPasswordPrompts=${ASK_PW}"

	if [ -e ${SA_FILE} ];then
		. ${SA_FILE} >/dev/null
	fi;

	if [ ! -e ${SA_FILE} ] || [ ! "${SSH_AGENT_PID}" ] || ! ps -p ${SSH_AGENT_PID} > /dev/null;then
		if [ -e ${SA_FILE} ];then
			rm ${SA_FILE}
		fi;
		touch ${SA_FILE}
		chmod 600 ${SA_FILE}
		ssh-agent -s >> ${SA_FILE}
		. ${SA_FILE} >/dev/null
	fi;

	if [ "${ASK_PW}" != "0" ];then
		ssh_agent_add_key >/dev/null
	fi;
}

ssh_agent_add_key() {
	if [ -e ${SSH_KEY} ] && ! (ssh-add -l | grep ${SSH_KEY}) >/dev/null 2>&1;then
		ssh-add ${SSH_KEY}
	fi;
}

mount_sys() {
	for sysdir in dev proc sys;do
		if [ ! -d ${1}/${sysdir} ];then
			mkdir ${1}/${sysdir}
		fi;
		mount --bind /${sysdir} ${1}/${sysdir}
	done;

	if [ ! -d ${1}/var/volatile ];then
		mkdir -p ${1}/var/volatile
	fi;
	mount -t tmpfs none ${1}/var/volatile/
	for voldir in tmp log;do
		if [ ! -d ${1}/var/volatile/${voldir} ];then
			mkdir ${1}/var/volatile/${voldir}
		fi;
	done
}

umount_image(){
	if [ ! -e /dev/comb-ns-root ];then
		echo "Not mounted"
		return 1
	fi;

	if [ ! -d ${1} ];then
		echo "Directory missing"
		return 1
	fi;

	umount_sys ${1}

	losetup -d /dev/comb-ns-root
	rm /dev/comb-ns-root
}

mount_image() {
	if [ -e /dev/comb-ns-root ];then
		echo "Already mounted"
		return 0
	fi;

	if ! check_ns_image ${1}.img;then
		echo "Image not found"
		return 1
	fi;

	if [ ! -d ${1} ] && [ -e ${1}.img ];then
		mkdir ${1}
	fi;

	LOOP=$(losetup -f)
	ln -s ${LOOP} /dev/comb-ns-root

	losetup -P ${LOOP} ${1}.img
	e2fsck -C 0 -fy ${LOOP}p2
	fsck.fat -a ${LOOP}p1
	mount ${LOOP}p2 ${1}
	mount ${LOOP}p1 ${1}/boot
	mount_sys ${1}
}

create_ns_image() {
	if [ ! "${1}" ];then
		echo "No output image specified"
		return 1
	elif [ ! "${2}" ] || [ ! -e ${2} ];then
		echo "Img tar file does not exist"
		return 1
	elif [ ${1} -nt ${2} ];then
		echo "Image exists and older"
		return 0
	fi;

	MNTDIR=$(mktemp -d -p ~ tmpmnt-XXXXXXXXX)

	if [ ! "${MNTDIR}" ];then
		echo "Cannot create mount"
		return 1
	fi;

	dd status=progress if=/dev/zero of=${1} bs=1M count=1536
	parted -s ${1} mklabel msdos mkpart primary fat32 1M 100M mkpart primary ext4 100M 100%

	LOOP=$(losetup -P -f --show ${1})
	if [ ! "${LOOP}" ];then
		echo "Could not allocate loop device"
		rm -rf ${MNTDIR}
		rm ${1}
		return 1
	fi;

	mkfs.vfat ${LOOP}p1 -n BOOT
	mkfs.ext4 ${LOOP}p2 -L ROOT

	mount ${LOOP}p2 ${MNTDIR}
	mkdir ${MNTDIR}/boot
	mount ${LOOP}p1 ${MNTDIR}/boot

	tar -C ${MNTDIR} -xf ${2}

	umount ${MNTDIR}/boot ${MNTDIR}
	rm -rf ${MNTDIR}
	losetup -d ${LOOP}
}

unpack_ns_image() {
	if [ -e ${1} ];then
		echo "Image exists"
		return 1;
	fi;

	if [ -e ${1}.pack ] && [ -e ${1}.pack.xz ] && [ ${1}.pack.xz -nt ${1}.pack ];then
		rm ${1}.pack
		xz -d -k ${1}.pack.xz --verbose
	elif [ -e ${1}.pack.xz ] && [ ${1}.pack.xz -nt ${1}.pack ];then
		xz -d -k ${1}.pack.xz --verbose
	fi;

	if [ ! -e ${1}.pack ];then
		echo "No packed image found"
		return 1
	fi;

	dd status=progress if=/dev/zero of=${1} bs=1M count=1536
	LOOP=$(losetup -f -P --show ${1})

	parted -s ${LOOP} mklabel msdos mkpart primary fat32 1M 100M mkpart primary ext4 100M 100%

	mkfs.vfat ${LOOP}p1 -n BOOT
	dd conv=notrunc,nocreat if=${1}.pack status=progress bs=1M skip=1 count=94 of=${LOOP}p1

	mkfs.ext4 ${LOOP}p2 -L ROOT
	e2image -pra -o 99614720 ${1}.pack ${LOOP}p2

	echo "Checking File System"
	fsck.fat -a ${LOOP}p1
	e2fsck -C 0 -fy ${LOOP}p2
	echo "Expanding File System"
	resize2fs ${LOOP}p2
	losetup -d ${LOOP}
}

check_ns_image() {
	if [ ! "${1}" ];then
		return 1;
	elif [ -e ${1} ];then
		return 0;
	elif [ -e ${1}.pack ] || [ -e ${1}.pack.xz ];then
		unpack_ns_image ${1}
	elif [ "${2}" ] && [ -e ${2} ];then
		create_ns_image ${1} ${2}
	else
		return 1;
	fi;
}

pack_ns_image() {
	if ! check_ns_image ${1};then
		echo "Image not found"
		return 1;
	fi;

	if [ -e ${1}.pack ] && [ ${1}.pack -nt ${1} ];then
		echo "Already packed"
		return 0;
	fi;


	LOOP=$(losetup -f -P --show ${1})
	fsck.fat -a ${LOOP}p1
	e2fsck -C 0 -fy ${LOOP}p2
	resize2fs -p -M ${LOOP}p2
	e2fsck -C 0 -fy ${LOOP}p2
	resize2fs -p -M ${LOOP}p2
	e2fsck -C 0 -fy ${LOOP}p2
	resize2fs -p -M ${LOOP}p2
	e2image -pra -O 99614720 ${LOOP}p2 ${1}.pack
	resize2fs -p ${LOOP}p2
	losetup -d ${LOOP}

	dd status=progress conv=nocreat,notrunc if=${1} bs=1M count=95 of=${1}.pack
	dd status=progress conv=nocreat,notrunc oflag=append if=/dev/zero bs=1M count=1 of=${1}.pack
	LOOP=$(losetup -f -P --show ${1}.pack)

	parted -s ${LOOP} mklabel msdos mkpart primary fat32 1M 100M mkpart primary ext4 100M 100%
	fsck.fat -a ${LOOP}p1
	e2fsck -C 0 -fy ${LOOP}p2
	resize2fs -p ${LOOP}p2

	losetup -d ${LOOP}
}

xz_pack_ns_image() {
	if [ ! "${1}" ] || [ ! -e ${1}.pack ];then
		echo "Image not found"
		return 1;
	fi;

	if [ -e ${1}.pack.xz ] && [ ${1}.pack.xz -nt ${1}.pack ];then
		echo "Already compressed"
		return 0;
	fi;

	if [ ! -e ${1}.pack.xz ] || [ ${1}.pack -nt ${1}.pack.xz ];then
		if [ -e ${1}.pack.xz ];then
			rm ${1}.pack.xz
		fi;
		xz -T 0 -k --verbose ${1}.pack
	fi;
}

mount_combo_image() {
	if [ -e /dev/comb-ns-root ];then
		echo "Already mounted"
		return 0
	fi;

	if [ ! -d ${1} ] && [ -e ${1}.img ];then
		mkdir ${1}
	elif [ ! -e ${1}.img ];then
		echo "Image not found"
		return 1
	fi;

	LOOP=$(losetup -f)
	ln -s ${LOOP} /dev/comb-ns-root

	losetup ${LOOP} ${1}.img
	e2fsck -C 0 -fy ${LOOP}
	mount ${LOOP} ${1}
	mount -t tmpfs none ${1}/boot
	mount_sys ${1}
}

umount_sys(){
	for sysdir in /dev /proc /sys /var/volatile /boot /;do
		umount ${1}${sysdir}
	done;
}


flash_ns_board() {
	if [ ! -d ${FW_PATH} ];then
		echo "Firmware path not found"
		return 1;
	fi;

	echo "Updating bootloader"

	if [ -d ${FW_PATH}/raspi-cm4-64/recovery ];then
		rpiboot -d ${FW_PATH}/raspi-cm4-64/recovery
	elif [ -d /usr/share/rpiboot/recovery ];then
		rpiboot -d /usr/share/rpiboot/recovery
	fi;

	if [ "$?" == "0" ];then
		echo "Repower board"
		sleep 5
	fi;

	rpiboot
	echo "Waiting For Flash"
	sleep 10
	for FLASH in /dev/sd?;do
		continue;
	done;

	if [ ! "${FLASH}" ] || [ ! -b "${FLASH}" ];then
		echo "Block device does not exit"
		return 1;
	fi

	echo "Sending flash image"
	if [ -e ${FW_PATH}/raspi-cm4-64/comb-ns.img ];then
		FW_FILE=${FW_PATH}/raspi-cm4-64/comb-ns.img
	elif [ -e ~/comb-ns.img ];then
		FW_FILE=~/comb-ns.img
	fi;
	if [ -e ${FW_FILE} ] && [ ! -e ${FW_FILE}.pack ];then
		pack_ns_image ${FW_FILE}
	elif [ -e ${FW_FILE} ] && [ -e ${FW_FILE}.pack ] && [ ${FW_FILE} -nt ${FW_FILE}.pack ];then
		pack_ns_image ${FW_FILE}
	elif [ ! -e ${FW_FILE}.pack ] && [ -e ${FW_FILE}.pack.xz ];then
		xz -d -k ${FW_FILE}.pack.xz --verbose
	elif [ -e ${FW_FILE}.pack ] && [ -e ${FW_FILE}.pack.xz ] && [ ${FW_FILE}.pack.xz -nt ${FW_FILE}.pack ];then
		rm ${FW_FILE}.pack
		xz -d -k ${FW_FILE}.pack.xz --verbose
	fi;

	if [ -e ${FW_FILE}.pack ];then
		dd if=${FW_FILE}.pack status=progress bs=1M of=${FLASH}
	elif [ -e ${FW_FILE} ];then
		dd if=${FW_FILE} status=progress bs=1M of=${FLASH}
	elif [ -e ${FW_FILE}.pack.xz ];then
		xz -d -c ${FW_FILE}.pack.xz |dd status=progress bs=1M of=${FLASH}
	elif [ -e ${FW_FILE}.xz ];then
		xz -d -c ${FW_FILE}.xz |dd status=progress bs=1M of=${FLASH}
	else
		echo "No flash file found"
		return 1;
	fi

	echo "Resize partition in MBR"
	parted ${FLASH} -s resizepart 2 100%
	echo "Checking File System"
	fsck.fat -a ${FLASH}1
	e2fsck -C 0 -fy ${FLASH}2
	echo "Expanding File System to fit flash"
	resize2fs ${FLASH}2
}

if [ ! "${ECM_ADDR}" ];then
	ECM_ADDR=192.168.2.2
fi;

if [ ! "${USB_ADDR}" ];then
	USB_ADDR=192.168.2.3
fi;

if [ ! "${DNS}" ];then
	DNS=8.8.8.8
fi;

if [ ! "${LOCAL_PORT}" ];then
	LOCAL_PORT=2222
fi;

if [ ! "${REMOTE_ADDR}" ];then
	REMOTE_ADDR="192.168.10.59"
fi;

if [ ! "${SSH_KEY}" ] && [ -e ~/.ssh/id_rsa ];then
	SSH_KEY=~/.ssh/id_rsa
fi;

if [ ! "${ASK_PW}" ];then
	ASK_PW=3;
fi;

if [ "${ASK_PW}" == "0" ];then
	ASK_TEST_PW=0
else
	ASK_TEST_PW=1
fi;

if [ ! "${PID_FILE}" ];then
	PID_FILE=/run/lock/wpnetlink
fi;

if [ ! "${FLOCK_TIME}" ];then
	FLOCK_TIME=30
fi;

if [ ! ${FW_PATH} ];then
	FW_PATH=/var/opt/comb
fi;

if [ ! "${FW_SRV_DIR}" ];then
	FW_SRV_DIR=${FW_PATH}
fi;

if [ ! "${SSH_OPTS}" ];then
	SSH_OPTS="-q -oUserKnownHostsFile=/dev/null -oHostKeyAlgorithms=+ssh-rsa -oPubkeyAcceptedKeyTypes=+ssh-rsa -oStrictHostKeyChecking=no -oTCPKeepAlive=yes -oServerAliveInterval=30"
fi;

ssh_agent_start
