#!/bin/bash

# Download DS-Mod packages from a randomly chosen mirror server. There are
# predefined servers in 'make menuconfig' which can be edited, but there is
# also an empty input field for a user-defined server. Additionally, another
# download source maybe specified on the command line as $2. $1 is the name
# of the file to be downloaded.
#
# This script is designed to be called by makefile includes (*.mk), but can
# also be called directly. It expects to find a file with necessary variables
# at a relative location '../.config' to this script. The variables are:
#   - DS_MOD_DL_NUM_SITES  (numeric value, e.g. 3)
#   - DS_MOD_DL_SITE_1     (URL, e.g. http://dsmod.3dfxatwork.de)
#   - ...
#   - DS_MOD_DL_SITE_n     (n = DS_MOD_DL_NUM_SITES)

helpmsg()
{
cat << 'EOF'
ds_download - download DS-Mod packages

Usage: ds_download (-?|--help) | (<download-dir> <dot-config> <filename> [<mirror>])
    download-dir  - target directory for download file
    dot-config    - path to .config for DS-Mod
    filename      - download file name
    mirror        - fallback mirror to download file from if preconfigured
                    mirrors fail
    -?, --help    - print this help text

Examples:
    ds_download dl .config package.tar.bz2
    ds_download dl .config package.tar.bz2 http://myserver.com/dsmod

Debugging: just set DEBUG=1, like this:
    DEBUG=1 ds_download dl .config package.tar.bz2
EOF
}

rand()
{
  # Create random 1-byte integer (for up to 255 download sites).
  # If more bytes are needed, increase 'count' parameter.
  rnd=$(dd if=/dev/urandom bs=1 count=1 2> /dev/null | od -d | head -n 1 | awk '{print $2}')
  # Normalise random number to return a value in range 1..$1
  echo $(( $rnd % $1 + 1 ))
}

do_download()
{
  # $1 = full download URL, $2 = target directory
  echo
  if [ "$DEBUG" == "1" ]; then echo -e "wget -P $1 $2"; fi
  wget -P "$1" "$2"
  wget_result=$?
  if [ "$wget_result" != "0" ]; then
    echo "Download failed - $2  ->  error code $wget_result" >&2
    return $wget_result
  fi
  echo "Download succeeded - $2  ->  saved to folder $1"
}


# Regular use: help parameter -> exit without error
if [ "$1" == "-?" -o "$1" == "--help" ]; then
  helpmsg
  exit 0
fi

# Wrong number of parameters -> exit with error
if [ $# -lt 3 -o $# -gt 4 ]; then
  helpmsg >&2
  exit 1
fi

DL_DIR="$1"
DOT_CONFIG="$2"
DL_FILE="$3"
FALLBACK_MIRROR="$4"

# Import DS-Mod config variables
. $DOT_CONFIG

if [ "$DEBUG" == "1" ]; then
  echo "ds_download parameters:"
  echo "  DL_DIR=$1"
  echo "  DOT_CONFIG=$2"
  echo "  DL_FILE=$3"
  echo "  FALLBACK_MIRROR=$4"
fi

# Fill array 'sites' with download server URLs (exclude empty strings)
for (( i=1 ; $i<=$DS_MOD_DL_NUM_SITES ; i++ )); do
  # Trim whitespace from download site name
  eval "dl_site=\$DS_MOD_DL_SITE_$i"
  read dl_site <<< "$dl_site";
  if [ "$dl_site" != "" ]; then
    (( num_sites++ ))
    sites[$num_sites]=$dl_site
  fi
done

# Randomly loop over preconfigured servers until a download succeeds
# or all requests have failed.
n=$num_sites
while [ $n -gt 0 ]; do
  i=$(rand $num_sites)
  if [ -z ${sites[$i]} ]; then continue; fi
  (( n-- ))
  do_download "$DL_DIR" "${sites[$i]}/$DL_FILE"
  if [ "$?" != "0" ]; then
    sites[$i]=""
    continue
  fi
  exit 0
done

# Trim whitespace from fallback mirror, too
read dl_site <<< "$FALLBACK_MIRROR";
if [ -z $dl_site ]; then
  echo "No fallback site specified - could not download file $DL_FILE" >&2
  exit 1
fi

# Try to download from fallback mirror
do_download "$DL_DIR" "${sites[$i]}/$DL_FILE"
if [ "$?" != "0" ]; then
  exit 1
fi