#!/bin/sh

__import_old_thickjails () {
    local _name _image _icount _icksum _new_cksum _old_cksum _uuid _irelease

    _name="${1}"
    _image="$(find ${iocroot}/images/ -name ${_name}\*.tar.xz)"
    _icount="$(echo ${_image}|wc -w)"
    _irelease="$(echo ${_image} | cut -d "_" -f 2 | \
        awk 'BEGIN { FS = "." } ; { print $1"."$2 }')"
    _icksum="$(find ${iocroot}/images/ -name ${_name}\*.sha256)"

    # If they don't have a release specified, we assume it's the same as host
    if [ "$(echo ${_irelease} | grep "/")" ] ; then
        # Remove STABLE or CURRENT from the name as we only can fetch RELEASEs
        _irelease="$(echo ${release} | sed -E 's/CURRENT.*|STABLE.*/RELEASE/')"
    fi

    if [ "${_icount}" -gt 0 ] ; then
        echo "* Found image ${_image}"
        echo "* Importing image ${_image}"

        if [ ! -f "${_icksum}" ] ; then
            echo "  ERROR: Missing checksum file!" >&2
            exit 1
        fi

        _new_cksum="$(sha256 -q ${_image})"
        _old_cksum="$(cat ${_icksum})"

        if [ "${_new_cksum}" != "${_old_cksum}" ] ; then
            echo "  ERROR: Checksum mismatch. Exiting." >&2
            exit 1
        else
            # Because any jail being imported this way are thickjails
            export type=thickjail
            _uuid="$(__create_jail "" -e)"
            tar -xvJf "${_image}" -C "${iocroot}/jails/${_uuid}/root"
            __set_jail_prop release="${_irelease}" "${_uuid}" \
                "${pool}/iocell/jails/${_uuid}"
        fi

    else
        __die "image ${_name} not found!"
    fi

    cat "${iocroot}/jails/${_uuid}/root/etc/rc.conf" | \
    sed -E "s/hostname.*/hostname=\"${_uuid}\"/g" \
    > "${iocroot}/jails/${_uuid}/rc.conf"

    mv "${iocroot}/jails/${_uuid}/rc.conf" \
    "${iocroot}/jails/${_uuid}/root/etc/rc.conf"
}

