#! /bin/bash

# Check ran as root
if ! [ "$(id -u)" = "0" ]; then
    echo "Run this builder must be root or with sudo"
    exit 1
fi

USAGE=$(cat <<EOF
Live CD builder
Usage: live-build-astra [OPTIONS]

OPTIONS
     -h|--help display this help and exit
     -d <distribution> create liveCD of given distribution
     -r <url> URL for distribution repo
     -i <filename> ISO image(s) to use as a source of packages and other stuff
(without -d, -r and -i options programm will be try to build image for current distribution with first repo from sources.list)

Example-1: live-build-astra
Example-2: live-build-astra -d smolensk -i "/usr/local/tmp/smolensk-current.iso;/usr/local/tmp/devel-smolensk-current.iso"
Example-3: live-build-astra -d orel -r ftp://FtpAddrOfRepo/repo
Example-4: live-build-astra -d smolensk -r "ftp://FtpAddrOfRepo/repo-main;ftp://FtpAddrOfRepo/repo-main-update;ftp://FtpAddrOfRepo/repo-devel"
EOF
)

usage () {
    echo "${USAGE}"
}

ln -sf bash /bin/sh
if [ "$(locale -a|grep -i 'ru_ru.utf')" = "" ]
then
   echo "Need locale ru_RU"
   echo "ru_RU.UTF-8 UTF-8" >> /etc/locale.gen
   locale-gen
fi

# Apply astra-changes (apt prevent this step in install/postinst/postrm)
rsync -a /usr/share/live-build-astra/build/ /usr/lib/live/build/
rsync -a /usr/share/live-build-astra/functions/ /usr/share/live/build/functions/

# Distribution and repo define
DISTRIB=""; repo=("" "" "" ""); IMAGE_LIST=""; URL_LIST=""
CLBR="/tmp/live-build-astra/sample_config"
LB_APPEND="boot=live net.ifnames=0 noautologin nox11autologin components username=astra-live locales=ru_RU.UTF-8,en_US.UTF-8 keyboard-layouts=us,ru keyboard-variants=, keyboard-options=grp:ctrl_shift_toggle,grp_led:scroll"
if [ -f "/etc/os-release" ]; then
  DISTRIB=`grep VARIANT_ID /etc/os-release | awk -F \= '{print $2}'`
  if [ ${#DISTRIB} -le 3 ]; then
   DISTRIB=`grep VERSION_CODENAME /etc/os-release | awk -F \= '{print $2}'`
  fi
fi
repo_line=`grep ^deb /etc/apt/sources.list | sed -n 1p`
repo[0]=`echo $repo_line | sed -e 's/\[.*\]//g' | awk '{print $2}'`
if [ ${#DISTRIB} -eq 0 ]; then
  DISTRIB=`echo $repo_line | sed -e 's/\[.*\]//g' | awk '{print $3}'`
fi
if [ $DISTRIB = "smolensk" -o $DISTRIB = "leningrad" -o $DISTRIB = "1.7_x86-64" -o $DISTRIB = "4.7_arm" ]; then
  has_parsec=1
else
  has_parsec=0
fi
if [ $has_parsec -eq 1 ]; then
  if [ $DISTRIB = "1.7_x86-64" ]; then
    STRAP_URL=${repo[0]}"/dists/"$DISTRIB"/Release"
    stealth_control=`curl -s $STRAP_URL | wc -l`
    if [ $stealth_control -eq 0 ]; then DISTRIB="smolensk"; fi
  fi
fi

while getopts "hd:r:i:-:" opt
do
  case $opt in
    h)
        usage
        exit 0
        ;;
    d)
        DISTRIB="$OPTARG"
        ;;
    r)
        URL_LIST="$OPTARG"
   ;;
    i)
        IMAGE_LIST="$OPTARG"
        ;;
    -)
   case $OPTARG in
     help) usage; exit 0;;
     *) echo "Wrong opts.Try again."; exit 1;;
   esac
  esac
done

pushd /usr/share/debootstrap/scripts
ln -nfs sid ${DISTRIB}
popd

