#!/bin/bash
# install-f123light.sh
# Description: Installer script for F123Light on x86_64 machines
#
# Copyright 2019, F123 Consulting, <information@f123.org>
# Copyright 2019, Storm Dragon, <storm_dragon@linux-a11y.org>
#
# This is free software; you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free
# Software Foundation; either version 3, or (at your option) any later
# version.
#
# This software is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this package; see the file COPYING.  If not, write to the Free
# Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
#
# This script is based off vm.sh located at https://stormdragon.tk/scripts/vm.sh
#
#--code--

# the gettext essentials
export TEXTDOMAIN=install-f123light.sh
export TEXTDOMAINDIR=/usr/share/locale
source gettext.sh

# Log writing function
log() {
    # Usage: command | log for just stdout.
	# Or command |& log for stderr and stdout.
    while read -r line ; do
        echo "$line" | sudo tee -a "$logFile"
    done
}
 
# Log file name is /var/log/scriptname
logFile="/var/log/${0##*/}"
# Clear previous logs
echo -n | sudo tee "$logFile" &> /dev/null

# Check if this script is already running
if [ $(ps ux | grep "$(basename $0)" |grep -v grep | wc -l) -gt 2 ] ; then
[ "$1" = "-a" ] || echo "This script already appears to be running... Exiting."
exit 1
fi

# Find out if we are efi or not.
if [[ -d /sys/firmware/efi ]]; then
    efi="yes"
else
    efi="no"
fi

gpgkeys=('1E14FA260F577600704793200DD7721ADC85709B' '8E322618C859858A0A11205F5BEA237143DDC193')
disk=sda
# Disk will be chosen by user once implemented
diskSize=$(lsblk -b -n -o size /dev/${disk} |head -n1)
bootSize=468
rootSize=30000
if [ $diskSize -le 36000000000 ];then
rootSize=15000
fi
homeSize=-1 # from last partitian to end of disk leaving enough space for gpt.
diskPrefix=$disk
if [[ $diskPrefix =~ (mmcblk|nvme).+ ]];then
diskPrefix=${diskPrefix}p
fi

# check internet and connect wifi if not connected
if ! ping -c4 1.1.1.1 &> /dev/null ; then
read -p "You don't seem to be connected to the internet. Would you like to connect via wifi? (y/n)" wifi
if [ "$wifi" = "y" ] ; then
echo "Once you press enter, a menu will open with all available wifi networks listed. Arrow to the one you want to use and press enter twice. Once you do this, if a password is required for your wifi network you must enter it, then press enter. Once wifi is connected you may continue with the installation."
read -p  "Press enter to continue or control+c to quit." continue
while : ; do
wifi-menu
if [ $? -ne 0 ] ; then
read -p "Wifi didn't seem to connect properly. Would you like to try again? (y/n)" wifi
if [ "$wifi" != "y" ] ; then
echo "Wifi couldn't connect. This installer cannot continue. If you wish to connect manually, do so and run $0 again."
exit 1
fi
else
break
fi
done
else
echo "This installer requires internet to run. Please connect manually and run $0 again."
exit 1
fi
fi

# Load files
echo "Loading, please wait..."
# Make sure we have git installed
pacman -Syy --needed --noconfirm git |& log &> /dev/null
for i in content-F123Light files-F123Light F123Light ; do
    case "$i" in
    "files-F123Light") branch="x86";;
    *) branch="master";;
    esac
    if [[ -d "/tmp/${i}" ]]; then
        git -C "/tmp/${i}" pull -q
        git -C "/tmp/${i}" checkout -b  ${branch} |& log &> /dev/null
    else
        if git clone -q --depth 1 -b $branch https://gitlab.com/f123/${i}.git /tmp/${i} ; then
            echo "Cloned ${i}" | log &> /dev/null
        else
            echo "$(gettext "Failed to download required files. Please make sure you are connected to the internet.")" | log
            exit 1
        fi
    fi
done

#get information
echo
echo "Welcome! Before I create your F123Light installation, I need to ask you a couple questions."
# Find out if we are installing to a vm?
read -p "Are you installing a virtual machine? (y/n) " vm
if [ "${vm^}" = "Y" ]; then
vm="yes"
else
vm="no"
fi
if [ "$vm" = "no" ]; then
echo "Do you want this script to partition your drive for you? If yes, the whole drive will be used for F123Light, and all data that existed on the drive before will be erased."
read -p "If no, you will need to create partitions and file systems and mount them to /mnt. (y/n) " format
if [ "${format^}" = "Y" ]; then
format="yes"
else
format="no"
fi
if [[ -z "$format" ]]; then
    echo "Format was not set to yes nor no." | log
fi
fi

