#! /bin/bash
# Copyright Neil Van Dyke.  See file "info.rkt".

# Note: Using the "live-build" from Debian Squeeze (2.0.12-2).

# TODO: Where we have a "../", that generally means a reference to a file in
# the "rackout" Racket source directory, which is not necessarily correct.
# Make a variable for the path, then figure out where we're going to build
# this.

Program="rackout-live-build"

BuildTimestamp=$(date "+%Y%m%d-%H%M")

Info() {
    echo "${Program}: ${1}"
}

Warning() {
    echo "${Program}: *WARNING* ${1}"
}

Error() {
    echo "${Program}: *ERROR* ${1}"
}

FatalError() {
    Error "$1"
    exit 1
}

CreateDir() {
    local Dir="$1"
    if [ ! -d "$Dir" ] ; then
        Info "Creating directory \"${Dir}\"..."
        mkdir -p "$Dir" \
            || FatalError "Could not create directory \"${Dir}\"."
    fi
}

CreateFile() {
    local File="$1"
    # TODO: Maybe add optional argument for chmod.
    CreateDir $(dirname "$File")
    if [ -f "$File" ] ; then
        Info "Removing existing file \"${File}\", for replacement..."
        /bin/rm "$File" \
            || FatalError "Could not remove file \"${File}\"."
    fi
    Info "Creating file \"${File}\"..."
    cat > "$File" \
        || FatalError "Could not create file \"${File}\"."
}

CreateSymlink() {
    local Source="$1"
    local Dest="$2"
    CreateDir $(dirname "$Dest")
    RemoveFileOrEmptyDirectory "$Dest"
    ln -s "$Source" "$Dest"
}

RemoveFileOrEmptyDirectory() {
    local File="$1"
    if [ -d "$File" ] ; then
        /bin/rmdir "$File" || exit 1
    elif [ -f "$File" ] ; then
        /bin/rm "$File" || exit 1
    fi
}

date

umask 022

# TODO: Check for whether "live-build" is installed before trying to install
# it.
# sudo apt-get install live-build

# TODO: Do we need these things that happen during build: squashfs-tools

# TODO: 
# apt-get install qemu-kvm qemu-utils

BuildDirBasename="rackout-live-build-dir"
[ "$(basename $(pwd))" = "$BuildDirBasename" ] \
|| FatalError "You must be in a directory named \"${BuildDirBasename}\"."

Info "Running lb clean..."
sudo lb clean \
|| Warning "lb clean failed."

F="auto/config"
CreateFile "$F" <<"EOH"
#!/bin/sh
echo "Entered auto/config script"
lb config noauto \
    --apt-recommends    false \
    --architecture      i386 \
    --backports         true \
    --binary-images     usb-hdd \
    --binary-indices    false \
    --bootappend-live   "noprompt persistent=nofiles" \
    --bootloader        syslinux \
    --cache             true \
    --cache-indices     true \
    --cache-packages    true \
    --chroot-filesystem squashfs \
    --distribution      squeeze \
    --hostname          rackout \
    --linux-flavours    686 \
    --mirror-binary     http://ftp.us.debian.org/debian/ \
    --mirror-bootstrap  http://ftp.us.debian.org/debian/ \
    --packages-lists    standard-x11 \
    --security          true \
    --syslinux-timeout  1 \
    --syslinux-menu     true \
    --username          user \
    --win32-loader      false
echo "Exiting auto/config script"
EOH
chmod 0755 "$F"

# Note: The "DEBIAN_LIVE" label is hardcoded into the scripts in Squeeze
# live-build.  We can try changing the label after the fact, with fs tools, but
# unsure whether it relies on the label in some circumstances.

# ConfigChrootSourcesDir="config/chroot_sources"
# 
# mkdir -p "$ConfigChrootSourcesDir"
# for Phase in chroot binary ; do
#     F="${ConfigChrootSourcesDir}/rackout-sources.${Phase}"
#     Info "Creating file \"${F}\"..."
#     cat > "$F" <<"EOH"
# deb http://backports.debian.org/debian-backports squeeze-backports main
# EOH
# done

ConfigChrootAptDir="config/chroot_apt"

