#!/bin/bash

# 文件放在 /usr/share/initramfs-tools/scripts/local-bottom/ 目录下
# 权限为 0755，执行 update-initramfs -u

err_mount_failed=10
err_umount_failed=11
err_rsync_failed=12
err_fstable_not_exist=13
err_uuid_not_exist=14
err_invalid_mount_type=15
err_uos_recovery_ini_not_exist=17

FSTABLE_PATH=
LOG_FILE=
LOG_LEVEL=

for x in $(cat /proc/cmdline); do
    case $x in
        recovery.debug)
            LOG_LEVEL=debug
            ;;
    esac
done

init_log()
{
    local backup_dir_prefix="/tmp/uos/backup"
    local date=`date +"%Y%m%d_%H%M%S"`
    local logpath=${backup_dir_prefix}/log
    mkdir -p ${logpath}
    LOG_FILE="$logpath/uos-restore-sys_$date.log"

    write_log "init_log, rootpath = ${rootmnt}, logpath = $logpath, LOG_FILE = $LOG_FILE"
}

copy_log()
{
    local log_dest_path=$1
    if [ x"$log_dest_path" = x ]; then
        # default log dest path
        log_dest_path=${rootmnt}/var/log/deepin/uos-recovery/restore/
    fi

    if [ ! -d $log_dest_path ]; then
        mkdir -p $log_dest_path
    fi

    cp -vrf $LOG_FILE $log_dest_path
    sync
    sync
    sync
}

dump_log()
{
    echo "dump log: "
    tail -n 50 $LOG_FILE
    echo "dump partition by lsblk:"
    echo "`lsblk -f`"
    sleep 15
}

write_log()
{
    if [ "$LOG_LEVEL" = "debug" ]; then
        echo "$1" | tee -a $LOG_FILE
        # 日志保存失败的话,加sleep方便在界面直接定位
        sleep 5
    else
        echo "$1" &>> $LOG_FILE
    fi
}

plymouth_output()
{
    #TODO:
    echo "$1"
}

display_result()
{
    RET=$1
    if [ $RET -eq $err_mount_failed ]; then
        plymouth_output "err, mount failed!"
    elif [ $RET -eq $err_umount_failed ]; then
        plymouth_output "err, umount failed!"
    elif [ $RET -eq $err_rsync_failed ]; then
        plymouth_output "err, rsync failed!"
    elif [ $RET -eq $err_fstable_not_exist ]; then
        plymouth_output "err, fstab not exist!"
    elif [ $RET -eq $err_uuid_not_exist ]; then
        plymouth_output "err, uuid not exist!"
    elif [ $RET -eq $err_invalid_mount_type ]; then
        plymouth_output "err, invalid mount type!"
    else
        plymouth_output "err, unkown error!"
    fi
}

is_fstab_exist()
{
    FSTABLE_PATH=${rootmnt}/etc/fstab
    if [ ! -e "$FSTABLE_PATH" ]; then
        write_log "is_fstab_exist: $FSTABLE_PATH file not exist!"
        return $err_fstable_not_exist
    fi

    return 0
}


