#!/usr/bin/env bash

RELEASE=`date +%Y%m%d`
THISDIR=($(cd $(dirname $0); echo "$PWD"))
test "$THISDIR" = "." && THISDIR=${PWD}
FINALDEST=$PWD/android-ndk-r10

# Clone the NDK (need a way to specify a version, but what
# about Google's click-through license agreement - maybe
# git sha1s would be best?)
if [ ! -d ndk ]; then
  git clone https://android.googlesource.com/platform/ndk.git ndk
  pushd ndk
  git am ${THISDIR}/ndk-git-patches/0001-Add-target-zlib-to-mingw-w64-build.patch || (echo "patch for zlib static build failed" && exit 1)
  git am ${THISDIR}/ndk-git-patches/0002-mingw-w64-add-another-patch-for-widl-compilation.patch || (echo "patch for widl mkstemps failed" && exit 1)
  popd
fi

# Pickup the NDK development defaults.
. ndk/build/tools/dev-defaults.sh

# Simple option parsing stuff.
option_to_var()
{
  echo $(echo $1 | tr '[a-z]' '[A-Z]' | tr '-' '_')
}
var_to_option()
{
  echo --$(echo $1 | tr '[A-Z]' '[a-z]' | tr '_' '-')
}
option()
{
  OPTION=$(var_to_option $1)
  if [ -n "$3" ]; then
    ALL_OPTIONS_TEXT=$ALL_OPTIONS_TEXT" $OPTION="$2"\n $3\n\n"
  else
    ALL_OPTIONS_TEXT=$ALL_OPTIONS_TEXT" $OPTION="$2"\n\n"
  fi
  ALL_OPTIONS="$ALL_OPTIONS "$1
  eval $1=\"$2\"
}
option_output_all()
{
  for OPTION in $ALL_OPTIONS; do
    OPTION_OUTPUT="$OPTION_OUTPUT $(var_to_option $OPTION)=${!OPTION}"
  done
  if [ ! $1 = "" ]; then
    echo -e "#!/bin/bash\n./$(basename $0)$OPTION_OUTPUT" > $1
  else
    echo -e "#!/bin/bash\n./$(basename $0)$OPTION_OUTPUT"
  fi
}
print_help()
{
  echo    ""
  echo    "Simple script to cross-compile the Android NDK's Python and GDBs"
  echo    "Written by Ray Donnelly <mingw.android@gmail.com> for Qt Project"
  echo    ""
  echo -e "Options are (--option=default)\n\n$ALL_OPTIONS_TEXT"
}
commas_to_spaces ()
{
  echo "$@" | tr ',' ' '
}
spaces_to_commas ()
{
  echo "$@" | tr ' ' ','
}

HOST_BITNESSES_DEFAULT=32,64
TARG_BITNESSES_DEFAULT=32
# Linux must come first in this list!
HOST_SYSTEMS_DEFAULT=linux,windows,darwin
# arm64,x86_64,mips64 don't currently work with build-host-gdb.sh yet!
TARG_ARCHES_DEFAULT="arm,x86,mips"
# 4.6 isn't dead yet and 4.9 isn't released yet.
DEFAULT_GCC_VERSION_LIST="4.6 4.8"
GCC_VERSION_LIST_DEFAULT=$(spaces_to_commas "${DEFAULT_GCC_VERSION_LIST}")

option HOST_BITNESSES "$HOST_BITNESSES_DEFAULT"   "The host bitness(es) you want"
option TARG_BITNESSES "$TARG_BITNESSES_DEFAULT"   "The target bitness(es) you want (only 32bit works for now!)"
option GCC_VERSIONS   "$GCC_VERSION_LIST_DEFAULT" "The GCC version(s) you want GDBs for"
option HOST_SYSTEMS   "$HOST_SYSTEMS_DEFAULT"     "The host systems to build for"
option ARCHES         "$TARG_ARCHES_DEFAULT"      "The target arches to build GDBs for"