ChrootLocalIncludesDir="config/chroot_local-includes"

for F in "${ConfigChrootAptDir}/preferences" "${ChrootLocalIncludesDir}/etc/apt/preferences" ; do
    CreateFile "$F" <<"EOH"
Package: *
Pin: release n=squeeze
Pin-Priority: 888

Package: *
Pin: release n=squeeze-updates
Pin-Priority: 888

Package: *
Pin: release n=squeeze-backports
Pin-Priority: 777

Package: libvlc5 libvlccore5 vlc vlc-data vlc-nox 
Pin: version 2.*
Pin-Priority: 991

EOH
done

ConfigChrootLocalHooksDir="config/chroot_local-hooks"
ConfigBinaryLocalHooksDir="config/binary_local-hooks"

F="${ConfigChrootLocalHooksDir}/rackout-chroot-hooks.sh"
CreateFile "$F" <<"EOH"
#! /bin/sh

set -e

Program="rackout-chroot-hooks.sh"

echo "${Program}: Running..."

echo "${Program}: *DEBUG* pwd = \"$(pwd)\""
echo "${Program}: *DEBUG* ls  = \"$(ls)\""
echo "${Program}: *DEBUG* env = \"$(env)\""

# Note: Despite examples included with live-build, "apt-get" in the chroot
# hooks here seems to apply to the host system for the build, and so assuming
# not chroot'd. Does not make sense, but subsequently I have seen this script
# being run chroot'd.

if [ ! -f "rackout-live-timestamp" ] ; then
    echo "${Program}: No \"rackout-live-timestamp\" file; probably in wrong directory."
    exit 1
fi

rm -rf   etc/skel/etc/wicd
mkdir -p etc/skel/etc
mv       etc/wicd            etc/skel/etc/wicd
ln -s    /home/user/etc/wicd etc/wicd

[ -d lib/firmware ] && /bin/rmdir lib/firmware
[ -f lib/firmware ] && /bin/rm    lib/firmware
ln -s /home/user/lib/firmware     lib/firmware

# TODO: !!! Does this "apt-get clean" remove from chroot'd or from build workstation?
# check /var/cache/apt
apt-get clean

rm -f var/cache/debconf/config.dat-old
rm -f var/cache/debconf/templates.dat-old
rm -rf usr/share/man
rm -rf usr/share/doc

# TODO: rm -rf /usr/share/info
# TODO: Also cat /dev/null to each file in var/log ?

echo "${Program}: Done."
EOH
chmod 0755 "$F"

F="${ConfigBinaryLocalHooksDir}/rackout-binary-hooks.sh"
CreateFile "$F" <<"EOH"
#! /bin/sh

set -e

Program="rackout-binary-hooks.sh"

echo "${Program}: Running..."

echo "${Program}: *DEBUG* pwd = \"$(pwd)\""
# Note: cwd is the build directory (i.e., "rackout-live-build-dir").

echo "${Program}: Done."
EOH
chmod 0755 "$F"

Info "Running lb config..."
lb config \
|| FatalError "lb config failed."

# TODO: Include Racket 5.3.1, preferrably from a ".deb" file.

CreateFile "config/chroot_local-packageslists/rackout.list" <<"EOH"
acpid
acpi-support
acpi-support-base
pciutils
usbutils
dmidecode
parted
bash-completion
less
emacs23
vim-tiny
sudo
rsync
dbus
openssh-server
tmux
rxvt-unicode-lite
xmonad
libghc6-xmonad-contrib-dev
libghc6-xmonad-dev
suckless-tools
libglib2.0-0
libgtk2.0-0
libpango1.0-0
libcairo2
libjpeg62
libpng12-0
gksu
wicd
wicd-daemon
wicd-cli
wicd-gtk
wpasupplicant
cdparanoia
vorbis-tools
vorbisgain
abcde
vlc
strace
EOH

Info "Copying syslinux template..."
rm -r config/templates/syslinux > /dev/null 2>&1
cp -r /usr/share/live/build/templates/syslinux config/templates/. \
|| FatalError "Could not copy syslinux template."

