#!/bin/bash

# Purpose {{{
# This script will download Debian netboot installer for both AMD64 and i368
#   1. Debian Stable (Bullseye)
#   2. Debian oldStable (Buster)
#   3. Debian oldoldStable (Stretch)
#   4. Debian Unstable (Sid)
# and make a sample menu.cfg config file.
# }}}
# Vars {{{
readonly PROGNAME=$(basename "${0}")
readonly NBARGS="${#}"
[ -z "${DEBUG}" ] && DEBUG=1
## Export DEBUG for sub-script
export DEBUG

# Default value for TFTP's directory
if command -v in.tftpd > /dev/null; then
	source /etc/default/tftpd-hpa
else
	TFTP_DIRECTORY="/srv/tftp"
fi

# Where to store Debian's installers
DEBIAN_INSTALLER_DIR="${TFTP_DIRECTORY}/installer/debian"
# tftp sample config file
DEBIAN_CONFIG_PXE="${DEBIAN_INSTALLER_DIR}/menu.cfg.example"

## Colors
readonly PURPLE='\033[1;35m'
readonly RED='\033[0;31m'
readonly RESET='\033[0m'
readonly COLOR_DEBUG="${PURPLE}"
# }}}
usage() {                                                       # {{{

	cat <<- EOF
usage: $PROGNAME [-d|-h]

This script will download "all" Debian's netboot installer for
tftp server for both AMD64 and i368 architectures.

EXAMPLES :
    - Download Debian's installers to default place (${TFTP_DIRECTORY})
        ${PROGNAME}

OPTIONS :
    -d,--debug
        Enable debug messages.

    -h,--help
        Print this help message.

EOF

}
# }}}
debug_message() {                                               # {{{

	local_message="${1}"

	## Print message if DEBUG is enable (=0)
	[ "${DEBUG}" -eq "0" ] && printf '\e[1;35m%-6b\e[m\n' "DEBUG − ${PROGNAME} : ${local_message}"

	return 0
}
# }}}
error_message() {                                               # {{{

	local_error_message="${1}"
	local_error_code="${2}"

	## Print message
	printf '%b\n' "ERROR − ${PROGNAME} : ${RED}${local_error_message}${RESET}"

	exit "${local_error_code:=66}"
}
# }}}

download_file() {                                               # {{{

	local_url="${1}"
	local_dest_file="${2}"

	debug_message "download_file − \
Download ${local_url} to ${RED}${local_dest_file}${COLOR_DEBUG} ."

	wget --quiet "${local_url}" --output-document="${local_dest_file}"

	## Unset variables
	unset local_url
	unset local_dest_file
}
# }}}
is_file_empty() {                                               # {{{

	local_file="${1}"

	## File is empty by default
	return_is_file_empty="0"

	### Check if the file is empty
	if [ ! -s "${local_file}" ]; then
		return_is_file_empty="0"
		debug_message "is_file_empty − \
The file ${RED}${local_file}${COLOR_DEBUG} is empty or doesn't exists."
	else
		return_is_file_empty="1"
		debug_message "is_file_empty − \
The file ${RED}${local_file}${COLOR_DEBUG} exists and has a size greater than zero."
	fi

	## Unset variables
	unset local_file

	return "${return_is_file_empty}"
}
# }}}