mount_fstab()
{
    local rootpath=${rootmnt}
    local fstable_path=$FSTABLE_PATH
    local logfile=$LOG_FILE
    write_log "mount_fstab: fstable_path = $fstable_path, rootpath = $rootpath, begin"
#    plymouth_output "mount_fstab: fstable_path = $fstable_path, rootpath = $rootpath, begin"
    local boot_uuid=
    local boot_mountpoint=
    local efi_uuid=
    local efi_mountpoint=

    while read fstabline; do
        # eg: UUID=bfc917ad-6f18-462b-af29-9bc823fd726d       /    ext4    rw,relatime    0 1
        if [ "${fstabline:0:5}" != "UUID=" ]; then
            continue
        fi

        fstype=$(echo "$fstabline" | awk '{print $3}')
        if [ $fstype = "swap" ]; then
            continue
        fi

        uuid=$(echo "$fstabline" | awk '{print $1}')
        if echo $uuid | grep -E -q "^UUID="; then
            uuid=$(echo "$uuid" | awk -F '=' '{print $2}')
        fi

        mountpoint=$(echo "$fstabline" | awk '{print $2}')
        if [ $mountpoint = "/" ]; then
            continue
        fi

        write_log  "fstype = $fstype, mountpoint = $mountpoint, uuid = $uuid"
        if [ $mountpoint = "/boot" ]; then
            boot_uuid=$uuid
            boot_mountpoint=$mountpoint
            continue
        fi

        if [ $mountpoint = "/boot/efi" ]; then
            efi_uuid=$uuid
            efi_mountpoint=$mountpoint
            continue
        fi

        if [ ! -e $rootpath$mountpoint ]; then
            write_log " Warnning! mount_fstab $rootpath$mountpoint not exit, create it "
            mkdir -p $rootpath$mountpoint
        fi

        ${rootmnt}/usr/bin/mount -U $uuid $rootpath$mountpoint &>>$logfile
        if [ $? -ne 0 ]; then
            write_log " mount_fstab mount error !, umount it, uuid=$uuid, mountPoint= $rootpath$mountpoint"
            ${rootmnt}/usr/bin/umount $rootpath$mountpoint &>>$logfile
            write_log " mount_fstab mount again ... "
            ${rootmnt}/usr/bin/mount -U $uuid $rootpath$mountpoint &>>$logfile
            #return $err_mount_failed
        fi
    done < "$fstable_path"

    # 先mount /boot
    if [ x"$boot_uuid" != x ]; then
        ${rootmnt}/usr/bin/mount -U $boot_uuid $rootpath$boot_mountpoint &>>$logfile
        if [ $? -ne 0 ]; then
            write_log " mount_fstab mount error !, umount it, boot_uuid=$boot_uuid, mountPoint= $rootpath$boot_mountpoint"
            ${rootmnt}/usr/bin/umount $rootpath$boot_mountpoint &>>$logfile
            write_log " mount_fstab mount again ... "
            ${rootmnt}/usr/bin/mount -U $boot_uuid $rootpath$boot_mountpoint &>>$logfile
        fi
    fi

    if [ x"$efi_uuid" != x ]; then
        ${rootmnt}/usr/bin/mount -U $efi_uuid $rootpath$efi_mountpoint &>>$logfile
        if [ $? -ne 0 ]; then
            write_log " mount_fstab mount error !, umount it, efi_uuid=$efi_uuid, efi_mountpoint= $rootpath$efi_mountpoint"
            ${rootmnt}/usr/bin/umount $rootpath$efi_mountpoint &>>$logfile
            write_log " mount_fstab mount again ... "
            ${rootmnt}/usr/bin/mount -U $efi_uuid $rootpath$efi_mountpoint &>>$logfile
        fi
    fi

    mount_bind
    local errcode=$?
    if [ $errcode -ne 0 ]; then
        write_log " mount_fstab: mount_bind error, rootpath = $rootpath, errcode = $errcode"
        return $errcode
    fi

    return 0
}

umount_fstab()
{
    local rootpath=${rootmnt}
    local fstable_path=$FSTABLE_PATH
    local logfile=$LOG_FILE
    local boot_mountpoint=
    local efi_mountpoint=

    umount_bind
    local errcode=$?
    if [ $errcode -ne 0 ]; then
        write_log " umount_fstab: umount_bind error, rootpath = $rootpath, errcode = $errcode"
        return $errcode
    fi
    write_log "umount_fstab: fstable_path = $fstable_path, rootpath = $rootpath, begin"

    while read fstabline; do
        # eg: UUID=bfc917ad-6f18-462b-af29-9bc823fd726d       /    ext4    rw,relatime    0 1
        if [ "${fstabline:0:5}" != "UUID=" ]; then
            continue
        fi

        mountpoint=$(echo "$fstabline" | awk '{print $2}')
        if [ $mountpoint = "/" ]; then
            continue
        fi

        fstype=$(echo "$fstabline" | awk '{print $3}')
        if [ $fstype = "swap" ]; then
            continue
        fi

        write_log "fstype = $fstype, mountpoint = $mountpoint"
        if [ $mountpoint = "/boot" ]; then
            boot_mountpoint=$mountpoint
            continue
        fi

        if [ $mountpoint = "/boot/efi" ]; then
            efi_mountpoint=$mountpoint
            continue
        fi

        if [ ! -e $rootpath$mountpoint ]; then
            write_log " Warnning! umount_fstab $rootpath$mountpoint not exit "
            continue
        fi

        ${rootmnt}/usr/bin/umount $rootpath$mountpoint &>>$logfile
        if [ $? -ne 0 ]; then
            write_log " umount_fstab umount error !, exit "
            return $err_umount_failed
        fi
    done < "$fstable_path"

    # 先卸载 /boot/efi, 后卸载 /boot
    if [ x"$efi_mountpoint" != x ]; then
        ${rootmnt}/usr/bin/umount $rootpath$efi_mountpoint &>>$logfile
        if [ $? -ne 0 ]; then
            write_log " umount_fstab umount error !, efi_mountpoint= $rootpath$efi_mountpoint"
            return $err_umount_failed
        fi
    fi

    if [ x"$boot_mountpoint" != x ]; then
        ${rootmnt}/usr/bin/umount $rootpath$boot_mountpoint &>>$logfile
        if [ $? -ne 0 ]; then
            write_log " umount_fstab umount error !, boot_mountpoint= $rootpath$boot_mountpoint"
            return $err_umount_failed
        fi
    fi

    return 0
}