__import () {
    local _name _fulluuid _tag _image _icount _irelease _idate _jail_release \
          _spinner _date _dataset

    _name="${1}"

    if [ -z "${_name}" ] ; then
        __die "missing image UUID!"
    fi

    _image="$(find ${iocroot}/images/ ! -name '*.sha256' -name ${_name}\*)"
    _irelease="$(echo ${_image} | cut -d "_" -f 2 | \
        awk 'BEGIN { FS = "." } ; { print $1"."$2 }')"
    _date=$(date "+%F")
    _idate="$(echo ${_image} | cut -d "-" -f 6-)"
    _icount="$(echo ${_image} | wc -w)"

    if [ -z "${_image}" ] ; then
        __die "${_name} not found!"
    fi

    # If they don't have a release specified, we assume it's the same as host
    if [ "$(echo ${_irelease} | grep "/")" ] ; then
        # Remove STABLE or CURRENT from the name as we only can fetch RELEASEs
        _irelease="$(echo ${release} | sed -E 's/CURRENT.*|STABLE.*/RELEASE/')"
    fi

    if [ "${_icount}" -gt 1 ] ; then
        __die "multiple matching images, please narrow down UUID."
    fi

    if [ -z "$(echo ${_image} | egrep 'thickjail|basejail')" ] ; then
        # Strip the extension off the image name for later
        _image="$(echo ${_image} | cut -d "." -f 1)"

        # Rename old exports to our new naming
        mv "${_image}.tar.xz" \
            "${_image}-thickjail-${_date}.tar.xz"
        mv "${_image}.sha256" \
            "${_image}-thickjail-${_date}.sha256"

        # Make sure _image reflects that new name
        _image="${_image}-thickjail-${_date}.tar.xz"
    fi

    if [ "$(echo ${_image} | egrep 'thickjail.*.tar.xz')" ] ; then
        __export_props "$@"
        __import_old_thickjails "${_name}"
        exit $?
    fi

    if [ -e "${iocroot}/jails/${_name}" ] ; then
        _dataset="$(__find_jail ${_name})" || exit $?
        _fulluuid="$(__check_name ${_name} ${_dataset})"
        _tag="$(__get_jail_prop tag ${_fulluuid} ${_dataset})"
        __die "${_name} has already been imported (${_tag})"
    elif [ ! -e "${iocroot}/releases/${_irelease}" ] ; then
        __die "please fetch ${_irelease} first."
    else
        # __spinner needs to be recreated here as we redirect with zfs send
        _spinner='/-\|'

        printf "  INFO: importing ${_name}:  "

        while true; do
            printf '\b%.1s' "${_spinner}"
            _spinner=${_spinner#?}${_spinner%???}
            sleep .1
        done &

        trap "kill $!" 2 3
        zfs recv -d "${pool}" < "${_image}"
        printf "\b%1s\n" "done!" ; kill $! && trap " " 2 3
    fi
}

__export () {
    local _name _dataset _date _fulluuid _jail_release _spinner _state \
          _jail_path _jail_type _clone_check

    _name="$1"
    _dataset=$(__find_jail ${_name}) || exit $?
    _clone_check="$(zfs get -H origin ${_dataset} | awk '{print $3}')"
    _fulluuid="$(__check_name ${_name} ${_dataset})"
    _jail_type="$(__get_jail_prop type ${_fulluuid} ${_dataset})"
    _tag="$(__get_jail_prop tag ${_fulluuid} ${_dataset})"
    _date=$(date "+%F")
    _jail_release="$(__get_jail_prop release ${_fulluuid} ${_dataset})"
    _export_name="${iocroot}/images/${_fulluuid}-${_jail_type}-${_date}_${_jail_release}"
    _jail_path="$(__get_jail_prop mountpoint ${_fulluuid} ${_dataset})"
    _state=$(jls | grep ${_jail_path} | wc -l)

    if [ -z "${_name}" ] ; then
        __die "missing UUID or TAG!"
    fi

    if [ -z "${_dataset}" ] ; then
        __die "${_name} not found."
    fi

    if [ ! -d "${iocroot}/images" ] ; then
        mkdir ${iocroot}/images
    fi

    if [ "${_jail_type}" = "jail" ] ; then
        # Check for thick or clone jails and migrate their type
        if [ "${_clone_check}" = "-" ] ; then
            __set_jail_prop "type=thickjail" "${_fulluuid}" "${_dataset}"
        else
            __set_jail_prop "type=clonejail" "${_fulluuid}" "${_dataset}"
        fi

        _jail_type="$(__get_jail_prop type ${_fulluuid} ${_dataset})"
        _export_name="${iocroot}/images/${_fulluuid}-${_jail_type}-${_date}_${_jail_release}"
    fi

    if [ "${_state}" -gt "0" ] ; then
        echo "  ERROR: ${_fulluuid} is running!" >&2
        echo "  Stop jail before exporting!" >&2
        exit 1
    fi

    # __spinner needs to be recreated here as we redirect with zfs send
    _spinner='/-\|'

    printf "  INFO: exporting ${_fulluuid} (${_tag}):  "

    while true; do
        printf '\b%.1s' "${_spinner}"
        _spinner=${_spinner#?}${_spinner%???}
        sleep .1
    done &

    trap "kill $!" 2 3
    zfs snapshot -r "${pool}/iocell/jails/${_fulluuid}@ioc-export-${_date}"
    zfs send -R "${pool}/iocell/jails/${_fulluuid}@ioc-export-${_date}" > \
                "${_export_name}"
    zfs destroy -r "${pool}/iocell/jails/${_fulluuid}@ioc-export-${_date}"
    printf "\b%1s\n" "done!" ; kill $! && trap " " 2 3
}