#Verify information
echo | log
echo "----------------------------------------------------------------------" | log
msg="You are"
if [[ "$vm" == "no" ]]; then
msg+=" not"
fi
echo "${msg} installing to a virtual machine." | log
echo "This computer will be called: f123light" | log
echo "Your root password will be: root" | log
echo | log
echo "Your user account is: f123" | log
echo "Your user account password is: f123" | log
echo | log
if [[ "$vm" == "no" ]]; then
echo "You are installing to disk, not virtual machine." | log
if [[ "$format" = "yes" ]]; then
echo "this script will automatically partition the disk for you. All previous data will be erased." | log
else
echo "You chose to manually handle partitions and file systems. Please make sure your desired directory structure is mounted to /mnt/" | log
fi
echo | log
fi
read -p "Press enter to continue: " continue
echo
echo "Note: When you press enter a lot of things will happen and you may wish to turn off speech during this process."
echo "To do so, if you have a numeric keypad, press numpad insert pluss numpad enter."
echo "If you are using a laptop, press and hold control, then press and hold capslock, finally press enter."
echo "This is a toggle, so to reenable speech, simply press the same keyboard shortcut again."
echo "Also note: when pacman installs the reflector package, it will rate the speed of arch linux package servers. This may take several minutes, so be patient."
unset continue
read -p "Continue with the installation? (y/n): " continue
if [ "${continue^}" != "Y" ]; then
exit 0
fi

# Add F123Light version of pacman.conf
if ! grep -q '\[f123light\]' /etc/pacman.conf ; then
   sed -i -e 's/\[core\]/[f123light]\nServer = https:\/\/packages.f123.org\/$arch\n\n[core]/' /etc/pacman.conf
fi

# Make sure system time is correct, and pacman-key is correct
ntpd -g |& log
pacman-key --populate archlinux |& log

# add f123 keys to the keyring.
pacman-key --recv-keys ${gpgkeys[@]}
pacman-key --lsign ${gpgkeys[@]}

# Synchronize repositories and install reflector if needed.
pacman -Syy --needed --noconfirm reflector |& log

# Now that we have reflector, run it to get best mirrors.
/usr/bin/reflector -f 10 -a 6 > /tmp/mirrorlist
F="$(< /tmp/mirrorlist)"
[ -n "$F" ] && mv /tmp/mirrorlist /etc/pacman.d/mirrorlist

# make partitions
if [[ "$format" == "yes" || "$vm" == "yes" ]]; then
    wipefs --all /dev/$disk |& log
    dd if=/dev/zero of=/dev/$disk bs=1M count=8 |& log
    if [[ "$efi" = "yes" ]]; then
        boot=1
        parted -s -a optimal -- /dev/$disk mklabel gpt \
            mkpart primary 3MiB ${bootSize}MiB set 1 esp on \
            mkpart primary $(( 3 + $bootSize ))MiB ${rootSize}MiB \
             mkpart primary $(( 3 + $bootSize + $rootSize ))MiB ${homeSize}MiB |& log
    else
        if [[ $diskSize -gt 2000000000000 ]]; then
            boot=2
            parted -s -a optimal -- /dev/$disk mklabel gpt \
                mkpart primary 1MiB 2MiB set 1 bios_grub on \
                mkpart primary 3MiB ${bootSize}MiB set 2 boot on \
                mkpart primary $(( 3 + $bootSize ))MiB ${rootSize}MiB \
                 mkpart primary $(( 3 + $bootSize + $rootSize ))MiB ${homeSize}MiB \
               disk_toggle pmbr_boot |& log
        else
        boot=1
            parted -s -a optimal -- /dev/$disk mklabel msdos \
                mkpart primary 3MiB ${bootSize}MiB set 1 boot on \
                mkpart primary $(( 3 + $bootSize ))MiB ${rootSize}MiB \
                 mkpart primary $(( 3 + $bootSize + $rootSize ))MiB ${homeSize}MiB \
               disk_toggle pmbr_boot |& log
        fi
    fi
    # make filesystems
    mkfs.vfat -F 32 /dev/${diskPrefix}${boot} |& log
    mkfs.ext4 /dev/${diskPrefix}$(( $boot + 1 )) |& log
    mkfs.ext4 /dev/${diskPrefix}$(( $boot + 2 )) |& log

    # set up /mnt
    # Root
    mount /dev/${diskPrefix}$(( $boot + 1 )) /mnt |& log
    # Create directory structure
    mkdir -pv /mnt/boot |& log
    mkdir -pv /mnt/home |& log
    # Boot
    mount /dev/${diskPrefix}${boot} /mnt/boot |& log
    # Home
    mount /dev/${diskPrefix}$(( $boot + 2 )) /mnt/home |& log
fi

# install packages

# Packages are in an array to make it easier to add/remove them.
mapfile -t packageList < <(sed -e 's/\([[:space:]a-zA-Z0-9_.\+-]*\).*/\1/g' -e 's/^ *//' -e 's/ .*//' -e '/\(^\s*[[:punct:]]\|^$\)/d' "/tmp/F123Light/build/package_lists/packages.list")
# Remove unneeded packages
for i in ${!packageList[@]} ; do
    if echo "${packageList[$i]}" | grep -q "fake-hwclock" ; then
        unset packageList[$i]
    fi
    if echo "${packageList[$i]}" | grep -q "pi-bluetooth" ; then
        unset packageList[$i]
    fi
    if echo "${packageList[$i]}" | grep -q "raspberry" ; then
        unset packageList[$i]
    fi