Info "Copying syslinux splash..."
cp ../rackout-live-syslinux-splash.png config/templates/syslinux/menu/splash.png \
|| FatalError "Could not copy syslinux splash."

ChrootLocalPreseedDir="config/chroot_local-preseed"

CreateFile "${ChrootLocalPreseedDir}/rackout-preseed" <<"EOH"
debconf passwd/user-default-groups string audio cdrom video plugdev netdev powerdev
EOH

CreateFile "${ChrootLocalIncludesDir}/etc/abcde.conf" <<"EOH"
ACTIONS=cddb,read,encode,tag,move,clean
CDDBCOPYLOCAL="n"
CDDBPROTO=6
CDDBURL="http://freedb.freedb.org/~cddb/cddb.cgi"
CDDBUSELOCAL="n"
CDPARANOIAOPTS="-q"
CDROMREADERSYNTAX=cdparanoia
EJECTCD=y
HELLOINFO="user@localhost"
KEEPWAVS=n
NOCDDBQUERY=n
NOSUBMIT=y
OGGENCOPTS="-Q"
OUTPUTDIR=/home/user/audio
OUTPUTTYPE=ogg
SHOWCDDBFIELDS=year,genre
VORBISCOMMENTOPTS="-R"

# If HTTPGET is modified, the HTTPGETOPTS options should also be defined 
# accordingly. If HTTPGET is changed, the default options will be set,
# if HTTPGETOPTS is empty or not defined.
#HTTPGET=wget
# for fetch (FreeBSD): HTTPGETOPTS="-q -o -"
# for wget: HTTPGETOPTS="-q -nv -O -"
# for curl (MacOSX): HTTPGETOPTS="-f -s"
#HTTPGETOPTS="-q -O -"

# Ogg:
#VORBIZEOPTS=
#OGGENCOPTS=

# FLAC:
#FLACOPTS="-f"

#WAVOUTPUTDIR=/tmp

# Support for systems with low disk space:
# n:	Default parallelization (read entire CD in while encoding)
# y:	No parallelization (rip, encode, rip, encode...)
#LOWDISK=n
EOH

F="${ChrootLocalIncludesDir}/etc/acpi/lid.sh"
CreateFile "$F" <<"EOH"
#/bin/sh
# Note: lid.sh has been changed to a no-op for RackOut Live, so that laptops 
# can be run cracked open (for cooling) while displaying to an external monitor,
# without this getting complicated.
exit 0
EOH
chmod 0755 "$F"

# Note: Can't do "new_pll=0" because seemed to disable high-res for DVI-0 on
# T60 (or maybe it's somehow disabling "radeon" altogether and falling back to
# "vesa", but no time to investigate further right now).
#
# CreateFile "${ChrootLocalIncludesDir}/etc/modprobe.d/radeon-kms.conf" <<"EOH"
# options radeon new_pll=0
# # Note: See https://bugs.freedesktop.org/show_bug.cgi?id=26358
# EOH

Info "Creating directory \"${ChrootLocalIncludesDir}/etc/skel/\"..."
mkdir -p "${ChrootLocalIncludesDir}/etc/skel/"             || FatalError ""
mkdir -p "${ChrootLocalIncludesDir}/etc/skel/bin"          || FatalError ""
mkdir -p "${ChrootLocalIncludesDir}/etc/skel/lib"          || FatalError ""
mkdir -p "${ChrootLocalIncludesDir}/etc/skel/lib/firmware" || FatalError ""

F="/usr/local/rackout-live/bashrc"
CreateSymlink "$F" "${ChrootLocalIncludesDir}/etc/skel/.bashrc"
CreateFile "${ChrootLocalIncludesDir}${F}" <<"EOH"
unset CDPATH
unset HISTFILE
unset HISTFILESIZE
unset MAIL
unset MAILPATH
unset MAILCHECK
unset TMOUT
umask 022

export PATH="/home/user/bin:/usr/local/rackout/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games"
export LD_LIBRARY_PATH="/lib:/usr/lib:/home/user/lib"

[ -z "$PS1" ] && return