# Check for command-line modifications to options.
while [ "$#" -gt 0 ]; do
  OPT="$1"
  case "$1" in
    --*=*)
      VAR=$(echo $1 | sed "s,^--\(.*\)=.*,\1,")
      VAL=$(echo $1 | sed "s,^--.*=\(.*\),\1,")
      VAR=$(option_to_var $VAR)
      eval "$VAR=\$VAL"
      ;;
    *help)
      print_help
      exit 0
      ;;
  esac
  shift
done

HOST_BITNESSES_LIST="$(commas_to_spaces ${HOST_BITNESSES})"
HOST_SYSTEMS_LIST="$(commas_to_spaces ${HOST_SYSTEMS})"
ARCHES_LIST="$(commas_to_spaces ${ARCHES})"
GCC_VERSIONS_LIST="$(commas_to_spaces ${GCC_VERSIONS})"

if [ ! -d development ]; then
  git clone https://android.googlesource.com/platform/development.git development
fi
if [ ! -d bionic ]; then
  git clone https://android.googlesource.com/platform/bionic.git bionic
fi

if [ -z "${HOST_BITNESSES}" ]; then
  echo "Please pass 32 and/or 64 for the host bitness wanted"
  exit 1
fi

export NDK=$PWD/ndk
export ANDROID_NDK_ROOT=$NDK
#export NDK_BUILDTOOLS_PATH=$NDK/build/tools

var_value ()
{
  echo "$`echo $1`"
}
register_var_option ()
{
  eval $2=$(var_value $2)
  echo $2=${!2}
}
extract_parameters ()
{
  true
}
log ()
{
  true
}

rebase_absolute_paths ()
{
  local _PATH=$1
  local _FIND=$2
  local _REPL=$3

  FILES="$(find $_PATH \( -name '*.la' -or -path '*/ldscripts/*' -or -name '*.conf' -or -name 'mkheaders' -or -name '*.py' -or -name '*.h' \))"
  for FILE in $FILES; do
    sed -i "s#${_FIND}#${_REPL}#g" $FILE
  done
}

