#!/bin/bash

USER_HOME=$(eval echo ~${SUDO_USER})

if [ "$EUID" -ne 0 ]
then 
  echo "Please run as root"
  exit 1
fi

baseDir=$(pwd)

build=$baseDir/build

config=$baseDir/config

debian_version=$(lsb_release -sc 2>/dev/null)

pack_list=(live cli disk net firmware dm-common xfce4 cinnamon gui libreoffice vm)

declare -A pack_name
pack_name[dm-common]="Composant commun pour l' interface graphique"
pack_name[xfce4]="Environnement de bureau Xfce"
pack_name[cinnamon]="Environnement de bureau Cinnamon"
pack_name[gui]="Ensemble de logiciel graphique"
pack_name[libreoffice]="Libreoffice Writer et Calc"
pack_name[vm]="Driver Virtualisation"

pack_forced=(live cli disk net firmware)

#pack_default=(dm-common gui xfce4 cinnamon libreoffice)


nb_hooks=0
declare -a hook_checklist
for file in $config/hooks/live/*;
do
  basename="$(basename -s ".hook.chroot" $file)"
  hook_checklist+=($basename "" "ON")
  ((nb_hooks++))
  #default all hook 
  hooks+="$basename "
done

#default DISABLE sid
sid=-1

_usage()
{
  cat <<EOF
-d use default setings
-v force debian version
-o Specifie output folder
-i if set create iso instead of only squashfs
EOF
}

if [ -z "$1" ]
then
  _usage
  exit 1
fi

#export http_proxy="http://192.168.110.1:3142"

KERNEL_PARAM="boot=live components lang=fr_FR.UTF-8 locales=fr_FR.UTF-8 keyboard-layouts=fr keyboard-model=pc105 timezone=Europe/Paris utc=yes"

_check()
{

  if [ -z "$out" ]
  then
    printf "\e[31mPlease specifie output folder\e[0m\n"
    _usage
    exit 1
  fi

  if [ -d "$out" ]
  then
    printf "Write in \e[96m$out\e[0m folder\n"
    if [ "$(ls -A $out)" ]
    then
      printf "\e[91m$out is not empty be careful\e[0m\n"
    fi
  else
    printf "\e[31m$out is not a folder\e[0m\n"
    _usage
    exit 1
  fi

}

_choose()
{

  RESULT=$(whiptail --title "Make debian live system" --inputbox "Specifie Debian codename" 10 70 $debian_version 3>&1 1>&2 2>&3)
  [[ "$?" = 1 ]] && printf "\e[91mCancel\e[0m\n" && exit

  debian_version=$RESULT

  printf "Debian version of live system: \e[96m$debian_version\e[0m\n"

  whiptail --title "Make debian live system" --yesno "Do you want to use sid ?" 7 70 --defaultno 3>&1 1>&2 2>&3
  sid=$?

  [[ $sid -eq 0 ]] && printf "Using \e[96msid\e[0m\\e[0m\n"

  declare -a pack_checklist
  size=$((${#pack_list[@]}-(${#pack_forced[@]})))
  for pack in ${pack_list[@]}; do
    [[  "${pack_forced[*]}" =~ "$pack" ]] && continue
    #[[  "${pack_default[*]}" =~ "$pack" ]] && status="ON" || status="OFF"
    status="ON"
    
    pack_checklist+=($pack "${pack_name[$pack]}" $status)
  done

  RESULT=$(whiptail --title "Make debian live system" --checklist "Select pack list" 15 70 ${size} "${pack_checklist[@]}" 3>&1 1>&2 2>&3)
  [[ "$?" = 1 ]] && printf "\e[91mCancel\e[0m\n" && exit

  pack=("${pack_forced[@]} $(echo $RESULT | xargs)")

  printf "Pack list: \e[96m${pack[*]}\e[0m\n"


  RESULT=$(whiptail --title "Make debian live system" --checklist "Select hooks to use" 15 70 ${nb_hooks} "${hook_checklist[@]}" 3>&1 1>&2 2>&3)
  [[ "$?" = 1 ]] && printf "\e[91mCancel\e[0m\n" && exit

  hooks=$(echo $RESULT | xargs)

  printf "Hooks list: \e[96m${hooks[*]}\e[0m\n"

}

_config()
{

  mkdir -p $build/config

  cd $build

  ln -sr $config/includes.chroot $build/config
  ln -sr $config/packages.chroot $build/config

  lb clean
  lb clean --cache

  #--apt-http-proxy "http://192.168.110.1:3142" \
  lb config noauto \
  --architectures amd64 \
  --distribution $debian_version \
  --binary-images iso-hybrid \
  --archive-areas "main contrib non-free-firmware" \
  --debian-installer none \
  --apt-recommends false \
  --updates true \
  --security true \
  --source false \
  --backports true \
  --memtest none \
  --bootappend-live "$KERNEL_PARAM"

  rm $build/config/package-lists/*

  for file in ${pack[@]}; do
    ln -sr $config/package-lists/$file.list.chroot $build/config/package-lists/$file.list.chroot
  done

  for hook in ${hooks[@]}; do
    ln -sr $config/hooks/live/$hook.hook.chroot $build/config/hooks/live/$hook.hook.chroot
  done

}

_build()
{
  
  printf "\e[96mBootstrap new root filesystem\e[0m\n"
  lb bootstrap
  [[ $? -eq 0 ]] || _exit_error

  #printf "\e[96mBuild live OS file system\e[0m\n"
  #lb chroot
  #[[ $? -eq 0 ]] || _exit_error

  printf "\e[96mBuild live OS file system\e[0m\n"
  lb chroot_cache restore
  [[ $? -eq 0 ]] || _exit_error
  lb chroot_prep install all mode-archives-chroot
  [[ $? -eq 0 ]] || _exit_error
  lb chroot_devpts install
  [[ $? -eq 0 ]] || _exit_error
  lb chroot_proc install
  [[ $? -eq 0 ]] || _exit_error
  lb chroot_selinuxfs install
  [[ $? -eq 0 ]] || _exit_error
  lb chroot_sysfs install
  [[ $? -eq 0 ]] || _exit_error
  lb chroot_debianchroot install
  [[ $? -eq 0 ]] || _exit_error
  lb chroot_dpkg install
  [[ $? -eq 0 ]] || _exit_error
  lb chroot_tmpfs install
  [[ $? -eq 0 ]] || _exit_error
  lb chroot_sysv-rc install
  [[ $? -eq 0 ]] || _exit_error
  lb chroot_hosts install
  [[ $? -eq 0 ]] || _exit_error
  lb chroot_resolv install
  [[ $? -eq 0 ]] || _exit_error
  lb chroot_hostname install
  [[ $? -eq 0 ]] || _exit_error
  lb chroot_apt install
  [[ $? -eq 0 ]] || _exit_error
  lb chroot_archives chroot install
  [[ $? -eq 0 ]] || _exit_error
  lb chroot_linux-image 
  [[ $? -eq 0 ]] || _exit_error
  lb chroot_firmware 
  [[ $? -eq 0 ]] || _exit_error
  lb chroot_preseed 
  [[ $? -eq 0 ]] || _exit_error
  lb chroot_includes_before_packages 
  [[ $? -eq 0 ]] || _exit_error


  [[ $sid -eq 0 ]] && _sid


  lb chroot_package-lists install
  [[ $? -eq 0 ]] || _exit_error
  lb chroot_install-packages install
  [[ $? -eq 0 ]] || _exit_error
  lb chroot_package-lists live
  [[ $? -eq 0 ]] || _exit_error
  lb chroot_install-packages live
  [[ $? -eq 0 ]] || _exit_error
  lb chroot_includes_after_packages 
  [[ $? -eq 0 ]] || _exit_error
  lb chroot_hooks 
  [[ $? -eq 0 ]] || _exit_error
  lb chroot_hacks 
  [[ $? -eq 0 ]] || _exit_error
  lb chroot_interactive 
  [[ $? -eq 0 ]] || _exit_error

}

_build_remove()
{

  lb chroot_prep remove all mode-archives-chroot
  [[ $? -eq 0 ]] || exit
#  lb chroot_archives chroot remove
#  [[ $? -eq 0 ]] || exit
#  lb chroot_apt remove
#  [[ $? -eq 0 ]] || exit
  lb chroot_hostname remove
  [[ $? -eq 0 ]] || exit
  lb chroot_resolv remove
  [[ $? -eq 0 ]] || exit
  lb chroot_hosts remove
  [[ $? -eq 0 ]] || exit
  lb chroot_sysv-rc remove
  [[ $? -eq 0 ]] || exit
  lb chroot_tmpfs remove
  [[ $? -eq 0 ]] || exit
  lb chroot_dpkg remove
  [[ $? -eq 0 ]] || exit
  lb chroot_debianchroot remove
  [[ $? -eq 0 ]] || exit
  lb chroot_sysfs remove
  [[ $? -eq 0 ]] || exit
  lb chroot_selinuxfs remove
  [[ $? -eq 0 ]] || exit
  lb chroot_proc remove
  [[ $? -eq 0 ]] || exit
  lb chroot_devpts remove
  [[ $? -eq 0 ]] || exit
  lb chroot_cache save
  [[ $? -eq 0 ]] || exit


  [[ $sid -eq 0 ]] && echo "deb http://deb.debian.org/debian sid main" >> $build/chroot/etc/apt/sources.list


  # Write commit hash and build date
  echo "$(git -C $baseDir log -1 --pretty='%cd %h %s' --date=format:"%F")" >> $build/chroot/etc/debian_version
  echo "Build date: $(date +"%F %R")" >> $build/chroot/etc/debian_version

}

_sid()
{
  printf "\e[96mAdd sid repository\e[0m\n"
  echo "deb http://deb.debian.org/debian sid main" >> $build/chroot/etc/apt/sources.list.d/zz-sources.list
  chroot $build/chroot apt update

  cat <<EOF > $build/chroot/etc/apt/preferences.d/sid.pref
# testing pref :

# 100 <= P < 500: causes a version to be installed unless there is a
# version available belonging to some other distribution or the installed
# version is more recent

Package: *
Pin: release a=testing
Pin-Priority: 400

# unstable pref :

# 0 < P < 100: causes a version to be installed only if there is no
# installed version of the package

Package: *
Pin: release a=unstable
Pin-Priority: 50
EOF
}

_prep_mounts()
{

  printf "\e[96mPreparing root filesystem\e[0m\n"
  lb binary_chroot
  [[ $? -eq 0 ]] || exit

  # Chroot preparation component lists
  # We deliberately exclude 'debianchroot'
  CHROOT_PREP_MOUNTS="devpts proc selinuxfs sysfs"
  CHROOT_PREP_OTHER="dpkg tmpfs sysv-rc hosts resolv hostname apt"

  # Configuring chroot
  lb chroot_prep install "${CHROOT_PREP_MOUNTS}"
  [[ $? -eq 0 ]] || exit
  lb chroot_prep install "${CHROOT_PREP_OTHER}" mode-apt-install-binary mode-archives-chroot
  [[ $? -eq 0 ]] || exit
  lb chroot_archives chroot install
  [[ $? -eq 0 ]] || exit
  
}

_prep_umounts()
{

  # Deconfiguring chroot
  lb chroot_prep remove "${CHROOT_PREP_MOUNTS}"
  [[ $? -eq 0 ]] || exit
  lb chroot_prep remove "${CHROOT_PREP_OTHER}"
  [[ $? -eq 0 ]] || exit
  
}

_create_squashfs()
{

  printf "\e[96mBuilding root filesystem\e[0m\n"
  lb binary_rootfs
  [[ $? -eq 0 ]] || exit
  lb binary_linux-image
  [[ $? -eq 0 ]] || exit

  printf "\e[96mCopy filesystem\e[0m\n"
  cp -v $build/chroot/{initrd.img,vmlinuz} $out/
  cp -v $build/binary/live/filesystem.squashfs $out/
  chown $SUDO_UID:$SUDO_GID $out/{initrd.img,vmlinuz,filesystem.squashfs}

}

_create_iso()
{

  printf "\e[96mPrepare image\e[0m\n"
  lb binary_syslinux
  [[ $? -eq 0 ]] || exit
  lb binary_grub_cfg
  [[ $? -eq 0 ]] || exit
  lb binary_grub-efi
  [[ $? -eq 0 ]] || exit

  printf "\e[96mCreate image\e[0m\n"
  lb binary_iso
  [[ $? -eq 0 ]] || exit

  printf "\e[96mCopy image\e[0m\n"
  outiso="$out/live-${debian_version}-image.iso"
  cp -v $build/live-image-amd64.hybrid.iso $outiso
  chown $SUDO_UID:$SUDO_GID $outiso

}

_exit_error()
{
  printf "\e[91mError\e[0m\n"
  _build_remove
  _delete
  exit
}

_delete()
{
  printf "\e[96mDelete $build\e[0m\n"
  rm -r $build
}

while getopts "dv:o:i" OPTION; do
  case $OPTION in
  d)
    default=true
    ;;
  v)
    debian_version=${OPTARG}
    ;;
  o)
    out="$(realpath ${OPTARG})"
    ;;
  i)
    iso=true
    ;;
  *)
    _usage
    exit 1
    ;;
  esac
done

_check
[[ $default = true ]] && pack=("${pack_forced[@]} ${pack_default[@]}") || _choose
_config
_build
_build_remove

mkdir -p $build/chroot/etc/skel/.ssh
cp -v $USER_HOME/.ssh/{config,key_rsa_majalis,key_rsa_majalis.pub} $build/chroot/etc/skel/.ssh
ssh-keygen -f $USER_HOME/.ssh/known_hosts -q -H -F ssh.netdldata.net > $build/chroot/etc/skel/.ssh/known_hosts
 
 _prep_mounts
_create_squashfs
[[ $iso = true ]] && _create_iso
_prep_umounts

_delete