main() {                                                        # {{{

	# Create directories and config file
	debug_message "Main − \
Create ${DEBIAN_INSTALLER_DIR} tree."
	mkdir --parents -- "${DEBIAN_INSTALLER_DIR}" \
		|| error_message "Can't create ${DEBIAN_INSTALLER_DIR} directory." "1"
	debug_message "Main − \
(re)Create ${DEBIAN_CONFIG_PXE} sample config file."
	true > "${DEBIAN_CONFIG_PXE}"

	# Parse all Debian's distribution
	for DISTRO in bullseye buster stretch sid; do # For "all" Debian's version
		## Then parse architecture
		for ARCH in amd64 i386; do                  # For all classic architecture
		debug_message "Main FOR loop − \
Manage ${RED}${DISTRO}${COLOR_DEBUG} release with ${RED}${ARCH}${COLOR_DEBUG} architecture."

			### Create destination directory
			mkdir --parents -- ${DEBIAN_INSTALLER_DIR}/${DISTRO}/${ARCH} \
				|| error_message "Can't create ${DEBIAN_INSTALLER_DIR}/${DISTRO}/${ARCH} tree." "1"

			### Download linux file
			download_file "http://deb.debian.org/debian/dists/${DISTRO}/main/installer-${ARCH}/current/images/netboot/debian-installer/${ARCH}/linux" \
				"${DEBIAN_INSTALLER_DIR}/${DISTRO}/${ARCH}/linux"
			is_file_empty "${DEBIAN_INSTALLER_DIR}/${DISTRO}/${ARCH}/linux" \
				&& error_message "${DEBIAN_INSTALLER_DIR}/${DISTRO}/${ARCH}/linux is empty !" "2"

			### Download initrd.gz
			download_file "http://deb.debian.org/debian/dists/${DISTRO}/main/installer-${ARCH}/current/images/netboot/debian-installer/${ARCH}/initrd.gz" \
				"${DEBIAN_INSTALLER_DIR}/${DISTRO}/${ARCH}/initrd.gz"
			is_file_empty "${DEBIAN_INSTALLER_DIR}/${DISTRO}/${ARCH}/initrd.gz" \
				&& error_message "${DEBIAN_INSTALLER_DIR}/${DISTRO}/${ARCH}/initrd.gz is empty !" "2"

			### Config file
			debug_message "Main FOR loop − \
Add tftp config sample."
			/bin/cat >> "${DEBIAN_CONFIG_PXE}" << EOF
label ${DISTRO}${ARCH}
  menu label Debian GNU/Linux ${DISTRO} ^${ARCH} bits
  kernel installer/debian/${DISTRO}/${ARCH}/linux
  append vga=normal initrd=installer/debian/${DISTRO}/${ARCH}/initrd.gz -- quiet
EOF
		done

	# Config file
	/bin/cat >> "${DEBIAN_CONFIG_PXE}" << EOF
label separator
  menu label ---
EOF
	done

# Config file
	/bin/cat >> "${DEBIAN_CONFIG_PXE}" << EOF
label mainmenu
  menu label ^Back...
  menu exit
EOF
}
# }}}

# Manage arguments                                                # {{{
# This code can't be in a function due to argument management

if [ ! "${NBARGS}" -eq "0" ]; then

	manage_arg="0"

	## If the first argument is not an option
	if ! printf -- '%s' "${1}" | grep -q -E -- "^-+";
	then
		## Print help message and exit
		printf '%b\n' "${RED}Invalid option: ${1}${RESET}"
		printf '%b\n' "---"
		usage

		exit 1
	fi

	# Parse all options (start with a "-") one by one
	while printf -- '%s' "${1}" | grep -q -E -- "^-+"; do

	case "${1}" in
		-d|--debug )                          ## debug
			DEBUG=0
			;;
		-h|--help )                           ## help
			usage
			## Exit after help informations
			exit 0
			;;
		* )                                   ## unknow option
			printf '%b\n' "${RED}Invalid option: ${1}${RESET}"
			printf '%b\n' "---"
			usage
			exit 1
			;;
	esac

	debug_message "Arguments management − \
${RED}${1}${COLOR_DEBUG} option managed."

	## Move to the next argument
	shift
	manage_arg=$((manage_arg+1))

	done

	debug_message "Arguments management − \
${RED}${manage_arg}${COLOR_DEBUG} argument(s) successfully managed."
else
	debug_message "Arguments management − \
No arguments/options to manage."
fi

# }}}

main

exit 0
