#!/bin/bash

. shell-config
. shell-var

. install2-sh-functions
. alterator-sh-functions
. install2-remount-functions

po_domain="alterator-livecd"
alterator_api_version=1
source_dir="${source_dir:-/.ro}"
du_exclude_list='/mnt /home /media /run /var/run /srv'
install_pid=

slideshow_conf="/etc/alterator/slideshow.conf"
# Default slideshow timeout, sec
default_slideshow_step=30
default_slideshow_path="/usr/share/install2/slideshow"

do_notify()
{
    alterator-mailbox-send "$1 \"$(write_string "$2")\""
    echo "message:$1 $2" >&2
    sleep 0.1
}

do_notify_error()
{
    do_notify error "$1"
}

do_notify_status()
{
    do_notify status "$1"
}

do_notify_stage()
{
    do_notify stage "$1"
}

##
# Return free space in bytes on mounted file system
#
free_space() {
        local target="$1" && shift
	local free_blk= blk_size=

        [ -e "$target" ] || return 1
	out=`stat --file-system --format='%f %S' "$target"`
	set -- $out
	free_blk="$1"
	blk_size="$2"
	echo $((free_blk*blk_size))
}

used_space() {
	local dir="$1"
	local out= free_blk= total_blk= used_blk= blk_size=
	out=`stat --file-system --format='%f %b %S' "$dir"`
	set -- $out
	free_blk="$1"
	total_blk="$2"
	blk_size="$3"
	used_blk=$((total_blk-free_blk))
	echo $((used_blk*blk_size))
}

# find the loop device of a mounted squashfs filesystem
squashfs_loopdev() {
	local mntpt="$1"
	local loopdev
	local rc
	loopdev="`findmnt -n -o SOURCE $mntpt`"
	rc=$?
	if [ $rc -ne 0 ]; then
		echo "$mntpt is not a mount point" >&2
		return 2
	fi

	echo "$loopdev"
}

parse_unsquashfs_progress() {
	local str="$*"
	local percentage
	# unsquashfs progress line:
	# [==============/                                    ] 61882/154938  39%
	str="${str## }"
	case "$str" in
		[*)
		;; # make vim happy: ]
		*)
		return 0
		;;
	esac

	str="${str##*] }"
	set -- $str
	percentage="$2"
	percentage="${percentage%%%}"
	echo "$percentage"
}

##
# copy squashfs image
#

do_install()
{
    local src="$1";shift
    local dst="$1";shift
    local total_size= free= pct= src_loopdev= rc=
    local save_nfiles= save_nfiles_soft=

    if [ ! -d "$src" ]; then
        do_notify_error "Can't find image mountpoint ($src)"
        return 1
    fi

    if ! mkdir -p -- "$dst";then
        do_notify_error "Can't write to $dst directory"
        return 1
    fi

    do_notify_stage preinstall

    shopt -sq dotglob

    total_size="$(used_space "$src")"
    free="$(free_space "$dst")"

    if [ $total_size -gt $free ]; then
        do_notify_error "No free space to copy image"
        return 1
    fi
    src_loopdev="$(squashfs_loopdev "$src")"
    rc=$?
    if [ $rc -ne 0 ]; then
	    notify_error "Squashfs image of "$src" not found"
	    return 1
    fi

    do_notify_stage install

    if [ -n "$(find "$dst" -mount -type f -print -quit)" ]; then
        do_notify_error "$dst is not empty!"
    fi

    # unsquashfs processes many files at once
    save_nfiles=`ulimit -H -n`
    save_nfiles_soft=`ulimit -S -n`
    ulimit -H -n $((1024*1024))
    ulimit -S -n $((1024*1024))
    unsquashfs -f -d "$dst" "$src_loopdev" > >(
    while read -r -d '
' progress_str; do
	    pct=`parse_unsquashfs_progress "$progress_str"`
	    if [ -n "$pct" ]; then
		    do_notify_status "$pct"
	    fi
    done;
    )
    rc=$?
    ulimit -H -n $save_nfiles
    ulimit -S -n $save_nfiles_soft

    if [ $rc -ne 0 ]; then
	    do_notify_error "Error unpacking image from ${src_loopdev} into ${dst}: $rc"
	    return 1
    fi
    # The image has been successfully unpacked, set progress to 100
    do_notify_status "100"

    # Set right perms on root directory of installed system
    chmod 0755 "$dst"

    # Remove /image directory of installed system
    rm -fr "$dst"/image

    # Mark installed system as new system to run postinstall scripts
    touch "$dst"/_NEW_SYSTEM_

    # Mount virtual filesystem
    do_notify_stage mount_chroot
    if ! mount_chroot; then
        do_notify_error "Error mounting virtual filesystem"
        return 1
    fi

    # Run systemd-tmpfiles in chroot
    do_notify_stage systemd_tmpfiles_chroot
    if ! systemd_tmpfiles_chroot; then
        do_notify_error "Error running systemd-tmpfiles in chroot"
        return 1
    fi

    # notify interface about finish
    do_notify_stage done
    sync

    return 0
}

### slideshow configuration
read_slideshow_conf()
{
    local step="$(shell_config_get "$slideshow_conf" step)"
    if [ -z "$step" ] || echo "$step" | grep -Evqs '^[[:digit:]]+$'; then
        step="$default_slideshow_step"
    fi
	write_string_param step "$step"

    local once="$(shell_config_get "$slideshow_conf" once)"
    if [ -n "$once" ] && shell_var_is_yes "$once"; then
        once='true'
    else
        once='false'
    fi
    write_bool_param once "$once"

    local url="$(shell_config_get "$slideshow_conf" url)"
    [ -n "$url" ] || url="$default_slideshow_path"
    write_string_param url "$url"
}

on_message()
{
        case "$in_action" in
                read)
                    case "$in__objects" in
                        slideshow-config)
                            read_slideshow_conf
                            ;;
                        *)
                        ;;
                    esac
                    ;;
                write)
                    if [ -n "$install_pid" ] && kill -0 "$install_pid" ;then
                        write_error "Process already running"
                        return
                    fi
                    do_install "$source_dir" "$destdir"&
                    install_pid=$!
                    ;;
        esac
}

message_loop
