#!/bin/sh
# Copyright (c) 2000-2016 Synology Inc. All rights reserved.

SS_COMMON_SCRIPT=/var/packages/SurveillanceStation/target/scripts/SurveillanceStationCommon.sh
if [ -f "${SS_COMMON_SCRIPT}" ]; then
	. ${SS_COMMON_SCRIPT}
else
	echo "$(date +'%b %e %H:%M:%S') $(basename ${SS_COMMON_SCRIPT}) not found, remove packages without backups." >> "/var/log/surveillance/surveillance.log"
	exit 0
fi

BACKUP_VERSION_COUNT=5
BTRFS_SNAPSHOT_FOLDER_NAME="#snapshot"
SYNO_INDEX_BIN="/usr/syno/bin/synoindex"
SS_PKG_VOLUME_BACKUP_DIR_NAME="@ssbackup"
SS_SYSTEM_RELATED_FILES="${SS_SYSTEM_DB_NAME} ${SS_EMAP_DIR_NAME} ${SS_RTSP_DIR_NAME} \
${SS_USER_PHOTO_DIR_NAME} ${SS_DATA_DIR_NAME} ${SS_AXISACSCTRL_DB_NAME} ${SS_POS_DB_NAME} \
${SS_ARCHIVING_DB} ${SS_TIMELAPSE_DB}"

__GetPkgVolumeBackupDir()
{
	local PkgVolumePath="$(readlink ${SS_TARGET_DIR} | sed "s/^\/volume\([^/]*\).*/\/volume\1/g")"

	echo "${PkgVolumePath}/${SS_PKG_VOLUME_BACKUP_DIR_NAME}"
}

GetColumnListValue()
{
	ColumnList=$1
	Idx=$2

	echo "${ColumnList}" | sed -n "${Idx}p"
}

RemoveCamRecFolder()
{
	SSDebugLog "Remove Camera Recording Folder."
	local CamRecFolderList
	local ListCnt
	local CamRecFolder

	if [ false == "${pkgwizard_keep_recording}" ]; then
		CamRecFolderList=$(${SS_SQLITE3} -cmd ".timeout 200000" "${SS_SYSTEM_DB}" "SELECT recording_path from camera WHERE owner_ds_id = 0 AND recording_path <> '';")

		ListCnt=1
		CamRecFolder=$(GetColumnListValue "${CamRecFolderList}" ${ListCnt})
		while [ "" != "${CamRecFolder}" ]; do
			SSDebugLog "Remove ${CamRecFolder}"
			/bin/rm -rf "${CamRecFolder}"
			ListCnt=$(expr ${ListCnt} + 1)
			CamRecFolder=$(GetColumnListValue "${CamRecFolderList}" ${ListCnt})
		done
	fi
}

RemoveIVARecFolder()
{
	SSDebugLog "Remove IVA Recording Folder."
	local IVARecFolder

	if [ false == "${pkgwizard_keep_recording}" ]; then
		IVARecFolder=$(${SS_SQLITE3} -cmd ".timeout 200000" "${SS_SYSTEM_DB}" "SELECT archive_path from log_rotate_settings WHERE tbl_name='ivarecording';")
		IVARecFolder=${IVARecFolder}"/@VideoAnalytics"

		SSDebugLog "Remove ${IVARecFolder}"
		/bin/rm -rf "${IVARecFolder}"
	fi
}

CleanupNonRecFlags()
{
	SSDebugLog "Cleanup non-recording mode flags."

	rm -f ${SS_LEAVING_NON_RECORDING_FILE}
	rm -f ${SS_NON_RECORDING_FILE}
}