download_or_build_toolchain_for_host ()
{
  LINUX_X86_CC_URL="https://android.googlesource.com/platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6"
  LINUX_X64_64_CC_URL="https://android.googlesource.com/platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6"

  if [ "${1}" = "linux-x86" -o "${1}" = "linux-x86_64" ]; then
    BASENAME=$(basename $LINUX_X86_CC_URL)
    if [ ! -d prebuilts/gcc/linux-x86/host/${BASENAME} ]; then
        (
         mkdir -p prebuilts/gcc/linux-x86/host
         cd prebuilts/gcc/linux-x86/host
         git clone $LINUX_X86_CC_URL ${BASENAME}
        )
        rebase_absolute_paths "prebuilts/gcc/linux-x86/host/${BASENAME}" "/tmp/ahsieh-gcc-32-x19222/2/i686-linux-glibc2.7-4.6" "$PWD/prebuilts/gcc/linux-x86/host/prebuilts-gcc-linux-x86-host-i686-linux-glibc2.7-4.6"
        # This is just to catch one file ;-)
        rebase_absolute_paths "prebuilts/gcc/linux-x86/host/${BASENAME}" "/tmp/ahsieh-gcc-32-x19222/1/i686-linux-glibc2.7-4.6" "$PWD/prebuilts/gcc/linux-x86/host/prebuilts-gcc-linux-x86-host-i686-linux-glibc2.7-4.6"
    fi

    BASENAME=$(basename $LINUX_X64_64_CC_URL)
    if [ ! -d prebuilts/gcc/linux-x86/host/${BASENAME} ]; then
        (
         mkdir -p prebuilts/gcc/linux-x86/host
         cd prebuilts/gcc/linux-x86/host
         git clone $LINUX_X64_64_CC_URL ${BASENAME}
        )
        rebase_absolute_paths "prebuilts/gcc/linux-x86/host/${BASENAME}" "" "$PWD/prebuilts/gcc/linux-x86/host"
    fi

    if [ ! -d prebuilts/tools ]; then
        (
         cd prebuilts
         git clone https://android.googlesource.com/platform/prebuilts/tools
         # seems this isn't being updated?
         sed -i "s/x86_64-linux-glibc2.7-4.6/${BASENAME}/" tools/gcc-sdk/gcc
        )
    fi
    PATH=$PWD/prebuilts/tools/gcc-sdk:"$PATH"
  fi

  BINPREFIX=$PWD/prebuilts/tools/gcc-sdk/
  if [ "${1}" = "windows-x86" -o "${1}" = "windows-x86_64" ]; then
    MINGW_PACKAGE_DIR=$PWD/mingw-w64-package
    if [ ! -f $MINGW_PACKAGE_DIR/x86_64-w64-mingw32-linux-x86_64.tar.bz2 ]; then
      mkdir -p ${MINGW_PACKAGE_DIR}
      echo "./ndk/build/tools/build-mingw64-toolchain.sh \
      --mingw-version=svn@5861 \
      --gcc-version=4.8.3 \
      --binutils-version=2.24 \
      --binprefix=${BINPREFIX} \
      --package-dir=$MINGW_PACKAGE_DIR \
      --work-dir=$PWD/buildmingw --verbose --verbose"
      ./ndk/build/tools/build-mingw64-toolchain.sh \
        --mingw-version=svn@5861 \
        --gcc-version=4.8.3 \
        --binutils-version=2.24 \
        --binprefix=${BINPREFIX} \
        --package-dir=$MINGW_PACKAGE_DIR \
        --work-dir=$PWD/buildmingw  --verbose --verbose
    fi
    if [ ! -d prebuilts/x86_64-w64-mingw32 ]; then
        (
          cd prebuilts
          tar -xf $MINGW_PACKAGE_DIR/x86_64-w64-mingw32-linux-x86_64.tar.bz2
        )
    fi
    PATH=$PWD/prebuilts/x86_64-w64-mingw32/bin:"$PATH"
  fi

  if [ "${1}" = "darwin-x86" -o "${1}" = "darwin-x86_64" ]; then
    if [ ! -d prebuilts/darwin ]; then
      (
       mkdir -p prebuilts/darwin
       cd prebuilts/darwin
       curl -S -L -O https://mingw-and-ndk.googlecode.com/files/multiarch-darwin11-cctools127.2-gcc42-5666.3-llvmgcc42-2336.1-Linux-120724.tar.xz
       tar -xJf multiarch-darwin11-cctools127.2-gcc42-5666.3-llvmgcc42-2336.1-Linux-120724.tar.xz
      )
    fi
    if [ ! -d prebuilts/darwin/MacOSX10.7.sdk ]; then
      (
       cd prebuilts/darwin
       tar -xjf $HOME/Dropbox/darwin-compilers-work/MacOSX10.7.sdk.tar.bz2
      )
    fi
    if [ ! -d prebuilts/darwin/MacOSX10.7.sdk ]; then
        echo "Please acquire a Mac OSX SDK and put it in prebuilts/darwin/MacOSX10.7.sdk"
        exit 1
    fi
    PATH=$PWD/prebuilts/darwin/bin:"$PATH"
    export DARWIN_TOOLCHAIN=$PWD/prebuilts/darwin/apple-osx/bin/i686-apple-darwin11
    export DARWIN_SYSROOT=$PWD/prebuilts/darwin/MacOSX10.7.sdk
  fi
}

arch_to_folder ()
{
  case $1 in
    arm)
      echo "arm-linux-androideabi"
      return 0
      ;;
    mips)
      echo "mipsel-linux-android"
      return 0
      ;;
    x86)
      echo "x86"
      return 0
      ;;
    *)
      echo "unknown"
      return 1
      ;;
  esac
}

arch_to_prog_prefix ()
{
  case $1 in
    arm)
      echo "arm-linux-androideabi"
      return 0
      ;;
    mips)
      echo "mipsel-linux-android"
      return 0
      ;;
    x86)
      echo "i686-linux-android"
      return 0
      ;;
    *)
      echo "unknown"
      return 1
      ;;
  esac
}

arch_and_gcc_version_to_gdb_version ()
{
  local _PROG_PREFIX=$(arch_to_prog_prefix ${1})
  _PROG_PREFIX=$_PROG_PREFIX"-${2}"
  get_default_gdb_version_for_gcc ${_PROG_PREFIX}
}

system_name_to_folder_name ()
{
  case $1 in
    windows-x86)
      echo "windows"
      ;;
    *)
      echo "$1"
      ;;
  esac
}