shopt -u hostcomplete
mesg n
NormalUsername="user"
if [ "$USER" = "$NormalUsername" ] ; then
    if [ -n "$SSH_CLIENT" ] ; then
        PS1="\h "
    else
        PS1=""
    fi
else
    if [ \( -n "$SSH_CLIENT" \) -o \( -n "$TMUX" \) -o \( -n "$SCREEN" \) ] ; then
        PS1="\u@\h "
    else
        PS1="\u@ "
    fi
fi
[ -n "$TMUX" ] && PS1="${PS1}TMUX "
[ -n "$STY"  ] && PS1="${PS1}SCREEN "
PS1="${PS1}\w"
case "$TERM" in
    linux|screen|vt*|ansi*|xterm*|rxvt*)
        PS1="\\[\\e[;7m\\] ${PS1} \\[\\e[m\\] "
        ;;
    *)
        PS1="[${PS1}] "
        ;;
esac
unset NormalUsername

if [ "$TERM" = "dumb" ] ; then
    shopt -u checkwinsize
else
    shopt -s checkwinsize
    bind "set page-completions off"
fi

alias g='grep'
alias gi='grep -i'
alias h='history'
alias l='/bin/ls -aF'
alias ll='/bin/ls -alF'

# TODO: Do we already get bash-completion from system-wide rc files?
# [ -f /etc/bash_completion ] && . /etc/bash_completion
EOH

F="/usr/local/rackout-live/bash_profile"
CreateSymlink "$F" "${ChrootLocalIncludesDir}/etc/skel/.bash_profile"
CreateFile "${ChrootLocalIncludesDir}${F}" <<"EOH"
#! /bin/bash
. "${HOME}/.bashrc"
if [ "$(/usr/bin/tty)" = "/dev/tty1" ] ; then
    echo "Starting X..."
    Cookie="$(/usr/bin/mcookie)"
    if [ $? = 0 ] ; then
        export DISPLAY=":0"
        xauth add "${DISPLAY}"            . "$Cookie"
        xauth add "${HOSTNAME}${DISPLAY}" . "$Cookie"
        unset mcoookie
        startx
	if [ $? = 0 ] ; then
            echo "Logging out after X..."
            logout
	else
            echo "*ERROR* startx failed.  Not logging out."
	fi
    else
        unset mcoookie
        echo "*ERROR* mcookie failed.  Not starting X."
    fi
fi
EOH

F="/usr/local/rackout-live/xsession"
CreateSymlink "$F" "${ChrootLocalIncludesDir}/etc/skel/.xsession"
CreateFile "${ChrootLocalIncludesDir}${F}" <<"EOH"
#!/bin/sh
xsetroot -solid black
xsetroot -cursor_name left_ptr
xset -dpms
xset s off
xset b 20 1000 30
xset r rate 300 50
for Keycode in $(xmodmap -pke | sed -n -e 's/^keycode  *\([0-9][0-9]\) *=  *Caps_Lock\( .*\)$/\1/p')
do
    xmodmap -e "keycode ${Keycode} = Caps_Lock Caps_Lock Caps_Lock Caps_Lock"
done
xmodmap \
    -e "clear lock" \
    -e "clear mod3" \
    -e "add mod3 = Caps_Lock"

# xrandr | grep "DVI-0 connected "
# if [ $? = 0 ]; then
#     # External monitor is connected
#     xrandr \
#         --fb 1920x1080 \
#         --output DVI-0 --mode 1920x1080 --pos 0x0 \
#         --output LVDS  --mode 1400x1050 --same-as DVI-0 --panning 1920x1080
#     if [$? -ne 0]; then
#         # Something went wrong. Autoconfigure the internal monitor and disable the external one
#         xrandr --output LVDS --mode auto --output DVI-0 --off
#     fi
# else
#     # External monitor is not connected
#     xrandr --output LVDS --mode 1400x1050 --output DVI-0 --off
# fi
# xrandr

# Note: We had to add the "LD_LIBRARY_PATH" here, because the setting in
# "/home/user/bashrc" is not propagated to the "vlc" process.
tmux new-session -d "PLTSTDERR=debug LD_LIBRARY_PATH=/lib:/usr/lib:/home/user/lib /usr/local/rackout/bin/rackout --big-display-only ; echo \"Press the Return key...\" ; read line" &
xmonad
ExitStatus=$?
if [ "$ExitStatus" != 0 ] ; then
    echo "*WARNING* xmonad returned exit status ${ExitStatus}.  Pausing."
    sleep 10
    exit 1