safe_exit() {
  for psnum in `netstat -npl | grep python3 | grep -e "127.0.0.2" | awk '{print $NF}' | awk -F \/ '{print $1}'`; do kill -9 $psnum; done
  if ! [ -e /etc/mtab ]
  then
     if [ -e /proc/mounts/mtab ]
     then
       ln -s /proc/mounts/mtab /etc/mtab
     else
       ln -s /proc/mounts /etc/mtab
     fi
  fi
  for iso_mount in `grep -e "/mnt/loop" /etc/mtab | awk '{print $2}'`; do umount -l $iso_mount; done
}

lba_rollback() {
  find /usr/lib/live/build/ -name *.orig -exec bash -c 'tgt=${1/\.orig/}; cp -v {} $tgt' funcname {} \;
  find /usr/share/live/build/ -name *.orig -exec bash -c 'tgt=${1/\.orig/}; cp -v {} $tgt' funcname {} \;
}

# Mount iso images as local repo
safe_exit
if [ -d $CLBR ]; then rm -rf $CLBR; fi
mkdir -p /mnt/loop $CLBR
tar -xjvf /usr/share/live-build-astra/astra_templates.tar.bz2 -C $CLBR
if [ ${#IMAGE_LIST} -ne 0 ]; then
  idx=0; port=18010; img_list=("" "" "" ""); repo[1]=""
  IFS=';' read -ra img_list <<< "$IMAGE_LIST"
  for img in ${img_list[@]}
  do
    if [ ${#img} -eq 0 ]; then break; fi
    rbind="/mnt/loop/repo_"$idx
    repo[$idx]="http://127.0.0.2:"$port

    mkdir -p $rbind
    echo "mount $img $rbind"
    mount $img $rbind

    pushd $rbind
    python3 -m http.server $port --bind 127.0.0.2 > /dev/null 2>&1 &
    binded=`netstat -npl | grep python3 | grep -e "127.0.0.2:$port" | wc -l`
    while [ $binded -eq 0 ]
    do
       sleep 1
       binded=`netstat -npl | grep python3 | grep -e "127.0.0.2:$port" | wc -l`
    done
    popd

    idx=$((idx + 1))
    port=$((port + 1))
  done
fi

# Parse external repositories list
if [ ${#URL_LIST} -ne 0 ]; then
  idx=0; url_list=("" "" "" ""); repo[1]=""
  IFS=';' read -ra url_list <<< "$URL_LIST"
  for url in ${url_list[@]}
  do
    if [ ${#url} -eq 0 ]; then break; fi
    repo[$idx]=$url
    idx=$((idx + 1))
  done
fi

# Build processing
if [ ${#DISTRIB} -eq 0 -o ${#repo[0]} -eq 0 ]; then
  echo "Invalid distribution name or repo name. Try again."
  exit 1
fi

if [ -d "/opt/workload" ]; then
  rm -rf /opt/workload
fi
mkdir -p /opt/workload /opt/live_CD /opt/live_report

pushd /opt/workload
CONF_OPTS="--verbose --distribution ${DISTRIB} --mirror-bootstrap ${repo[0]}"
if [ $DISTRIB = "leningrad" ]; then
  CONF_OPTS=${CONF_OPTS}" -a e2k"
elif [ $DISTRIB = "4.7_arm" ]; then
  CONF_OPTS=${CONF_OPTS}" -a arm64"
fi
if [ ${#repo[1]} -eq 0 ]; then
  CONF_OPTS=${CONF_OPTS}" --parent-mirror-chroot ${repo[0]} --mirror-chroot ${repo[0]} --parent-mirror-binary ${repo[0]} --mirror-binary ${repo[0]}"
else
  CONF_OPTS=${CONF_OPTS}" --parent-mirror-chroot ${repo[0]} --mirror-chroot ${repo[1]} --parent-mirror-binary ${repo[0]} --mirror-binary ${repo[1]}"
fi
if [ ${#repo[2]} -eq 0 ]; then
  CONF_OPTS=${CONF_OPTS}" --mirror-first-sibling NULL"
else
  CONF_OPTS=${CONF_OPTS}" --mirror-first-sibling ${repo[2]}"
fi
if [ ${#repo[3]} -eq 0 ]; then
  CONF_OPTS=${CONF_OPTS}" --mirror-second-sibling NULL"
else
  CONF_OPTS=${CONF_OPTS}" --mirror-second-sibling ${repo[3]}"
fi
if [ $has_parsec -eq 1 ]; then
  CONF_OPTS=${CONF_OPTS}" --is-pdp-distr true"
else
  CONF_OPTS=${CONF_OPTS}" --is-pdp-distr false"
fi
scan_foreign_repos=`grep ^deb /usr/share/live-build-astra/customyze/external_repo.list | wc -l`
if [ $scan_foreign_repos -ne 0 ]; then
  CONF_OPTS=${CONF_OPTS}" --include-foreign-repo true"
else
  CONF_OPTS=${CONF_OPTS}" --include-foreign-repo false"
fi
CONF_OPTS=${CONF_OPTS}" --security false --updates false --linux-flavours generic --initramfs live-boot --firmware-chroot false --firmware-binary false"
CONF_OPTS=${CONF_OPTS}" --archive-areas main --apt-source-archives false --apt-indices false --loadlin false --win32-loader false --debian-installer false"
CONF_OPTS=${CONF_OPTS}" --debian-installer-gui false --zsync false"

lb config ${CONF_OPTS}
sed -e "s/APT_OPTIONS=\"--yes\"/APT_OPTIONS=\"--yes -oAPT::Get::Install-Suggests=false\"/" -i config/common
sed -e "s/^LB_BOOTAPPEND_LIVE=\"boot=live components quiet splash\"/LB_BOOTAPPEND_LIVE=\"${LB_APPEND}\"/" -i config/binary
sed -e "s/^Archive-Areas: main/Archive-Areas: main contrib non-free/" -i config/build

rsync -avu8 $CLBR/hooks/ config/hooks/
rsync -avu8 $CLBR/bootloaders config/
rsync -avu8 $CLBR/includes.chroot/ config/includes.chroot/
rsync -avu8 $CLBR/includes.binary/ config/includes.binary/
rsync -avu8 $CLBR/includes.source/ config/includes.source/
rsync -avu8 $CLBR/includes.bootstrap/ config/includes.bootstrap/
rsync -avu8 $CLBR/package-lists/ config/package-lists/
if [ -f config/bootloaders/grub-pc/grub.cfg ]; then
  if [ -f /usr/share/live-build-astra/customyze/boot.yml ]; then
    alt_delay=`grep ^timeout /usr/share/live-build-astra/customyze/boot.yml| awk -F ": " '{print $2}'`
    sed -e "s/GRUBTMT/"${alt_delay}"/" -i config/bootloaders/grub-pc/grub.cfg
  else
    sed -e "s/GRUBTMT/10/" -i config/bootloaders/grub-pc/grub.cfg
  fi
fi

# Add/remove custom packages
if [ -s /usr/share/live-build-astra/customyze/astra_extend.list ]; then
  cp -v /usr/share/live-build-astra/customyze/astra_extend.list config/package-lists/
fi
if [ -s /usr/share/live-build-astra/customyze/shrink.roster ]; then
  mkdir -p config/includes.source/shrink-list
  cp -v /usr/share/live-build-astra/customyze/shrink.roster config/includes.source/shrink-list/
fi
# Add custom deb-files
if [ -d /usr/share/live-build-astra/customyze/extra_pkgs ]; then
  ext_deb_num=`find /usr/share/live-build-astra/customyze/extra_pkgs -maxdepth 1 -mindepth 1 -type f | wc -l`
  if [ $ext_deb_num -ne 0 ]; then
    cp -r /usr/share/live-build-astra/customyze/extra_pkgs config/includes.source/
  fi
fi

set -o pipefail && lb build |& tee /opt/live_report/build.log

# Finalyze
if [ $? -ne 0 ]; then
  safe_exit
  lba_rollback
  rm -rf $CLBR
  echo "Build was failed. See /opt/live_report/build.log for details."
  exit 1
fi

find . -maxdepth 1 -name "*.iso" -exec mv -v {} /opt/live_CD/ \;
popd

# Final clean
#rm -rf /opt/workload $CLBR /opt/live_report
safe_exit
lba_rollback
pushd /opt/live_CD; ls -l; popd