BackupDatabases()
{
	if [ false == "${pkgwizard_keep_recording}" -a \
		 false == "${pkgwizard_keep_system}" ]; then
		return
	fi

	if [ ! -f $SS_SYSTEM_DB -o \
		 ! -d $SS_SERVICE_DATA_FOLDER_LINK/ ]; then
		return
	fi

	SSDebugLog "Backup related databases"

	local DstDir=${SS_SERVICE_DATA_FOLDER_LINK}/${SS_SHARE_BACKUP_DIR_NAME}

	mkdir -p $DstDir

	DoBackupDB $DstDir $SS_SYSTEM_DB $SS_SYSTEM_DB_NAME
	DoBackupDB $DstDir $SS_REC_DB $SS_REC_DB_NAME
	DoBackupDB $DstDir $SS_REC_CNT_DB $SS_REC_CNT_DB_NAME
	DoBackupDB $DstDir $SS_LOG_DB $SS_LOG_DB_NAME
	DoBackupDB $DstDir $SS_SNAPSHOT_DB $SS_SNAPSHOT_DB_NAME
	DoBackupDB $DstDir $SS_AXISACSCTRL_DB $SS_AXISACSCTRL_DB_NAME
	DoBackupDB $DstDir $SS_AXISACSEVTLOG_DB $SS_AXISACSEVTLOG_DB_NAME
	DoBackupDB $DstDir $SS_POS_DB $SS_POS_DB_NAME
	DoBackupDB $DstDir $SS_TRANSACTIONSLOG_DB $SS_TRANSACTIONSLOG_DB_NAME
	DoBackupDB $DstDir $SS_ARCHIVING_DB $SS_ARCHIVING_DB_NAME
	DoBackupDB $DstDir $SS_REC_DEL_DETAIL_DB $SS_REC_DEL_DETAIL_DB_NAME
	DoBackupDB $DstDir $SS_TIMELAPSE_DB $SS_TIMELAPSE_DB_NAME
	DoBackupDB $DstDir $SS_IPSPEAKER_DB $SS_IPSPEAKER_DB_NAME
}

GetBakDb()
{
	local DbDir="$1"
	local DbName="$2"
	local DbVersion="$3"

	echo $(ls -t "$DbDir" | grep "^${DbName}\..*\.${DbVersion}$" | head -1)
}

DoBackupDB()
{
	local BakDir=$1
	local SrcDb=$2
	local DbName=$3

	local BakDb=""
	local Version=""
	local i=0

	# checkpoint database
	Sqlite3Exec $SrcDb "PRAGMA wal_checkpoint(FULL);" > /dev/null 2>&1
	if [ $? != 0 ]; then
		Sqlite3Exec $SrcDb "PRAGMA wal_checkpoint(PASSIVE);" > /dev/null 2>&1
	fi

	# Backup previous versions of DB
	BakDb=$(GetBakDb $BakDir $DbName $((BACKUP_VERSION_COUNT-1)))

	# Step1: Delete the oldest backup
	if [ -f "$BakDir/$BakDb" ]; then
		rm -f "$BakDir/$BakDb"
	fi

	# Step2: Shift backups version number
	i=$((BACKUP_VERSION_COUNT-2))
	while [ 0 -le $i ]
	do
		BakDb=$(GetBakDb $BakDir $DbName $i)

		if [ -f "$BakDir/$BakDb" ]; then
			Version=`echo $BakDb | cut -d '.' -f 3`
			mv -f "$BakDir/$BakDb" "$BakDir/$DbName.$Version.$((i+1))"
		fi
		i=$((i-1))
	done

	# Step3: Copy the newest version of db
	Version=$(echo $SURVEILLANCE_PKG_VERSION | cut -d '-' -f 2)
	cp "$SrcDb" "$BakDir/$DbName.$Version.0"
}

