#!/bin/bash -e

# pass your docker hub login name as $1, defaults to your user name
# you should have a repositories named ubuntu and debian
# if you have your own repository, you can also prepend it:
# my.repo.url:5000/myname the script will then append ubuntu or debian
# e.g. to my.repo.url:5000/myname/ubuntu:trusty-amd64
# please login to docker before you start this script
docker_user=${1:-${docker_user:-$(id -un)}}

if test -f /etc/setup-debootstrap.conf; then
    . /etc/setup-debootstrap.conf
fi
if test -f ~/setup-debootstrap.conf; then
    . ~/setup-debootstrap.conf
fi

tmpdir=${tmpdir:-"/var/tmp/chroots"}
test -d "${tmpdir}" || mkdir -p "${tmpdir}"
docker_user=${docker_user:-${USER}}
if test -z "${ports[@]}"; then
    #ports=( armhf powerpc ppc64el s390x arm64   )
    #qemus=( arm   ppc     ppc64   s390x aarch64 )
    ports=( armhf )
    qemus=( arm   )
fi
numports=${#ports[@]}
if test -z "$archs"; then
    case "$(dpkg --print-architecture)" in
        (amd64) archs="amd64 i386";;
        (*) archs=$(dpkg --print-architecture);;
    esac
    for ((i=0; i<$numports; ++i)); do
        if test -x /usr/bin/qemu-${qemus[$i]}-static; then
            archs+=" ${ports[$i]}"
        fi
    done
fi
excludes="precise-armhf"
no_universe="jessie sid wheezy"

ubuntu_qt5="zesty yakkety xenial wily vivid trusty"
ubuntu_qt4="precise"
debian_qt5="jessie sid"
debian_qt4="wheezy"
# not yet successfully installable: debian stretch and buster

ubuntu=("${ubuntu_qt5}" "${ubuntu_qt4}")
debian=("${debian_qt5}" "${debian_qt4}")
distros=(${distros:-"${ubuntu[@]}" "${debian[@]}"})

packages_qt5="libpoppler-qt5-dev libpodofo-dev libqt5designer5 libqt5svg5-dev libqt5webkit5-dev qt5-default qt5-qmake qtbase5-dev qtbase5-dev-tools qttools5-dev qttools5-dev-tools"
packages_qt4="libqt4-core libqt4-designer libqt4-dev libqt4-webkit qt4-dev-tools qt4-qmake"
# |libqtcore4 |libqtwebkit-dev |libp11-kit-dev|libgnutls-dev
packages_base="apt-transport-https automake autotools-dev binutils-dev debhelper default-jdk-headless doxygen dpkg-dev g++ git graphviz libboost-thread-dev libcppunit-dev liblog4cxx-dev libpcsclite-dev libpkcs11-helper1-dev libproxy-dev libssl-dev libtool libz-dev lsb-release mscgen nodejs pandoc pkg-config software-properties-common subversion subversion-tools texinfo xvfb"
#package_not_in_yakkety="default-jdk-headless"
package_not_in_wily="default-jdk-headless"
package_not_in_vivid="default-jdk-headless liblog4cxx-dev"
package_not_in_trusty="default-jdk-headless liblog4cxx-dev"
package_not_in_jessie="default-jdk-headless liblog4cxx-dev"
package_not_in_precise="default-jdk-headless liblog4cxx-dev"
package_not_in_wheezy="default-jdk-headless liblog4cxx-dev nodejs"

if test -z "${packages[@]}"; then
    packages=("${packages_base} ${packages_qt5}" "${packages_base} ${packages_qt4}" "${packages_base} ${packages_qt5}" "${packages_base} ${packages_qt4}")
fi
if test -z "${index}" -a "${#distros[@]}" -ne "${#packages[@]}"; then
    echo "**** ERROR: number of distribution lists doesn't match package lists" 1>&2
    echo "            distribution lists: ${#distros[@]}" 1>&2
    echo "            package lists:      ${#packages[@]}" 1>&2
    exit 1
fi

fastmode=0;
limit=
arch=
while [ $# -gt 0 ]; do
    case "$1" in
        (-f|--fastmode) fastmode=1;;
        (-l|--limit) shift; limit=$1;;
        (-a|--arch) shift; arch=$1;;
        (*)
            echo "**** ERROR: unknown option $1" 1>&2
            exit 1;;
    esac
    shift
done

error() {
    tmpdir=$2
    disto=$3
    arch=$4
    echo "**** ERROR at ${0}:${1}" 1>&2
    echo ".... on $(eval echo \"${BASH_COMMAND}\")" 1>&2
    echo ".... tmpdir=$tmpdir arch=$arch distro=$distro" 1>&2
    
    exit 1
}

for ((i=0; i<${#distros[@]}; ++i)); do
    package="${packages[${index:-$i}]}"
    for distro in ${distros[$i]}; do
        prevent=package_not_in_${distro};
        instpkgs=${package}
        for pkg in ${!prevent}; do
            instpkgs=${instpkgs//${pkg}/}
        done
        if test -n "$limit" -a "$distro" != "$limit"; then
            continue
        fi
        if ! test -e /usr/share/debootstrap/scripts/${distro}; then
            echo "**** WARNING: skipping unsupported ${distro}" 1>&2
            continue;
        fi
        ubuntus="${ubuntu[@]}"
        if test "${ubuntus//${distro}/}" != "${ubuntus}"; then
            type="ubuntu"
        else
            type="debian"
        fi
        for arch in ${arch:-$archs}; do
            if [[ "${distro}-${arch}" = "$excludes" ]]; then
                continue;
            fi
            trap 'error "${LINENO}" "${tmpdir}" "${disto}" "${arch}"' ERR SIGINT
            echo "******** process $type $distro $arch ********" 1>&2
            if test -d "${tmpdir}/${distro}-${arch}"; then
                echo " ++++    already exists ${tmpdir}/${distro}-${arch}" 1>&2
                if test $fastmode -eq 1; then
                    continue;
                fi
            else
                if test "$(dpkg --print-architecture)" = "$arch" -o \( "$(dpkg --print-architecture)" = amd64 -a "$arch" = i386 \) ; then
                    echo " ----    install ${tmpdir}/${distro}-${arch}" 1>&2
                    sudo debootstrap --arch="$arch" "$distro" "${tmpdir}/${distro}-${arch}"
                else
                    for ((i=0; $i<$numports; ++i)); do
                        if test "${ports[$i]}" = "${arch}"; then
                            break;
                        fi
                    done
                    qemu="${qemus[$i]}"
                    if ! test -e /usr/bin/qemu-${qemu}-static; then
                        echo "**** WARNING: no emulator ${qemu} found, skipping ${arch}" 1>&2
                        continue;
                    fi
                    arch=${arch#*-}
                    echo " ----    install on $qemu ${tmpdir}/${distro}-${arch}" 1>&2
                    sudo debootstrap --foreign --arch="$arch" "$distro" "${tmpdir}/${distro}-${arch}"
                    sudo cp /usr/bin/qemu-${qemu}-static "${tmpdir}/${distro}-${arch}/usr/bin/qemu-${qemu}-static"
                    if test -f "${tmpdir}/${distro}-${arch}"/debootstrap/debootstrap; then
                        ls -l "${tmpdir}/${distro}-${arch}"/debootstrap/debootstrap
                    fi
                    sudo DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true LC_ALL=C LANGUAGE=C LANG=C chroot "${tmpdir}/${distro}-${arch}" dpkg --configure -a
                fi
            fi
            echo " ----    mount filesystems in ${tmpdir}/${distro}-${arch}" 1>&2
            for x in proc sys dev; do
                if mount | grep -q "${tmpdir}/${distro}-${arch}"/$x; then
                    sudo umount -flr "${tmpdir}/${distro}-${arch}"/$x
                fi
            done
            sudo mount -t proc proc "${tmpdir}/${distro}-${arch}"/proc
            sudo mount -t sysfs sys "${tmpdir}/${distro}-${arch}"/sys
            sudo mount -o bind /dev "${tmpdir}/${distro}-${arch}"/dev
            echo " ----    preconfigure debian packages in ${tmpdir}/${distro}-${arch}" 1>&2
            sudo chroot "${tmpdir}/${distro}-${arch}" debconf-set-selections <<EOF
console-setup   console-setup/fontsize-fb47     select  8x16
console-setup   console-setup/fontface47        select  Fixed
console-setup   console-setup/charmap47 select  UTF-8
console-setup   console-setup/store_defaults_in_debconf_db      boolean true
keyboard-configuration  console-setup/ask_detect        boolean false
keyboard-configuration  console-setup/detected  note
console-setup   console-setup/fontsize  string  8x16
console-setup   console-setup/fontsize-text47   select  8x16
console-setup   console-setup/codesetcode       string  Uni2
keyboard-configuration  console-setup/detect    detect-keyboard
console-setup   console-setup/codeset47 select  . Combined - Latin; Slavic Cyrillic; Greek
EOF
            echo " ----    prevent packages in ${tmpdir}/${distro}-${arch}" 1>&2
            for f in "dbus" "libpam-systemd*" "packagekit*" "policykit*" "colord"; do
                sudo chroot "${tmpdir}/${distro}-${arch}" <<EOF1
if ! grep -q "Package: $f" /etc/apt/preferences; then
cat >> /etc/apt/preferences <<EOF2

Package: $f
Pin-Priority: -100

EOF2
fi
EOF1
            done
            echo " ----    upgrade ${tmpdir}/${distro}-${arch}" 1>&2
            sudo chroot "${tmpdir}/${distro}-${arch}" apt-get -o Acquire::ForceIPv4=true update
            sudo chroot "${tmpdir}/${distro}-${arch}" apt-get -o Acquire::ForceIPv4=true -y -f install
            sudo chroot "${tmpdir}/${distro}-${arch}" apt-get -o Acquire::ForceIPv4=true -y upgrade
            sudo chroot "${tmpdir}/${distro}-${arch}" apt-get -o Acquire::ForceIPv4=true install -y python-software-properties software-properties-common || \
                sudo chroot "${tmpdir}/${distro}-${arch}" apt-get -o Acquire::ForceIPv4=true install -y software-properties-common
            if [[ "${distro}" = "${no_universe}" ]]; then
                sudo chroot "${tmpdir}/${distro}-${arch}" add-apt-repository universe || \
                    ( test "$type" != "debian" && \
                            sudo chroot "${tmpdir}/${distro}-${arch}" add-apt-repository "deb http://archive.ubuntu.com/ubuntu ${distro} universe" )
            fi
            sudo chroot "${tmpdir}/${distro}-${arch}" apt-get -o Acquire::ForceIPv4=true update
            sudo chroot "${tmpdir}/${distro}-${arch}" apt-get -o Acquire::ForceIPv4=true -y dist-upgrade
            echo " ----    cleanup ${instpkgs} to ${tmpdir}/${distro}-${arch}" 1>&2
            sudo chroot "${tmpdir}/${distro}-${arch}" apt-get -o Acquire::ForceIPv4=true autoremove --purge -y
            echo " ----    install ${instpkgs} to ${tmpdir}/${distro}-${arch}" 1>&2
            sudo chroot "${tmpdir}/${distro}-${arch}" apt-get -o Acquire::ForceIPv4=true install -y ${instpkgs}
            echo " ----    unmount filesystems in ${tmpdir}/${distro}-${arch}" 1>&2
            for x in proc sys dev; do
                if mount | grep -q "${tmpdir}/${distro}-${arch}"/$x; then
                    sudo umount -flr "${tmpdir}/${distro}-${arch}"/$x
                fi
            done
            echo " ----    import ${tmpdir}/${distro}-${arch} to ${docker_user}/${type}:${distro}-${arch}" 1>&2
            cd "${tmpdir}/${distro}-${arch}"
            sudo tar c . | docker import - "${docker_user}/${type}:${distro}-${arch}"
            echo " ----    push ${tmpdir}/${distro}-${arch} to ${docker_user}/${type}:${distro}-${arch}" 1>&2
            docker push "${docker_user}/${type}:${distro}-${arch}"
        done
    done
done