do_build ()
{
  SYSTEMS_NEEDING_PYTHON=
  SYSTEMS_NEEDING_GDB=
  SYSTEMS=
  for HOST_SYSTEM in ${HOST_SYSTEMS_LIST}; do
    for HOST_BITNESS in ${HOST_BITNESSES_LIST}; do
      if [ "${HOST_BITNESS}" = "32" ]; then
        HOST_SYSTEM2=$HOST_SYSTEM"-x86"
      else
        HOST_SYSTEM2=$HOST_SYSTEM"-x86_64"
      fi
      if [ -n "${SYSTEMS}" ]; then
        SYSTEMS=$SYSTEMS",${HOST_SYSTEM2}"
      else
        SYSTEMS="${HOST_SYSTEM2}"
      fi
      HOST_FOLDER=$(system_name_to_folder_name ${HOST_SYSTEM2})
      if [ ! -f ndk-build-gdb-temp./${RELEASE}/prebuilt/ndk-python-${HOST_FOLDER}.tar.bz2 ]; then
        if [ -n "${SYSTEMS_NEEDING_PYTHON}" ]; then
          SYSTEMS_NEEDING_PYTHON=$SYSTEMS_NEEDING_PYTHON",${HOST_SYSTEM2}"
        else
          SYSTEMS_NEEDING_PYTHON="${HOST_SYSTEM2}"
        fi
      fi
      if [ ! -d buildgdb/install-host-${HOST_SYSTEM2} ]; then
        if [ -n "${SYSTEMS_NEEDING_GDB}" ]; then
          SYSTEMS_NEEDING_GDB=$SYSTEMS_NEEDING_GDB",${HOST_SYSTEM2}"
        else
          SYSTEMS_NEEDING_GDB="${HOST_SYSTEM2}"
        fi
      fi
      download_or_build_toolchain_for_host ${HOST_SYSTEM2}
    done
  done

  echo "SYSTEMS_NEEDING_PYTHON are: ${SYSTEMS_NEEDING_PYTHON}"
  echo "SYSTEMS_NEEDING_GDB are: ${SYSTEMS_NEEDING_GDB}"

  if [ -n "${SYSTEMS_NEEDING_PYTHON}" ]; then
    ./ndk/build/tools/build-host-python.sh \
      --package-dir=$PWD/ndk-build-gdb-temp.${SYSTEM}/${RELEASE}/prebuilt \
      --toolchain-src-dir=${PWD}/toolchain-src \
      --systems=${SYSTEMS_NEEDING_PYTHON} \
      --build-dir=$PWD/buildpython \
      --verbose --verbose
  fi

  if [ -n "${SYSTEMS_NEEDING_GDB}" ]; then
    ./ndk/build/tools/build-host-gdb.sh \
      --toolchain-src-dir=${PWD}/toolchain-src \
      --gdb-version=7.3.x,7.6,7.7 \
      --python-version=2.7.5 \
      --systems=${SYSTEMS_NEEDING_GDB} \
      --python-build-dir=$PWD/buildpython \
      --build-dir=$PWD/buildgdb \
      --arch=${ARCHES} \
      --verbose --verbose
  fi
}