BackupSystemFiles()
{
	local PkgVolumeBackupDir="$(__GetPkgVolumeBackupDir)"

	if [ false == "${pkgwizard_keep_system}" ]; then
		SSDebugLog "Remove ${PkgVolumeBackupDir} since pkgwizard_keep_system is false."

		if [ -n "PkgVolumeBackupDir" -a "\/" != "PkgVolumeBackupDir" ]; then
			/bin/rm -rf "${PkgVolumeBackupDir}"
		fi
	else
		SSDebugLog "Backup system DB to package volume."

		if [ ! -d "${PkgVolumeBackupDir}" ]; then
			/bin/mkdir "${PkgVolumeBackupDir}"
		fi

		# To compatible with old ss version
		if [ -d $SS_SERVICE_DATA_FOLDER_LINK/ ]; then
			/bin/cp -f "${SS_ARCHIVING_DB}" "$SS_SERVICE_DATA_FOLDER_LINK/"
			/bin/cp -f "${SS_TIMELAPSE_DB}" "$SS_SERVICE_DATA_FOLDER_LINK/"
		else
			SSDebugLog "$SS_SERVICE_DATA_FOLDER_LINK/ removed befor Backup db."
		fi

		SetValueToConfFile "${SS_SETTINGS_CONF}" "${CONF_KEY_SYS_DB_BKP_PATH}" "${PkgVolumeBackupDir}"
		SetValueToConfFile "${SS_SETTINGS_CONF}" "${CONF_KEY_AXISACSCTRL_DB_BKP_PATH}" "${PkgVolumeBackupDir}"
		SetValueToConfFile "${SS_SETTINGS_CONF}" "${CONF_KEY_POS_DB_BKP_PATH}" "${PkgVolumeBackupDir}"
		SetValueToConfFile "${SS_SETTINGS_CONF}" "${CONF_KEY_IPSPEAKER_DB_BKP_PATH}" "${PkgVolumeBackupDir}"
		SetValueToConfFile "${SS_SETTINGS_CONF}" "${CONF_KEY_ARCHIVING_DB_BKP_PATH}" "${PkgVolumeBackupDir}"
		SetValueToConfFile "${SS_SETTINGS_CONF}" "${CONF_KEY_TIMELAPSE_DB_BKP_PATH}" "${PkgVolumeBackupDir}"

		/bin/mv -f "${SS_SYSTEM_DB}" "${PkgVolumeBackupDir}/"
		/bin/mv -f "${SS_EMAP_DIR}" "${PkgVolumeBackupDir}/"
		/bin/mv -f "${SS_RTSP_DIR}" "${PkgVolumeBackupDir}/"
		/bin/mv -f "${SS_USER_PHOTO_DIR}" "${PkgVolumeBackupDir}/"
		/bin/mv -f "${SS_DATA_DIR}" "${PkgVolumeBackupDir}/"
		/bin/mv -f "${SS_AXISACSCTRL_DB}" "${PkgVolumeBackupDir}/"
		/bin/mv -f "${SS_POS_DB}" "${PkgVolumeBackupDir}/"
		/bin/mv -f "${SS_IPSPEAKER_DB}" "${PkgVolumeBackupDir}/"
		/bin/mv -f "${SS_ARCHIVING_DB}" "${PkgVolumeBackupDir}/"
		/bin/mv -f "${SS_TIMELAPSE_DB}" "${PkgVolumeBackupDir}/"

		[ -f "${SS_SYSTEM_DB}" ] && SSDebugLog "${SS_SYSTEM_DB} still exist."
		[ -d "${SS_EMAP_DIR}" ] && SSDebugLog "${SS_EMAP_DIR} still exist."
		[ -d "${SS_RTSP_DIR}" ] && SSDebugLog "${SS_RTSP_DIR} still exist."
		[ -d "${SS_USER_PHOTO_DIR}" ] && SSDebugLog "${SS_USER_PHOTO_DIR} still exist."
		[ -d "${SS_DATA_DIR}" ] && SSDebugLog "${SS_DATA_DIR} still exist."
		[ -f "${SS_AXISACSCTRL_DB}" ] && SSDebugLog "${SS_AXISACSCTRL_DB} still exist."
		[ -f "${SS_POS_DB}" ] && SSDebugLog "${SS_POS_DB} still exist."
		[ -f "${SS_IPSPEAKER_DB}" ] && SSDebugLog "${SS_IPSPEAKER_DB} still exist."
		[ -f "${SS_ARCHIVING_DB}" ] && SSDebugLog "${SS_ARCHIVING_DB} still exist."
		[ -f "${SS_TIMELAPSE_DB}" ] && SSDebugLog "${SS_TIMELAPSE_DB} still exist."
	fi
}

UpdateEventIndex()
{
	SSDebugLog "UpdateEventIndex."

	local SSShareFolderDir=$(/usr/syno/sbin/synoshare --get "${DEFAULT_SS_SHARE_NAME}" | grep "Path ......" | sed -e 's/^.*\[\(.*\)\]/\1/g')

	if [ ! -d "${SSShareFolderDir}" ]; then
		return
	fi

	if [ false == "${pkgwizard_keep_recording}" ]; then
		# Reindex shared folder
		$SYNO_INDEX_BIN -R $SSShareFolderDir
	fi
}

RemoveServiceData()
{
	local TgtDir="$1"
	local ExcldDirs="$2"

	if [ ! -d "$TgtDir" ]; then
		return
	fi

	local DelFileList=$(ls -1A "$TgtDir")

	for KeepFileName in $ExcldDirs; do
		DelFileList=$(echo "$DelFileList" | grep -v "^${KeepFileName}$")
	done

	local ListCnt=1
	local DelFile=$(GetColumnListValue "$DelFileList" $ListCnt)

	while [ "" != "${DelFile}" ]; do
		SSDebugLog "Remove ${TgtDir}/${DelFile}"
		/bin/rm -rf "${TgtDir}/${DelFile}"
		ListCnt=$(expr $ListCnt + 1)
		DelFile=$(GetColumnListValue "$DelFileList" $ListCnt)
	done
}