fi
exit 0
EOH

F="/usr/local/rackout-live/vlcrc"
CreateSymlink "$F" "${ChrootLocalIncludesDir}/etc/skel/.config/vlc/vlcrc"
CreateFile "${ChrootLocalIncludesDir}${F}" <<"EOH"
album-art=2
qt-privacy-ask=0
EOH

F="/usr/local/rackout-live/xmonad.hs"
CreateSymlink "$F" "${ChrootLocalIncludesDir}/etc/skel/.xmonad/xmonad.hs"
CreateFile "${ChrootLocalIncludesDir}${F}" <<"EOH"
import XMonad
import XMonad.Layout.NoBorders
import XMonad.Util.EZConfig(additionalKeys)
import System.IO

main = do
    xmonad $ defaultConfig
        { borderWidth        = 8
        , terminal           = "rxvt"
        , normalBorderColor  = "red4"
        , focusedBorderColor = "green1"
        , layoutHook         = layout
        , modMask            = mod4Mask
        } `additionalKeys`
        [ 
          -- TODO
        ]

layout = noBorders Full ||| tiled ||| Mirror tiled
  where
     tiled   = Tall nmaster delta ratio
     nmaster = 1
     ratio   = 1/2
     delta   = 3/100

EOH

CreateFile "${ChrootLocalIncludesDir}/etc/X11/app-defaults/URxvt" <<"EOH"
URxvt.foreground:         grey90
URxvt.background:         black
URxvt.cursorColor:        green
URxvt.scrollColor:        gray20
URxvt.font:               -adobe-courier-medium-r-normal--14-*-*-*-m-*-*-*
URxvt.scrollBar_right:    True
URxvt.scrollBar_floating: True
EOH

CreateFile "${ChrootLocalIncludesDir}/etc/ssh/sshd_config" <<"EOH"
Port 22
Protocol 2
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_dsa_key
UsePrivilegeSeparation yes
KeyRegenerationInterval 3600
ServerKeyBits 768
SyslogFacility AUTH
LogLevel ERROR
LoginGraceTime 120
PermitRootLogin no
StrictModes no
RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile %h/.ssh/authorized_keys
IgnoreRhosts yes
RhostsRSAAuthentication no
HostbasedAuthentication no
IgnoreUserKnownHosts yes
PermitEmptyPasswords no
ChallengeResponseAuthentication no
PasswordAuthentication no
X11Forwarding yes
X11DisplayOffset 10
PrintMotd no
PrintLastLog yes
TCPKeepAlive yes
UseLogin no
AcceptEnv LANG LC_*
Subsystem sftp /usr/lib/openssh/sftp-server
UsePAM yes
EOH

CreateFile "${ChrootLocalIncludesDir}/etc/issue" <<"EOH"
EOH

CreateFile "${ChrootLocalIncludesDir}/etc/issue.net" <<"EOH"
EOH

CreateFile "${ChrootLocalIncludesDir}/etc/motd" <<EOH
EOH

CreateFile "${ChrootLocalIncludesDir}/rackout-live-timestamp" <<EOH
${BuildTimestamp}
EOH

ChrootUsrLocalRackoutDir="${ChrootLocalIncludesDir}/usr/local/rackout"
Info "Copying RackOut dist-tree to \"${ChrootUsrLocalRackoutDir}\"..."
/bin/rm -r "$ChrootUsrLocalRackoutDir" > /dev/null 2>&1
mkdir -p "$ChrootUsrLocalRackoutDir"
(cd ../dist-tree && tar cf - *) \
| (cd "$ChrootUsrLocalRackoutDir" && tar xpvf -) \
|| FatalError "Copying of RackOut dist-tree failed."

Info "Running lb build..."
time sudo ionice -c2 -n6 lb build \
|| FatalError "lb build failed."

date

Info "Done."
exit 0
