#!/bin/sh

show_usage()
{
  cat<<EOF >&2
Usage: $0 [OPTIONS] -f SOURCE -t TARGET

Available options:
  -f PATH  copy data from PATH (e.g. /media/cdrom)
  -t PATH  copy data to PATH (e.g. /usr/local/share/swars)

  -M       do not copy music
  -d DEVICE read audio tracks from DEVICE (e.g. /dev/sr0)
  -l LANG  choose language LANG

  -h       print usage information

Available languages: eng fre ger ita spa swe
EOF
}

if [ $# -eq 1 -a "x$1" = "x--help" ]; then
  show_usage
  exit 0
fi

WITH_MUSIC="yes"
OWN_TARGET="no"
DEVICE=""
SOURCE=""
TARGET=""
LANG="eng"

LEVELS_VERSION="1.0.1.31"
LEVELS_PACKAGE="swars-levels-1_0_1_31"
LEVELS_PKG_MD5="57ca7bf586aa7d75f94808dde6f525c7"

GFX_VERSION="1.0.3.218"
GFX_PACKAGE="swars-gfx-1_0_3_218"
GFX_PKG_MD5="7a86388f7b50260497db411cb80d1b22"

SFX_VERSION="1.0.0.22"
SFX_PACKAGE="swars-sfx-1_0_0_22"
SFX_PKG_MD5="f222a89bfe0a2c931394c2ae25508a6d"

OPTS="f:t:Md:l:h"

while getopts "$OPTS" arg; do
  case "$arg" in
    f)
      SOURCE="$OPTARG"
      ;;
    t)
      TARGET="$OPTARG"
      ;;
    M)
      WITH_MUSIC="no"
      ;;
    d)
      DEVICE="$OPTARG"
      ;;
    l)
      LANG="$OPTARG"
      ;;
    h)
      show_usage
      exit 0
      ;;
    *)
      exit 1
  esac
done

check_music_tools()
{
  if [ "$WITH_MUSIC" = "no" ]; then
    return 0
  fi

  CDPARANOIA=`which cdparanoia`
  if [ -z "$CDPARANOIA" ]; then
    CDPARANOIA=`which cd-paranoia`
  fi
  OGGENC=`which oggenc`
  if [ -z "$OGGENC" ]; then
    OGGENC=`which oggenc2`
  fi

  if [ -z "$CDPARANOIA" ] || [ -z "$OGGENC" ]; then
    cat<<EOF >&2
You don't have the tools needed to copy the music.  Please ensure that you
have 'cdparanoia' and 'oggenc' (from vorbis-tools) in your path or run with
-M and try again.
EOF
    return 1
  fi

  return 0
}

check_source()
{
  if [ -z "$SOURCE" ]; then
    echo "Source not specified.  Try --help." >&2
    exit 1
  fi
  if ! [ -d "$SOURCE" ]; then
    echo "Source directory '$SOURCE' does not exist!" >&2
    return 1
  fi

  if [ -d "$SOURCE/game" ]; then
    SOURCE="$SOURCE/game"
    return 0
  fi

  echo "Source directory '$SOURCE' does not contain the data from the game!" >&2
  return 1
}

check_target()
{
  if [ -z "$TARGET" ]; then
    echo "Target not specified.  Try --help." >&2
    exit 1
  fi

  if [ -d "$TARGET" ]; then
    local file_count=`ls "$TARGET" | wc -l | sed 's/[^0-9]//g'` || return 1

    if [ "x$file_count" != "x0" ]; then
      echo "Target directory '$TARGET' is not empty!" >&2
      return 1
    fi
  fi

  install -v -d "$TARGET" || return 1
  OWN_TARGET="yes"

  return 0
}

dl_package()
{
  local proj_nam=$1
  local pkg_nam=$2
  local pkg_ver=$3
  local pkg_md5=$4

  local real_md5=`md5sum "${pkg_nam}.zip" | cut -d " " -f1`
  if [[ "x${real_md5}" != "x${pkg_md5}" ]]; then
    wget "https://github.com/${proj_nam}/releases/download/${pkg_ver}/${pkg_nam}.zip" || return 1
  fi

  local real_md5=`md5sum "${pkg_nam}.zip" | cut -d " " -f1`
  if [[ "x${real_md5}" != "x${pkg_md5}" ]]; then
    printf 'Downloaded package MD5 mismatch: %s\n' "$pkg_nam" >&2
    printf 'Expected md5sum: %s\n' "$pkg_md5" >&2
    return 1
  fi

  return 0
}