RemoveServDataFolder()
{
	if [ ! -d $SS_SERVICE_DATA_FOLDER_LINK/ ]; then
		return
	fi

	# $pkgwizard_keep_recording may be empty
	if [ true == "$pkgwizard_keep_recording" ]; then
		BackupServDataFolder
	elif [ false == "$pkgwizard_keep_recording" ]; then
		if [ false == "$pkgwizard_keep_system" ]; then
			rm -rf $(realpath $SS_SERVICE_DATA_FOLDER_LINK)
			return
		fi

		RemoveServiceData "$SS_SERVICE_DATA_FOLDER_LINK" \
						  "$SS_CAP_INFO_DIR_NAME $SS_SHARE_BACKUP_DIR_NAME"
	fi

	# Remove empty camcap dir
	rmdir --ignore-fail-on-non-empty ${SSShareFolderDir}/${SS_CAP_INFO_DIR_NAME}
}

BackupServDataFolder()
{
	local BkpDir="$(__GetPkgVolumeBackupDir)"
	local SrcDir="$(readlink $SS_SERVICE_DATA_FOLDER_LINK)"
	local DstDir="${BkpDir}/${SS_SERVICE_DATA_FOLDER_NAME}"

	if [ ! -d "$SrcDir" ]; then
		SSDebugLog "Service data dir [$SrcDir] doesn't exist."
		return 1
	fi

	if [ -e "$DstDir" ]; then
		SSDebugLog "Delete existing destination backup dir [$DstDir]."
		rm -rf "$DstDir"
	fi

	if [ ! -d "$BkpDir" ]; then
		/bin/mkdir "$BkpDir"
	fi

	SSDebugLog "Backup service data dir to [$DstDir]."
	SetValueToConfFile "$SS_SETTINGS_CONF" "$CONF_KEY_SERV_DATA_BKP_PATH" "$BkpDir"
	/bin/mv -f "$SrcDir" "${BkpDir}/"
}

RemoveShareFolder()
{
	SSDebugLog "Remove share folder."

	# Remove shared folder only when pkg uninstall
	# ${pkgwizard_keep_recording} will be empty value when upgrade pkg
	if [ -z "${pkgwizard_keep_recording}" ]; then
		return
	fi

	local SSShareFolderDir=$(/usr/syno/sbin/synoshare --get "${DEFAULT_SS_SHARE_NAME}" \
									| grep "Path ......" | sed -e 's/^.*\[\(.*\)\]/\1/g')

	if [ ! -d "${SSShareFolderDir}" ]; then
		return
	fi

	if [ false == "$pkgwizard_keep_recording" ]; then
		if [ false == "$pkgwizard_keep_system" ]; then
			${SYNO_SHARE_TOOL} --del TRUE "${DEFAULT_SS_SHARE_NAME}"
			[ -d "${SS_SHARE_FOLDER_LINK}" ] && /bin/rm -rf $SS_SHARE_FOLDER_LINK
			return
		fi

		RemoveServiceData "$SSShareFolderDir" "$BTRFS_SNAPSHOT_FOLDER_NAME $SS_SYSTEM_RELATED_FILES"
	fi

	if [ -z "$(ls -A "${SSShareFolderDir}")" ]; then
		${SYNO_SHARE_TOOL} --del TRUE "${DEFAULT_SS_SHARE_NAME}"
	fi
}

RemovePgsqlDB()
{
	SSDebugLog "Remove pgsql DB."

	if [ ${USE_SQLITE} == true ]; then
		return
	fi

	if [ false == "${pkgwizard_keep_recording}" ]; then
		local PidList=$(${PGSQL_BIN_PSQL} -t -c "select procpid from pg_stat_activity where datname='${PGSQL_DB_NAME}'")
		for Pid in ${PidList}; do
			kill ${Pid}
		done

		echo "Drop surveillance database"
		${PGSQL_BIN_DROPDB}
		if [ $? != 0 ]; then
			SSDebugLog "Failed to dropdb"
			exit 1
		fi
	fi
}

main()
{
	PackageInfoGet

	SSDebugLog "Start pre-uninstall."

	RemoveCamRecFolder
	RemoveIVARecFolder
	CleanupNonRecFlags

	BackupDatabases
	BackupSystemFiles

	RemoveShareFolder
	RemoveServDataFolder
	RemovePgsqlDB

	UpdateEventIndex

	SSDebugLog "Finish pre-uninstall."

	exit 0
}

main "$@"