do_install ()
{
  for HOST_BITNESS in ${HOST_BITNESSES_LIST}; do
    for HOST_SYSTEM in ${HOST_SYSTEMS_LIST}; do
      if [ "${HOST_BITNESS}" = "32" ]; then
        HOST_SYSTEM=$HOST_SYSTEM"-x86"
      else
        HOST_SYSTEM=$HOST_SYSTEM"-x86_64"
      fi
      HOST_FOLDER=$(system_name_to_folder_name ${HOST_SYSTEM})
      DEST=${FINALDEST}/${HOST_FOLDER}/android-ndk-r10
      [ -d ${DEST} ] && rm -rf ${DEST}
      mkdir -p ${DEST}
      tar -xf ndk-build-gdb-temp./${RELEASE}/prebuilt/ndk-python-${HOST_FOLDER}.tar.bz2 -C ${DEST}
      for ARCH in $ARCHES_LIST; do
        TARG_FOLDER=$(arch_to_folder ${ARCH})
        PROG_PREFIX=$(arch_to_prog_prefix ${ARCH})
        mkdir -p ${DEST}/build/tools/toolchain-licenses
        cp -f toolchain-src/gcc/gcc-4.8/COPYING{.LIB,} ${DEST}/build/tools/toolchain-licenses
        pushd toolchain-src/python/Python-2.7.5
          cp LICENSE ${DEST}/build/tools/toolchain-licenses/PYTHON-2.7.5.LICENSE
          cp $0 ${DEST}/build/tools/build-gdbs.sh
          git log . > ${DEST}/build/tools/toolchain-licenses/PYTHON-2.7.5.NDK.MODIFICATIONS
        popd
        for GCC_VERSION in $GCC_VERSIONS_LIST; do
          GDB_VERSION=$(arch_and_gcc_version_to_gdb_version ${ARCH} ${GCC_VERSION})
          # The installed in ndk location, is missing some things (lib, lib32 folders) but should be ok.
          SOURCES=${PWD}/ndk/toolchains/gdb-${TARG_FOLDER}-${GDB_VERSION}/prebuilt/${HOST_FOLDER}/*
          # The initial, real results from make install are here:
          # SOURCES=${PWD}/buildgdb/install/${HOST_SYSTEM}/gdb-${TARG_FOLDER}-${GDB_VERSION}/*
          TARGET_DIR=${DEST}/toolchains/${TARG_FOLDER}-${GCC_VERSION}/prebuilt/${HOST_FOLDER}
          echo "Copying $SOURCES to $TARGET_DIR"
          [ -d ${TARGET_DIR} ] || mkdir -p ${TARGET_DIR}
          for SOURCE in $SOURCES; do
            if [ ! -d ${SOURCE} ]; then
              echo "Error: Source directory $SOURCE doesn't exist"
            fi
            cp -rf ${SOURCE} ${TARGET_DIR}
          done
        done
      done
    done
  done
}

do_package ()
{
  for HOST_BITNESS in ${HOST_BITNESSES_LIST}; do
    for HOST_SYSTEM in ${HOST_SYSTEMS_LIST}; do
      if [ "${HOST_BITNESS}" = "32" ]; then
        HOST_SYSTEM=$HOST_SYSTEM"-x86"
      else
        HOST_SYSTEM=$HOST_SYSTEM"-x86_64"
      fi
      HOST_FOLDER=$(system_name_to_folder_name ${HOST_SYSTEM})
      SOURCE=${FINALDEST}/${HOST_FOLDER}
      DEST=${FINALDEST}/android-ndk-r10-${HOST_FOLDER}-gdb.tar
      pushd $SOURCE
      case $HOST_SYSTEM in
        windows*|linux*)
          [ -f ${DEST}.xz ] || tar -cJf ${DEST}.xz android-ndk-r10
        ;;
        darwin*)
          [ -f ${DEST}.bz2 ] || tar -cjf ${DEST}.bz2 android-ndk-r10
        ;;
      esac
      popd
    done
  done
}

do_downloads ()
{
  if [ ! -d toolchain-src ]; then
    mkdir toolchain-src
    pushd toolchain-src
    git clone $OPTION_GIT_BASE/python.git python
    pushd python > /dev/null 2>&1
      git am ${THISDIR}/python-git-patches/0001-Use-os.path.normpath-line-on-GCC-include-paths.patch
    popd > /dev/null 2>&1
    git clone $OPTION_GIT_BASE/gdb.git gdb
    git clone $OPTION_GIT_BASE/build.git build
    git clone $OPTION_GIT_BASE/gcc.git gcc
    git clone $OPTION_GIT_BASE/expat.git expat
    popd
  fi
}

do_everything ()
{
  trap - EXIT
  echo calling do_downloads
  do_downloads
  echo calling do_build
  do_build
  echo calling do_install
  do_install
  do_package
}

# Run download-toolchain-sources.sh to get various variables and
# functions defined. However, it exits with a failure if run like
# this, so trap that failure and proceed on to do_everything().
# Yeah this is a nasty hack. Still, no one will read this far.
trap do_everything EXIT
. $NDK/build/tools/download-toolchain-sources.sh || true 