mount_bind()
{
    local rootpath=${rootmnt}
    local fstable_path=$FSTABLE_PATH
    local logfile=$LOG_FILE
    write_log "mount_bind: fstable_path= $fstable_path, rootpath=$rootpath"

    while read fstabline; do
        # eg: /data/home /home none defaults,bind 0 0
        if [ "${fstabline:0:1}" != "/" ]; then
            continue
        fi

        bind_flag=$(echo "$fstabline" | awk -F ',' '{print $2}' | awk '{print $1}')
        write_log "mount_bind: fstabline: $fstabline, bind_flag= $bind_flag"
        if [ "${bind_flag}" != "bind" ]; then
            continue
        fi
        olddir=$(echo "$fstabline" | awk '{print $1}')
        newdir=$(echo "$fstabline" | awk '{print $2}')

        write_log "mount_bind: bind_flag = $bind_flag, olddir = $olddir, newdir = $newdir"
        if [ ! -e $rootpath$newdir ]; then
            write_log " Warnning! mount_bind $rootpath$newdir not exit , create it"
            mkdir -p $rootpath$newdir
        fi

        ${rootmnt}/usr/bin/mount --bind $rootpath$olddir $rootpath$newdir &>>$logfile
        if [ $? -ne 0 ]; then
            write_log " mount_bind mount --bind error !, exit "
            return $err_mount_failed
        fi
    done < "$fstable_path"

    return 0
}

umount_bind()
{
    local rootpath=${rootmnt}
    local fstable_path=$FSTABLE_PATH
    local logfile=$LOG_FILE
    write_log "umount_bind: fstable_path= $fstable_path, rootpath=$rootpath"

    while read fstabline; do
        # eg: /data/home /home none defaults,bind 0 0
        if [ "${fstabline:0:1}" != "/" ]; then
            continue
        fi

        bind_flag=$(echo "$fstabline" | awk -F ',' '{print $2}' | awk '{print $1}')
        write_log "umount_bind: fstabline: $fstabline, bind_flag= $bind_flag"
        if [ "${bind_flag}" != "bind" ]; then
            continue
        fi
        olddir=$(echo "$fstabline" | awk '{print $1}')
        newdir=$(echo "$fstabline" | awk '{print $2}')

        write_log "umount_bind: bind_flag = $bind_flag, olddir = $olddir, newdir = $newdir"

        if [ ! -e $rootpath$newdir ]; then
            write_log " Warnning! umount_bind $rootpath$newdir not exit "
            continue
        fi
        ${rootmnt}/usr/bin/umount $rootpath$newdir &>>$logfile
        if [ $? -ne 0 ]; then
            write_log " umount_bind umount error !, exit "
            return $err_umount_failed
        fi
    done < "$fstable_path"

    return 0
}

ini_get()
{
    local file_path=$1
    local section=$2
    local key=$3

    local val=$(awk -F "=" '/\['${section}'\]/{a=1}a==1&&$1~/'${key}'/{print $2;exit}' $file_path)
    echo $val
}

# ini 文件里的 key 不要重复，暂时还不支持重复的key在不同的section里
ini_set()
{
    local file_path=$1
    local key=$2
    local val=$3
    val=$(echo ${val//\\/\/})

    sed -i "/^$key/s/=.*/=$val/" $file_path
    write_log "ini_set file_path=$file_path, key=$key, val=$val"
}
