#!/bin/bash
# Copied from: https://github.com/iiab/iiab-factory/blob/master/iiab

# To install Internet-in-a-Box (IIAB) 8.1 / pre-release onto Raspberry Pi OS,
# Ubuntu 22.04+, Linux Mint 21+ or Debian 12+, run this 1-line installer:
#
#                     curl iiab.io/install.txt | bash

# 1. WARNING: NOOBS IS *NOT* SUPPORTED, as its partitioning is very different.
#    On a Raspberry Pi, WE RECOMMEND YOU INSTALL THE LATEST RASPBERRY PI OS:
#    https://www.raspberrypi.com/documentation/computers/getting-started.html
#    To attempt IIAB 8.1 on another Linux see the manual/legacy instructions:
#    https://github.com/iiab/iiab/wiki/IIAB-Installation#do-everything-from-scratch

# 2. An Ethernet cable is HIGHLY RECOMMENDED during installation, as this is
#    more reliable than WiFi (and faster!)  WARNING: IF YOU CONNECT YOUR IIAB'S
#    INTERNAL WIFI TO THE INTERNET OVER 5 GHz, YOU'LL PREVENT OLDER LAPTOPS/
#    PHONES/TABLETS (WHICH REQUIRE 2.4 GHz) FROM CONNECTING TO YOUR IIAB'S
#    INTERNAL HOTSPOT.  See: "wifi_up_down: True" in /etc/iiab/local_vars.yml

# 3. Run 'sudo raspi-config' on Raspberry Pi, to set LOCALISATION OPTIONS

# 4. OPTIONAL: if you have slow/pricey Internet, pre-position KA Lite's
#    mandatory 0.9 GB English Pack (en.zip) within /tmp -- you can grab it from
#    https://pantry.learningequality.org/downloads/ka-lite/0.17/content/contentpacks/en.zip

# 5. Follow on-screen instructions (TYPE 'sudo iiab' TO RESUME IF EVER NECESS!)

# 6. Within about 1-2 hours, it will announce that INTERNET-IN-A-BOX (IIAB)
#    SOFTWARE INSTALL IS COMPLETE, prompting you to reboot...TO ADD CONTENT!

# Thanks   For   Building   Your   Own   Library   To   Serve   One   &   All
#
# DRAFT IIAB 8.1 Release Notes:
# https://github.com/iiab/iiab/wiki/IIAB-8.1-Release-Notes
#
# SPECIAL THANKS to countries + communities + volunteers who worked non-stop
# to bring about IIAB 8.1!  https://internet-in-a-box.org/contributing.html
#
# IIAB Dev Team
# http://FAQ.IIAB.IO


set -e                                   # Exit on error (avoids snowballing)
export DEBIAN_FRONTEND=noninteractive    # Bypass (most!) interactive questions

FLAGDIR=/etc/iiab/install-flags
APTPATH=/usr/bin    # Avoids problematic /usr/local/bin/apt on Linux Mint

FAST=false    # YOUR OWN RISK: Fewer security & user education prompts.
MFABT=false   # As above BUT bypasses editing of local_vars.yml + apt updates.
# When you have no time to read the MFABT book: "Move Fast and Break Things:
# How Facebook, Google, and Amazon Cornered Culture and Undermined Democracy"

REPO_BOUNDARY=1561    # iiab/iiab's lowest PR as of October 2020
pr_changes_local_vars=false
clones_and_pulls_done=false

if [[ $(id -un) != "root" ]]; then
    echo -e "\nPlease run: sudo iiab\n"
    exit 1
fi

if [[ $1 == "-f" || $1 == "--fast" ]]; then
    # EXAMPLE: 'curl iiab.io/fast.txt | bash [-s 361 2604 2607]' AND 'sudo iiab -f' TO CONTINUE
    FAST=true
    shift
elif [[ $1 == "-r" || $1 == "--risky" ]]; then
    # EXAMPLE: 'curl iiab.io/risky.txt | bash [-s 361 2604 2607]' AND 'sudo iiab -r' TO CONTINUE
    FAST=true
    MFABT=true
    shift
fi

mkdir -p $FLAGDIR    # Which also creates /etc/iiab for the step just below