download_packages()
{
  dl_package "swfans/swars-levels" "${LEVELS_PACKAGE}" "${LEVELS_VERSION}" "${LEVELS_PKG_MD5}" || return 1
  dl_package "swfans/swars-gfx" "${GFX_PACKAGE}" "${GFX_VERSION}" "${GFX_PKG_MD5}" || return 1
  dl_package "swfans/swars-sfx" "${SFX_PACKAGE}" "${SFX_VERSION}" "${SFX_PKG_MD5}" || return 1

  return 0
}

copy_music()
{
  if [ "$WITH_MUSIC" = "no" ]; then
    return 0
  fi

  install -v -d "$TARGET/music" || return 1

  for track_number in 1 2 3; do
    local cd_number=$(($track_number+1))
    local track_wav="$TARGET/music/track_$track_number.wav"
    local track_ogg="$TARGET/music/track_$track_number.ogg"
    if [ -z "$DEVICE" ]; then
      "$CDPARANOIA" "$cd_number" "$track_wav" || return 1
    else
      "$CDPARANOIA" -d "$DEVICE" "$cd_number" "$track_wav" || return 1
    fi
    "$OGGENC" -b 192 "$track_wav" || return 1
    rm -vf "$track_wav" || return 1
    chmod 0644 "$track_ogg" || return 1
  done

  return 0
}

install_file()
{
  local fname="$1"

  # Find the input file name ignoring case
  local src=`find "$SOURCE" -ipath "$SOURCE/$fname"`
  local dst="$TARGET/$fname"

  if [ ! -n "$src" ]; then
    printf 'File missing from your SOURCE: %s\n' "$fname" >&2
    return 1
  fi

  install -v -T -m 0644 "$src" "$dst" || return 1

  return 0
}

install_file_to()
{
  local fname="$1"
  local dstdir="$2"

  # Find the input file name ignoring case
  local src=`find "$SOURCE" -ipath "$SOURCE/$fname"`
  local fbase=`basename "$fname"`
  local dst="$TARGET/$dstdir/$fbase"

  if [ ! -n "$src" ]; then
    printf 'File missing from your SOURCE: %s\n' "$fname" >&2
    return 1
  fi

  install -v -T -m 0644 "$src" "$dst" || return 1

  return 0
}

install_dir()
{
  local dname="$1"

  local dst="$TARGET/$dname"

  install -v -d "$dst" || return 1

  return 0
}

copy_data()
{
  install_dir "data" || return 1

  for fn in bgtables.dat tables.dat startgho.dat synghost.tab; do
    install_file "data/${fn}" || return 1
  done

  for fn in cities.dat mapinsid.dat mech.dat people.txt textwalk.dat; do
    install_file "data/${fn}" || return 1
  done

  for fn in w-icons; do
    install_file "data/${fn}.dat" || return 1
    install_file "data/${fn}.tab" || return 1
  done

  for fn in 00 01 02 03 04 05; do
    install_file "data/mapout${fn}.dat" || return 1
    install_file "data/tex${fn}.dat" || return 1
  done

  for fn in 0 1 2 3 4 5; do
    install_file "data/mspr-${fn}.dat" || return 1
    install_file "data/mspr-${fn}.tab" || return 1
    install_file "data/mspr-${fn}.inf" || return 1
  done

  for fn in s z; do
    install_file "data/outro-${fn}.smk" || return 1
    install_file "data/outro-${fn}.raw" || return 1
  done

  for fn in tit nam qot; do
    install_file "data/${fn}-font.dat" || return 1
    install_file "data/${fn}-font.tab" || return 1
  done

  for fn in pal s-proj; do
    install_file "data/${fn}.pal" || return 1
  done

  install_dir "data/equip" || return 1

  for fn in 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18; do
    install_file "data/equip/net${fn}.fli" || return 1
  done

  install_dir "qdata" || return 1

  for fn in posdefs.idx posdefs.wad primveh.obj; do
    install_file "qdata/${fn}" || return 1
  done

  for fn in 10 11 12 13; do
    install_file "qdata/demo-${fn}.fli" || return 1
  done

  for fn in flyby.fli pal.pal; do
    install_file "qdata/${fn}" || return 1
  done

  for fn in 0 1 2 3; do
    install_file "qdata/pal${fn}.dat" || return 1
  done

  for fn in syn_fail syn_go syn_mc zel-go zel-mc; do
    install_file "qdata/${fn}.smk" || return 1
  done

  install_dir "qdata/equip" || return 1

  install_dir "levels" || return 1

  install_dir "maps" || return 1

  for fn in 000 001 002 003 004 005 006 007 008 009 010 011 020 021 022 025 026 027 028 030 032 035 036 040 041 044 045 046 047 050 079; do
    install_file "maps/map${fn}.scn" || return 1
  done

  install_dir "sound" || return 1

  for fn in music.dat sample.ad; do
    install_file "sound/${fn}" || return 1
  done

  install_dir "intro" || return 1

  # Copy files which on the CD are in per-language dir
  install_file_to "language/$LANG/text.dat" "data" || return 1
  install_file_to "language/$LANG/syn_ele.smk" "data" || return 1
  install_file_to "language/$LANG/chu_ele.smk" "data" || return 1

  install_file_to "language/$LANG/intro.smk" "intro" || return 1

  return 0
}