done
# Add the boot loader and needed packages.
packageList+=("grub" "dosfstools")
if [[ "$efi" == "yes" ]]; then
    packageList+=("efibootmgr")
fi
if [ "$vm" = "no" ]; then
    packageList+=("grub" "os-prober")
fi

# Install packages.
pacstrap /mnt ${packageList[@]} |& log

# generate fstab
genfstab -U -p /mnt > /mnt/etc/fstab

#copy sound state
alsactl store
cp /var/lib/alsa/asound.state /mnt/var/lib/alsa/asound.state |& log

# Copy over F123Light configuration files
cp -arv /tmp/files-F123Light/files/* /mnt/ |& log
# Update F123Light specific configuration directory.
cp -arv /tmp/files-F123Light/files/etc/F123-Config/ /mnt/etc/F123-Config |& log
mkdir -p /mnt/usr/share/doc/F123
cp -Rv /tmp/content-F123Light/F123/* /mnt/usr/share/doc/F123 |& log

# Initialize the timestamp file
date '+%y%m%d%H%M' > /mnt/etc/timestamp-f123light

# Get list of services to be enabled once inside the chroot
echo -n "systemctl enable " > /mnt/f123light-services
 tail -1 /tmp/F123Light/build/F123Light.conf | cut -d '"' -f2 | sed 's/ /\nsystemctl enable /g' >> /mnt/f123light-services

# chroot
arch-chroot /mnt /bin/bash << EOF |& log

# Source the services variable.
source f123light-services

# Configure pulse stuff
groupadd --system pulse
groupadd --system pulse-access
useradd --system -g pulse -G audio -d /var/run/pulse -m -s /bin/nologin pulse
gpasswd -a pulse lp
gpasswd -a root pulse-access

# set hostname
echo "f123light" > /etc/hostname

# Set hwclock for install to disc.
if [ "$vm" = "no" ]; then
hwclock --systohc --utc
fi

# set locale
echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen
locale-gen
echo 'LANG=en_US.UTF-8' > /etc/locale.conf

# Install internet packages for install to disc.
if [ "$vm" = "no" ]; then
pacman -S --noconfirm --needed dialog iw wpa_supplicant
fi

# Enable internet for the vm
if [ "$vm" = "yes" ]; then
systemctl enable dhcpcd
fi

# enable service files.
bash /f123light-services

# install and configure grub or systemd boot bootloader
if [[ "$efi" == "no" ]]; then
    grub-install --target=i386-pc --recheck /dev/${disk}
    sed -i 's/#\s*GRUB_INIT_TUNE=/GRUB_INIT_TUNE=/' /etc/default/grub
    grub-mkconfig -o /boot/grub/grub.cfg
else
    if [[ "$(cat /sys/firmware/efi/fw_platform_size)" = "64" ]]; then
        grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB
        sed -i 's/#\s*GRUB_INIT_TUNE=/GRUB_INIT_TUNE=/' /etc/default/grub
        grub-mkconfig -o /boot/grub/grub.cfg
            #bootctl install --esp-path=/boot
            #mkdir -p /boot/loader/entries
            #cp /usr/share/systemd/bootctl/arch.conf /boot/loader/entries
            #cp /usr/share/systemd/bootctl/loader.conf /boot/loader
            #sed -i -e "s/PARTUUID=XXXX/PARTUUID=$(lsblk -n -o uuid /dev/${diskPrefix}2)/" -e "s/rootfstype=XXXX/rootfstype=ext4/" /boot/loader/entries/arch.conf
    else
        # This is highly likely not to work, I'm leaving it here until we confirm if it does or doesn't. //Michael
        grub-install --target=i386-efi --efi-directory=/boot --bootloader-id=GRUB
        sed -i 's/#\s*GRUB_INIT_TUNE=/GRUB_INIT_TUNE=/' /etc/default/grub
        grub-mkconfig -o /boot/grub/grub.cfg
    fi
fi

# set root password
echo "root:root" | chpasswd

# Enable multilib for 64 bit systems.
sed -i '/^#\[multilib\]$/{{N;s/^#\[multilib\]\n#Include = \/etc\/pacman.d\/mirrorlist$/[multilib]\nInclude = \/etc\/pacman.d\/mirrorlist/;t;P;D}}' /etc/pacman.conf
pacman -Sy

#Create user account
useradd -m -g users -G wheel,storage,power,uucp,audio,games,lp,scanner,pulse-access -s /bin/bash f123

# set user password
echo "f123:f123" | chpasswd

#allow users of group wheel to use sudo without password for next section
sed -i 's/# %wheel ALL=(ALL) NOPASSWD: ALL/%wheel ALL=(ALL) NOPASSWD: ALL/' /etc/sudoers

sudo -u f123 touch /home/f123/.firstboot

# end section sent to chroot
EOF

# Copy over the log of the installation
cp $logFile /mnt/var/log

# sync for good measure
sync

# unmount
umount -R /mnt

espeak -v en-us -a 150 "Installation complete!" &> /dev/null

echo "Installation complete! Type poweroff to shut down this live invironment."
echo "Then power on to boot into your newly installed F123Light operating system!"
echo "Thank you for choosing F123Light."
exit 0
