#!/bin/bash
set -e

function usage() {
	echo "Usage: $0 min_x max_x min_y max_y [target_dir=elevation] [parallelism=$(nproc)] [decompress=true]"
	exit 1
}

#validate ranges
if [ -z "$4" ]; then
	usage
fi
min_x=$(python3 -c "import math; print(int(math.floor($1)))")
max_x=$(python3 -c "import math; print(int(math.ceil($2) - 1))")
min_y=$(python3 -c "import math; print(int(math.floor($3)))")
max_y=$(python3 -c "import math; print(int(math.ceil($4) - 1))")

if [ $min_x -gt $max_x ] || [ $min_x -lt -180 ] || [ $max_x -gt 180 ]; then
	usage
fi
if [ $min_y -gt $max_y ] || [ $min_y -lt -90 ] || [ $max_y -gt 90 ]; then
	usage
fi

if [ -z $5 ]; then
	dest=elevation
else
	dest="$5"
fi
if [ -z $6 ]; then
	para=$(nproc)
else
	para="$6"
fi
if [[ -z $7 ]] || [[ $7 != "false" ]]; then
	decomp=true
	export decomp
else
	unset decomp
fi

#get dirs
for y in $(seq ${min_y} 1 ${max_y}); do
	dir=$(python3 -c "print('%s%02d' % ('S' if ${y} < 0 else 'N', abs(${y})))")
	echo "${dest}/${dir}"
done | while read d; do mkdir -p $d; done

#get the data
expected=$((($max_x - $min_x + 1)*($max_y - $min_y + 1)))
echo "extracting $expected elevation tiles"
ext=$( [[ ${decomp} ]] && echo "" || echo ".gz" )
for x in $(seq ${min_x} 1 ${max_x}); do
	for y in $(seq ${min_y} 1 ${max_y}); do
		file=$(python3 -c "print('%s%02d%s%03d.hgt' % ('S' if ${y} < 0 else 'N', abs(${y}), 'W' if ${x} < 0 else 'E', abs(${x})))")
		dir=$(echo ${file} | sed "s/^\([NS][0-9]\{2\}\).*/\1/g")
		#if we dont already have it or its the wrong size
		if [ ! -e ${dest}/${dir}/${file} ] || [ $(stat -c %s ${dest}/${dir}/${file}) -ne $((3601*3601*2)) ]; then
			echo "http://s3.amazonaws.com/elevation-tiles-prod/skadi/${dir}/${file}.gz ${dest}/${dir}/${file}${ext}"
		fi
	done
done | parallel --env decomp --progress -C ' ' -P ${para} 'curl --retry 3 --retry-delay 0 --max-time 100 -s -o - {1} | ( [[ ! ${decomp} ]] && cat || gunzip ) > {2}'

#check they are all there
echo "checking all files exist"
total=$(find ${dest} | grep -cF hgt)
if [ ${total} -ne ${expected} ]; then
	echo "try again, $((${expected} - ${total})) files are missing"
	exit 1
fi

#check their sizes
echo "checking file sizes"
if [ ${decomp} ]; then
	found=$(find ${dest} -type f -size $((3601*3601*2))c | wc -l)
else
	found=$(for f in $(find ${dest} -type f); do gzip -l $f | tail -n 1; done | grep -cvF $((3601*3601*2)))
fi
if [ ${found} -ne ${expected} ]; then
	echo "try again, $((${expected} - ${found})) files are corrupt"
	exit 1
fi