extract_packages()
{
  unzip -o "${LEVELS_PACKAGE}.zip" -d "${TARGET}" || return 1
  find "$TARGET/swars/LEVELS" -mindepth 1 -maxdepth 1 -type f -iname 'c*.*' \
    | while read file; do
    mv -vn "$file" -t "${TARGET}/levels" || return 1
      done
  find "$TARGET/swars/MAPS" -mindepth 1 -maxdepth 1 -type f -iname 'map*.*' \
    | while read file; do
    mv -vn "$file" -t "${TARGET}/maps" || return 1
      done
  rm -rf "${TARGET}/swars" || return 1

  unzip -o "${GFX_PACKAGE}.zip" -d "${TARGET}" || return 1
  find "$TARGET/swars/data" -mindepth 1 -maxdepth 1 -type f -iname '*.*' \
    | while read file; do
    mv -vn "$file" -t "${TARGET}/data" || return 1
      done
  find "$TARGET/swars/data/equip" -mindepth 1 -maxdepth 1 -type f -iname '*.*' \
    | while read file; do
    mv -vn "$file" -t "${TARGET}/data/equip" || return 1
      done
  find "$TARGET/swars/qdata/equip" -mindepth 1 -maxdepth 1 -type f -iname '*.*' \
    | while read file; do
    mv -vn "$file" -t "${TARGET}/qdata/equip" || return 1
      done
  rm -rf "${TARGET}/swars" || return 1

  unzip -o "${SFX_PACKAGE}.zip" -d "${TARGET}" || return 1
  find "$TARGET/swars/sound" -mindepth 1 -maxdepth 1 -type f -iname '*.dat' \
    | while read file; do
    mv -vn "$file" -t "${TARGET}/sound" || return 1
      done
  rm -rf "${TARGET}/swars" || return 1

  return 0
}

check_language()
{
  case "$LANG" in
    eng)
      LANG_NAME="English"
      ;;
    fre)
      LANG_NAME="French"
      ;;
    ger)
      LANG_NAME="German"
      ;;
    ita)
      LANG_NAME="Italian"
      ;;
    spa)
      LANG_NAME="Spanish"
      ;;
    swe)
      LANG_NAME="Swedish"
      ;;
    *)
      echo "Unsupported language: $LANG." >&2
      return 1
      ;;
  esac
  return 0
}

create_config_ini()
{
  cat<<EOF >"$TARGET/config.ini"
CD="D:\\GAME\\"
InstallDrive="C:\\"
Language="$LANG_NAME"
Intro="Max"
Anims="Max"
Sound="Max"
Levels="Max"
Data="Max"
Maps="Max"
DOS="Max"
EOF
  [ $? -eq 0 ] || return 1
  return 0
}

error()
{
  if [ "$OWN_TARGET" = "yes" ]; then
    echo "Removing target directory."
    rm -rf "$TARGET"
  fi
  echo "Failed to install data (consult the above error messages)."
  exit 1
}

check_source || error
check_music_tools || error
check_language || error
check_target || error
download_packages || error
copy_music || error
copy_data || error
extract_packages || error
create_config_ini || error

echo "Data successfully installed."