# Save CLI params (PR #s) for Section J. so 'sudo iiab' continues after reboots
if [ $# -ne 0 ]; then
    printf '%s\n' "$@" >> /etc/iiab/pr-queue
fi


# 1. Subroutine for B.  Returns true (0) if username ($1) exists with password ($2)
command -v grep &> /dev/null ||
    $APTPATH/apt -y install grep    # AVOID UX CLUTTER+DELAYS: 5 MORE BELOW
command -v perl &> /dev/null ||
    $APTPATH/apt -y install perl    # AVOID UX CLUTTER+DELAYS: 4 MORE BELOW
check_user_pwd() {
    # 2021-08-28: New OS's use 'yescrypt' so use Perl instead of Python (#2949)
    # This also helps avoid parsing the (NEW) 4th sub-field in $y$j9T$SALT$HASH
    field2=$(grep "^$1:" /etc/shadow | cut -d: -f2)
    [[ $(perl -e "print crypt('$2', '$field2')") == $field2 ]]
}

# 2. Subroutine for Sections A. and G.  Returns any IIAB variable value -- SEE:
# https://wiki.iiab.io/go/FAQ#What_is_local_vars.yml_and_how_do_I_customize_it.3F

# 2021-08-28: bash scripts using default_vars.yml &/or local_vars.yml
# https://github.com/iiab/iiab-factory/blob/master/iiab#L119
# https://github.com/iiab/iiab/blob/master/scripts/iiab-apps-to-be-installed#L5
# https://github.com/iiab/iiab/blob/master/roles/remoteit/templates/iiab-remoteit#L8
# https://github.com/iiab/iiab/blob/master/roles/firmware/templates/iiab-check-firmware#L10
# https://github.com/iiab/iiab/blob/master/roles/network/templates/gateway/iiab-gen-iptables#L48
# https://github.com/iiab/maps/blob/master/osm-source/pages/viewer/scripts/iiab-install-map-region#L23-L39
# https://github.com/iiab/iiab/blob/master/roles/openvpn/templates/iiab-support READS+WRITES TO local_vars.yml (INCL NON-BOOLEAN)

iiab_var_value() {
    v1=$(grep "^$1:\s" /opt/iiab/iiab/vars/default_vars.yml 2> /dev/null | tail -1 | sed "s/^$1:\s\+//; s/#.*//; s/\s*$//; s/^\(['\"]\)\(.*\)\1$/\2/")
    v2=$(grep "^$1:\s" /etc/iiab/local_vars.yml 2> /dev/null | tail -1 | sed "s/^$1:\s\+//; s/#.*//; s/\s*$//; s/^\(['\"]\)\(.*\)\1$/\2/")
    [[ $v2 != "" ]] && echo $v2 || echo $v1    # [ "$v2" ] ALSO WORKS
}

# 3. Subroutine for C. and F.  Clone 3 IIAB repos
clone-repos() {                        # PREREQ: 'apt update'
    echo -e "\n\nDOWNLOAD (CLONE) IIAB'S 3 KEY REPOS INTO /opt/iiab ..."
    command -v git &> /dev/null ||
        $APTPATH/apt -y install git    # AVOID UX CLUTTER+DELAYS: 3 MORE BELOW
    mkdir -p /opt/iiab
    cd /opt/iiab
    echo
    if [ -d iiab ]; then
        echo -e "REPO EXISTS? Consider 'cd /opt/iiab/iiab; git pull'"
    else
        git clone https://github.com/iiab/iiab -b release-8.1
    fi
    echo
    if [ -d iiab-admin-console ]; then
        echo -e "REPO EXISTS? Consider 'cd /opt/iiab/iiab-admin-console; git pull'"
    else
        git clone https://github.com/iiab/iiab-admin-console
    fi
    echo
    if [ -d iiab-factory ]; then
        echo -e "REPO EXISTS? Consider 'cd /opt/iiab/iiab-factory; git pull'"
    else
        git clone https://github.com/iiab/iiab-factory
    fi
}

# 4. Subroutine for C. and F.  Install optional PR's
pull-prs() {
    echo -e "\n\nINSTALL PR's FROM iiab/iiab OR iiab/iiab-admin-console -- USAGE EXAMPLES:\n"
    echo -e "   sudo iiab 361 2604 2607"
    echo -e "   curl iiab.io/install.txt | bash -s 361 2604 2607\n"
    if [ -s /etc/iiab/pr-queue ]; then    # Set an email address for 'git pull' if one isn't yet set
        git config --get user.email 1> /dev/null ||
            git config --global user.email "albert@einstein.edu"
        echo -e "\nYour git email is set to: \e[1m$(git config --get user.email)\e[0m"
        echo -e 'Change this by running: sudo git config --global user.email "you@example.com"'

        command -v jq &> /dev/null || {
            echo
            $APTPATH/apt -y install jq    # Or grep/sed to avoid 3+ sec delay
        }
    fi

    # Similar to 'for pr in "$@"' but survives reboots:
    while [ -s /etc/iiab/pr-queue ]; do    # Test that file exists & is non-empty
        pr=$(head -1 /etc/iiab/pr-queue)    # Try the next PR, from top of queue
        if ! [[ "$pr" =~ ^[1-9][0-9]*$ ]]; then
            echo -e "\n\e[1mInvalid PR number:\e[0m $pr\n"
            echo -n "Delete it from top of /etc/iiab/pr-queue and continue? [Y/n] "
            read -n 1 -r ans < /dev/tty
            echo
            [[ $ans == "n" || $ans == "N" ]] &&    # [[ $ans =~ ^[nN]$ ]]
                exit 1
            sed -i '1d' /etc/iiab/pr-queue    # Delete 1st line
            continue
        fi

        if (( pr >= REPO_BOUNDARY )); then
            repo=iiab
        else
            repo=iiab-admin-console
        fi

        http_code=$(curl -sH "Accept: application/vnd.github.v3" https://api.github.com/repos/iiab/$repo/pulls/$pr -w "%{http_code}" -o /tmp/iiab-pr.json)
        if [[ $http_code != "200" ]]; then
            echo -e "\n\e[41;1mCOULD NOT FIND PR #$pr (https://github.com/iiab/$repo/pull/$pr)\e[0m\n"
            echo -en "\e[41;1mHTTP ERROR: $http_code\e[0m\e[1m "
            [[ $http_code == "403" ]] &&
                echo -en "(DID YOU REQUEST 60+ PR's IN ONE HOUR?)"
            [[ $http_code == "404" ]] &&
                echo -en "(IS #$pr AN ISSUE, RATHER THAN A PR?)"
            echo -e "\n"

            cat /tmp/iiab-pr.json    # GitHub sometimes includes an English explanation of the error, and URL, e.g. https://developer.github.com/v3/#rate-limiting
            echo
            curl -IsH "Accept: application/vnd.github.v3" https://api.github.com/repos/iiab/$repo/pulls/$pr    # HTTP headers typically reveal a lot more!

            echo -n "Delete it from top of /etc/iiab/pr-queue and continue? [Y/n] "
            read -n 1 -r ans < /dev/tty
            echo
            [[ $ans == "n" || $ans == "N" ]] &&    # [[ $ans =~ ^[nN]$ ]]
                exit 1
            sed -i '1d' /etc/iiab/pr-queue    # Delete 1st line
            continue
        fi

        title=$(jq -r '.title' /tmp/iiab-pr.json)
        account=$(jq -r '.head.label' /tmp/iiab-pr.json | cut -d: -f1)
        repo2=$(jq -r '.head.repo.name' /tmp/iiab-pr.json)    # 2021-11-22: For PR's created from oddly named forks (instead of "iiab" or "iiab-admin-console" !)
        branch=$(jq -r '.head.label' /tmp/iiab-pr.json | cut -d: -f2)
        commit_8chars=$(jq -r '.head.sha' /tmp/iiab-pr.json | cut -c1-8)
        files_changed=$(jq -r '.changed_files' /tmp/iiab-pr.json)

        echo -e "\nPR #$pr: cd /opt/iiab/$repo"
        cd /opt/iiab/$repo
        #git checkout -b POTLUCK master || true    # If test branch name/norm in future...for both repos?
        local_branch_old=$(git branch --show-current)
        if [[ $local_branch_old == "master" || $local_branch_old == "main" ]]; then
            #local_branch_new=$pr                 # e.g. "2604"
            if [[ $branch == "master" || $branch == "main" ]]; then
                local_branch_new="$pr-$branch"    # e.g. "2604-main"
            else
                local_branch_new=$branch          # e.g. "huge-speedup"
            fi
        else
            #local_branch_new="$local_branch_old-$pr"        # e.g. "2604-2607-3173"
            local_branch_new="$local_branch_old--$branch"    # e.g. "huge-speedup--qa--docs"
        fi
        echo -e "git checkout -b \e[1m$local_branch_new\e[0m"
        git checkout -b $local_branch_new    # FAILS IF (1) branch name's also master/main (2) branch name > 250 chars (branch names > 244 chars cannot be pushed)

        echo -e "git pull --no-edit --no-rebase --set-upstream https://github.com/$account/$repo2 $branch"    # Or $repo2.git
        git pull --no-edit --no-rebase --set-upstream https://github.com/$account/$repo2 $branch || {
            echo -e "\n\e[1mgit exit/error code:\e[0m $?\n"    # if hides err code
            echo -n "Delete it from top of /etc/iiab/pr-queue and continue? [Y/n] "
            read -n 1 -r ans < /dev/tty
            echo
            if [[ $ans == "n" || $ans == "N" ]]; then    # [[ $ans =~ ^[nN]$ ]]
                exit 1
            fi
            sed -i '1d' /etc/iiab/pr-queue    # Delete 1st line
            continue
        }

        sed -i '1d' /etc/iiab/pr-queue    # Delete 1st line
        echo "$(date '+%F %T %Z') #$pr $files_changed $commit_8chars https://github.com/$account/$repo2 $branch \"$title\"" >> /etc/iiab/pr-list-pulled    # For iiab-diagnostics
    done
}


# # Ask for password change if pi/raspberry default remains
# if check_user_pwd "pi" "raspberry"; then
#     echo -e "\n\n\e[41;1mRaspberry Pi's are COMPROMISED often if the default password is not changed!\e[0m\n"
#
#     echo -n "What password do you want for GNU/Linux user 'pi' ? "
#     read ans < /dev/tty    # Whines but doesn't change password if [Enter]
#     echo pi:"$ans" | chpasswd || true    # Overrides 'set -e'
# fi


# A. Create user 'iiab-admin' (or any other, some prefer 'pi' or 'ubuntu') as
# nec, with the default password.  If customizing this is important to you,
# please pre-position /etc/iiab/local_vars.yml specifying the 3 vars below.

IIAB_ADMIN_USER=$(iiab_var_value iiab_admin_user)
[[ $IIAB_ADMIN_USER == "" ]] &&
    IIAB_ADMIN_USER="iiab-admin"

IIAB_ADMIN_PUBLISHED_PWD=$(iiab_var_value iiab_admin_published_pwd)
[[ $IIAB_ADMIN_PUBLISHED_PWD == "" ]] &&
    IIAB_ADMIN_PUBLISHED_PWD="g0adm1n"

if ! [[ $(iiab_var_value iiab_admin_user_install) =~ ^[fF]alse$ ]]; then
    if ! id -u "$IIAB_ADMIN_USER" &> /dev/null; then
        /usr/sbin/useradd "$IIAB_ADMIN_USER"
        echo "$IIAB_ADMIN_USER":"$IIAB_ADMIN_PUBLISHED_PWD" | chpasswd
    fi
fi

# B. If 'iiab-admin' (or equivalent) use default password, prompt for change
if check_user_pwd "$IIAB_ADMIN_USER" "$IIAB_ADMIN_PUBLISHED_PWD"; then
    echo -e "\n\n\e[41;1mDANGER: User '$IIAB_ADMIN_USER' has public password '$IIAB_ADMIN_PUBLISHED_PWD' per http://FAQ.IIAB.IO\e[0m\n"

    echo -e "This is for login to Internet-in-a-Box's Admin Console (http://box.lan/admin)"
    echo -e "Technical Details: https://github.com/iiab/iiab/blob/master/roles/iiab-admin"

    if ! $($FAST); then
        echo -en "\nWhat password do you want for GNU/Linux user '$IIAB_ADMIN_USER' ? "
        read ans < /dev/tty    # Whines but doesn't change password if [Enter]
        echo "$IIAB_ADMIN_USER":"$ans" | chpasswd || true    # Overrides 'set -e'
    fi
fi

if [ -f $FLAGDIR/iiab-complete ]; then
    echo -e "\n\nIIAB INSTALLATION (/usr/sbin/iiab) IS ALREADY COMPLETE -- per existence of:"
    echo -e "$FLAGDIR/iiab-complete -- nothing to do.\n"
    exit 0
fi

# C. Position & customize /etc/iiab/local_vars.yml
command -v wget &> /dev/null ||
    $APTPATH/apt -y install wget    # AVOID UX CLUTTER+DELAYS: 4 MORE ABOVE
command -v nano &> /dev/null ||
    $APTPATH/apt -y install nano    # AVOID UX CLUTTER+DELAYS: 5 MORE ABOVE
if [ -f /etc/iiab/local_vars.yml ]; then

    # FUTURE: Test if their local_vars.yml is sufficiently version-compatible ?

    echo -e "\n\n  EXISTING /etc/iiab/local_vars.yml is being used to install Internet-in-a-Box\n"

    echo -e "   🚂 🚃 🚄 🚅 🚆 🚇 🚈 🚉 🚊 🚋 🚌 🚍 🚎 🚏 🚐 🚑 🚒 🚚 🚛 🚜 🚞 🚟 🚠 🚡 🚲\n"

    echo -e "                     Google 'local_vars.yml' to learn more!"
else
    echo -e "\n\nInstalling Internet-in-a-Box requires /etc/iiab/local_vars.yml\n"

    echo -e "PLEASE PICK (1) 🚵 SMALL (2) 🚢🚣 MEDIUM or (3) 🚂🚃🚃 LARGE (NEEDS 2+ GB RAM)."
    echo -e "Or try (m) for 🚑 MEDICAL.\n"

    echo -e 'See "What services (IIAB apps) are suggested during installation?" and'
    echo -e '"What can I do with E-books and Internet-in-a-Box?" in http://FAQ.IIAB.IO\n'

    echo -e "WARNING: This Can Take More Than An Hour, depending on Internet speed, CPU,"
    echo -e "temperature, and the speed of your microSD card.\n"

    echo -n "Please type 1, 2, 3 or m: "
    read -n 1 -r local_vars_size < /dev/tty
    echo; echo
    case $local_vars_size in
        0)
            local_vars_src_file=local_vars_unittest.yml
            ;;
        1)
            local_vars_src_file=local_vars_small.yml
            ;;
        3)
            local_vars_src_file=local_vars_large.yml
            ;;
        m)
            local_vars_src_file=local_vars_medical.yml
            ;;
        n)
            local_vars_src_file=local_vars_none.yml
            ;;
        *)
            local_vars_src_file=local_vars_medium.yml
            ;;
    esac

    # Quick pre-scan for any PR(s) that change user-specified local_vars.yml
    if [ -s /etc/iiab/pr-queue ]; then    # Test that file exists & is non-empty
        while read pr; do
            if (( pr < REPO_BOUNDARY )); then
                continue
            fi

            # https://docs.github.com/en/rest/pulls/pulls#list-pull-requests-files
            http_code=$(curl -sH "Accept: application/vnd.github.v3" https://api.github.com/repos/iiab/iiab/pulls/$pr/files -w "%{http_code}" -o /tmp/iiab-pr-files.json)
            if [[ $http_code == "200" ]]; then
                #jq -r '.[].filename' /tmp/iiab-pr-files.json > /tmp/iiab-pr-filelist
                #if grep -q "^vars/$local_vars_src_file$" /tmp/iiab-pr-filelist; then
                # Defer jq install til later for smooth UX: (grep works w/o apt delays!)
                if grep -q '^\s*"filename": "vars/'$local_vars_src_file'",$' /tmp/iiab-pr-files.json; then
                    pr_changes_local_vars=true
                    break
                fi
            fi
        done < /etc/iiab/pr-queue
    fi

    if $($pr_changes_local_vars); then
        echo -e "\n  \e[44;1m                                                                           \e[0m"
        echo -e "  \e[44;1m              At least one PR will change your local_vars.yml              \e[0m"
        echo -e "  \e[44;1m                                                                           \e[0m"
        echo -e "  \e[44;1m                   SO LET'S CLONE & PULL FIRST (1-2 min)                   \e[0m"
        echo -e "  \e[44;1m                                                                           \e[0m\n\n"
        $APTPATH/apt update    # -q useless; -qq too quiet (an option if optimizing later nec)
        clone-repos
        pull-prs
        clones_and_pulls_done=true
    elif [ -s /etc/iiab/pr-queue ]; then    # Test that file exists & is non-empty
        echo -e "\n\e[1m                    PR's will not change your local_vars.yml\e[0m"
        echo
        echo -e "\e[1m          So it's safe to edit local_vars.yml BEFORE cloning & pulling\e[0m\n\n"
    fi

    # Copy or download local_vars.yml + edit it optionally
    if [ -f /opt/iiab/iiab/vars/$local_vars_src_file ]; then
        cp /opt/iiab/iiab/vars/$local_vars_src_file /etc/iiab/local_vars.yml
        echo
    else
        wget -O /etc/iiab/local_vars.yml https://github.com/iiab/iiab/raw/master/vars/$local_vars_src_file
    fi

    if ! $($MFABT); then
        echo -en "\nEdit /etc/iiab/local_vars.yml to customize your Internet-in-a-Box? [Y/n] "
        read -n 1 -r ans < /dev/tty
        echo
        if [[ $ans != "n" && $ans != "N" ]]; then    # ! [[ $ans =~ ^[nN]$ ]]
            echo -e "\n1) PLEASE RUN: sudo nano /etc/iiab/local_vars.yml\n"

            echo -e "2) NEED HELP?  Type CTRL+G to learn...the nano editor\n"

            echo -e "3) After you're done editing, RUN 'sudo iiab' TO CONTINUE!\n"
            exit 0
        fi
    fi
fi

# D. Mandate OS SECURITY/UPDATES if 'apt update' has any (THEN REBOOT, AS NEC)
# Educate implementer while waiting for 'apt update'
echo -e "\n\n ██████████████████████████████████████████████████████████████████████████████"
echo -e " ██                                                                          ██"
echo -e " ██  RUN 'sudo iiab' IF THIS INSTALL SCRIPT EVER FAILS, TO TRY TO CONTINUE!  ██"
echo -e " ██                                                                          ██"
echo -e " ██████████████████████████████████████████████████████████████████████████████"

if ! $($MFABT); then
    echo -e "\n\n'apt update' is checking for OS updates, \e[1mwhich may force a reboot...\e[0m\n"
    # echo -e "2019-07-11 TEMP WORKAROUND FOR RASPBIAN BUSTER'S testing->stable apt GLITCH...\nDetails @ https://github.com/iiab/iiab/issues/1856\n"
    # apt -y update || true    # Overrides 'set -e'
    # echo -e "\nNOW THE REAL 'apt update' WILL RUN...\n"
    #$APTPATH/apt -qq update > /tmp/apt.stdout 2> /tmp/apt.stderr; rc=$(echo $?) || true    # Overrides 'set -e'
    #if (( $(wc -c < /tmp/apt.stderr) > 82 )); then    # apt.stderr typically contains exactly 82 characters when there are no errors, no matter the primary locale, i.e. 3-line file "\nWARNING: apt does not have a stable CLI interface. Use with caution in scripts.\n\n" ...OR... in other cases more than 82, e.g. many lines of errors when apt is busy/locked/offline/etc
    # 2022-10-28: BEWARE 'apt -qq update 2> /tmp/apt.stderr' would behave very differently (i.e. if STDIN isn't being redirected, then [1] /tmp/apt.stderr DOESN'T contain 82-char warning "\nWARNING: apt does not have a stable CLI interface. Use with caution in scripts.\n\n" and [2] /tmp/apt.stderr DOES contain ANSI color escape codes, which grep [BELOW] would need to scan for using https://unix.stackexchange.com/questions/324835/grep-for-an-ansi-escape-code)
    #if grep -q '^E: ' /tmp/apt.stderr; then    # We ignore '^W: ' warnings and '^N: ' notices (per: https://unix.stackexchange.com/questions/590027/what-does-the-error-line-prefix-w-mean-like-from-apt-get-or-other-similar) to avoid 'sudo iiab' holdups arising from {MongoDB, Yarn, etc} "Key is stored in legacy trusted.gpg keyring (/etc/apt/trusted.gpg)"
    #if [[ $rc != "0" ]]; then    # apt's Return Code simpler (than both conditions above!)
    if ! $APTPATH/apt -qq update > /tmp/apt.stdout 2> /tmp/apt.stderr; then    # Simpler than all 3 above!
        echo -e "'apt update' FAILED. VERIFY YOU'RE ONLINE and resolve all errors below:\n"
        cat /tmp/apt.stderr
        exit 1
    elif grep -q 'apt list --upgradable' /tmp/apt.stdout; then    # apt.stdout typically contains {"All packages are up to date.\n" [even if primary locale is French & Hindi!], "Todos los paquetes están actualizados.\n", "所有软件包均为最新。\n"} ...OR... {"5 packages can be upgraded. Run 'apt list --upgradable' to see them.\n" [even if primary locale is French & Hindi!], "Se puede actualizar 1 paquete. Ejecute «apt list --upgradable» para verlo.\n", "有 1 个软件包可以升级。请执行 ‘apt list --upgradable’ 来查看它们。\n"}
        cat /tmp/apt.stdout    # e.g. "5 packages can be upgraded. Run 'apt list --upgradable' to see them.\n"
        echo -e "\nYour OS will now be upgraded...this takes time. THEN IT WILL REBOOT (IF NEC!)\n"

        if ! $($FAST); then
            echo -n "Hit any key to confirm you'll RUN 'sudo iiab' AFTER IT REBOOTS: "
            read -n 1 -r ans < /dev/tty
            echo; echo
        fi
        $APTPATH/apt -y dist-upgrade
    else
        cat /tmp/apt.stdout    # "All packages are up to date.\n"
        if ! $($FAST); then
            echo -ne "\nHit any key to confirm you'll TRY TO RERUN 'sudo iiab' IF THERE IS A PROBLEM: "
            read -n 1 -r ans < /dev/tty
            echo; echo
        fi
    fi

    # 2021-09-03 #2975: Is a reboot needed? We check after reboot too, safeguarding
    # against users (or apt above, or unattended-upgrades) spontaneously AGAIN apt
    # updating /boot e.g. kernel AT ANYTIME -- also many weeks could have passed.
    bootupTime=$(($(date +%s) - $(cut -d. -f1 /proc/uptime)))    # Seconds since...
    bootDirLastModFile=$(date +%s -r "/boot/$(ls -t /boot | head -1)") # 1970-01-01
    # Works w/o RTC (real-time clock, i.e. battery) because:
    # Both 'apt' installs to /boot and IIAB installs require Internet (e.g. NTP).
    if (( bootupTime < bootDirLastModFile )); then
        reboot
        exit 0    # Nec to avoid bogus continuation & misleading output below
    fi
fi

##############################################################################
################### MAIN INTERACTIVE STUFF (ABOVE) DONE!!! ###################
##############################################################################

# E. If microSD, lower reserve disk space from ~5% to 2%
# if [ -f /proc/device-tree/model ] && grep -qi raspberry /proc/device-tree/model; then
if [ -e /dev/mmcblk0p2 ]; then
    echo -e "\n\nFound microSD card /dev/mmcblk0p2: Lower its reserve disk space from ~5% to 2%\n"
    tune2fs -m 2 /dev/mmcblk0p2
fi

# F. For a smoother + tighter UX in above interactive portion
if ! $($clones_and_pulls_done); then
    clone-repos
    pull-prs
fi

# G. Install Ansible + 2 IIAB repos
echo -e "\n\nINSTALL ANSIBLE + CORE IIAB SOFTWARE + ADMIN CONSOLE / CONTENT PACK MENUS...\n"

if [ -f $FLAGDIR/iiab-ansible-complete ]; then
    echo -e "ANSIBLE INSTALLATION IS ALREADY COMPLETE -- per existence of:"
    echo -e "$FLAGDIR/iiab-ansible-complete\n"

    echo -e "To upgrade Ansible, you can run: sudo /opt/iiab/iiab/scripts/ansible\n\n"
else
    echo -e "Install Ansible..."
    /opt/iiab/iiab/scripts/ansible
    touch $FLAGDIR/iiab-ansible-complete
fi

echo -e "\n┌──────────────────────────────────────────────────────────────────────────────┐"
echo -e "│                                                                              │"
echo -e "│   NOW INSTALL IIAB SOFTWARE! If glitches arise (connectivity or otherwise)   │"
echo -e "│                                                                              │"
echo -e "│   PLEASE TRY TO CONTINUE BY RE-RUNNING PARENT SCRIPT 'sudo iiab' -- or run   │"
echo -e "│                                                                              │"
echo -e "│   child script ./iiab-install -- both avoid repeating any of the 9 stages.   │"
echo -e "│                                                                              │"
echo -e "└──────────────────────────────────────────────────────────────────────────────┘"

cd /opt/iiab/iiab/
./iiab-install    # "$@"

if [ -f $FLAGDIR/iiab-admin-console-complete ]; then
    echo -e "ADMIN CONSOLE INSTALLATION IS ALREADY COMPLETE -- per existence of:"
    echo -e "$FLAGDIR/iiab-admin-console-complete\n"
elif [[ $(iiab_var_value admin_console_install) =~ ^[fF]alse$ ]]; then
    echo -e "LET'S NOT TRY TO INSTALL ADMIN CONSOLE -- because:"
    echo -e "'admin_console_install: False' is likely in /etc/iiab/local_vars.yml\n"
else
    echo -e "Install Admin Console... (also runs iiab-get-kiwix-cat to d/l Kiwix catalog,"
    echo -e "and installs Dynamic Menuing for /library/www/html/home/index.html)\n"

    cd /opt/iiab/iiab-admin-console
    ./install
    touch $FLAGDIR/iiab-admin-console-complete
fi

if [[ $(iiab_var_value admin_console_enabled) =~ ^[fF]alse$ ]]; then
    echo -e "'admin_console_enabled: False' is likely in /etc/iiab/local_vars.yml"
    echo -e "...so let's try to DISABLE & STOP Admin Console's iiab-cmdsrv.service\n"

    systemctl disable iiab-cmdsrv || true    # Overrides 'set -e'
    systemctl stop iiab-cmdsrv || true    # Overrides 'set -e'
else
    echo -e "'admin_console_enabled: False' isn't in /etc/iiab/local_vars.yml"
    echo -e "...so let's try to ENABLE & START Admin Console's iiab-cmdsrv.service\n"

    systemctl enable iiab-cmdsrv || true    # Overrides 'set -e'
    systemctl start iiab-cmdsrv || true    # Overrides 'set -e'
fi

# H. KA Lite prep
if [ -d /library/ka-lite ]; then
    echo -e "\n\nKA LITE REQUIRES 2 THINGS...\n"

    echo -e "Register with KA Lite - just the anonymous registration...\n"
    # /usr/bin/kalite venv wrapper invokes 'export KALITE_HOME=/library/ka-lite'
    if [ ! -f $FLAGDIR/kalite-zone-complete ]; then
        echo -e "Now running 'kalite manage generate_zone' ...\n"
        kalite manage generate_zone || true    # Overrides 'set -e'
        touch $FLAGDIR/kalite-zone-complete
    else
        echo -e "'kalite manage generate_zone' IS ALREADY COMPLETE -- per existence of:"
        echo -e "$FLAGDIR/kalite-zone-complete\n"
    fi

    echo -e "\nInstall KA Lite's mandatory 0.9 GB English Pack... (en.zip)\n"
    if [ ! -f $FLAGDIR/kalite-en.zip-complete ]; then
        #echo -e 'Now retrieving it...\n'
        cd /tmp
        if [ -f en.zip ]; then
            if [ $(wc -c < en.zip) -ne 929916955 ]; then
                echo -e "\nERROR: /tmp/en.zip must be 929,916,955 bytes to proceed.\n" >&2
                exit 1
            else
                echo -e "\nUsing existing /tmp/en.zip whose 929,916,955 byte size is correct!\n"
            fi
        else
            wget https://pantry.learningequality.org/downloads/ka-lite/0.17/content/contentpacks/en.zip
        fi
        echo -e 'Now installing /tmp/en.zip into /library/ka-lite/content/*\n'
        kalite manage retrievecontentpack local en en.zip
        touch $FLAGDIR/kalite-en.zip-complete
    fi
fi
# WARNING: /tmp/en.zip (and all stuff in /tmp) is auto-deleted during reboots
# NEW WAY ABOVE - since 2018-07-03 - installs KA Lite's mandatory English Pack
#
# kalite manage retrievecontentpack download en
# OLD WAY ABOVE - fails w/ sev ISPs per https://github.com/iiab/iiab/issues/871

# I. Start BitTorrent downloads, e.g. if /etc/iiab/local_vars.yml requested any
if $(systemctl -q is-active transmission-daemon) && ! $(ischroot -t); then
    echo -e "\n\nSTARTING BITTORRENT DOWNLOAD(S) for KA Lite...Please Monitor: http://box:9091\n"
    transmission-remote -n Admin:changeme -t all --start
fi

touch $FLAGDIR/iiab-complete

# J. Educate Implementers prior to rebooting!
echo -e "\n\n         ┌───────────────────────────────────────────────────────────┐"
echo -e "         │                                                           │"
echo -e "         │   INTERNET-IN-A-BOX (IIAB) SOFTWARE INSTALL IS COMPLETE   │"
echo -e "         │                                                           │"
echo -e "         └───────────────────────────────────────────────────────────┘\n"

echo -e "(1A) A couple minutes after you reboot (below) try to connect any laptop to"
echo -e 'Wi-Fi hotspot "Internet in a Box".  If this works, verify that you can browse'
echo -e "to http://box or http://box.lan or http://10.10.10.10\n"

echo -e "(1B) IF THOSE 3 DON'T WORK, try http://box.local from any device connected to"
echo -e "your usual network.  Or try http://localhost from your IIAB itself!\n"

echo -e "(1C) IF ALL 5 ABOVE DON'T WORK, ask the person who set up the network/router"
echo -e "in your building for the IP address of your IIAB, so you can browse to it"
echo -e "using (something like) http://192.168.0.100 -- FOR NOW, IP ADDRESS(ES) ARE:\n\e[1m"

hostname -I

echo -e '\e[0m\n(2) ADD CONTENT using http://box.lan/admin (changing "box.lan" to be as above!)'
echo -e 'PLEASE READ "What are the default passwords?" and "How do I customize my'
echo -e 'Internet-in-a-Box home page?" at http://FAQ.IIAB.IO\n'

echo -e "(3) Please run the 'iiab-diagnostics' command, to generate a URL summarizing"
echo -e "your IIAB configuration, for volunteers seeking to help you.  We strongly"
echo -e "encourage you to share this URL also when connecting with others in the IIAB"
echo -e "global community, learning from other initiatives in your region and beyond!\n"

#echo -e "(3) If you're installing IIAB over Wi-Fi (instead of Ethernet) remember to run"
#echo -e "'iiab-hotspot-on' at the VERY END, when you're ready to ACTIVATE YOUR IIAB's"
#echo -e "INTERNAL WI-FI HOTSPOT.  CAUTION: this permanently kills your IIAB's Internet"
#echo -e "(over Wi-Fi anyway) until you later run 'iiab-hotspot-off'.  CAVEAT: these"
#echo -e "two commands only work with Raspberry Pi as of 2019-09-30.\n"

if ! $(ischroot -t); then
    echo -ne "HIT [Enter] TO REBOOT, CONFIRMING YOU'VE" '"photographed" THE ABOVE PARAGRAPHS: '
    read ans < /dev/tty

    # Sets hostname, improves RTC + memory mgmt, starts BitTorrents if needed, etc!
    reboot
else
    echo -ne "IIAB Done"
    exit 0
fi
