#!/bin/sh -efu

. install2-sh-functions

cmdline_has_arg expertmode && verbose=1 || verbose=

verbose()
{
	if [ -n "$verbose" ]; then
		msg "$@"
	fi
}

# Get file from remote HTTP or FTP server.
# Usage:   get_rfile <from> <to>
# Example: get_rfile "http://bigtits.ru/run.me" "/tmp/run.me"
get_rfile()
{
    local curl_opt_cmn="--connect-timeout 2 \
                        --max-time 2 \
                        --retry 5 \
                        --retry-delay 2 \
                        --show-error \
                        --create-dirs \
                        --silent \
                        --write-out %{http_code}"
    local curl_opt_ftp="$curl_opt_cmn --ftp-pasv"
    local curl_opt_http="$curl_opt_cmn"

    local url=$1 && shift
    local out=$1 && shift
    local ret=-1
    local curl_opt=
    local is_http=$(expr match "$url" '\(http\)')
    local is_ftp=$(expr match "$url" '\(ftp\)')

    [ -z "$url" ] && return $ret
    [ -z "$out" ] && return $ret
    [ -x "/usr/bin/curl" ] || return $ret
    [ -n "$is_http$is_ftp" ] || return $ret

    if [ -n "$is_ftp}" ]; then
        curl_opt="$curl_opt_ftp"
    elif [ -n "$is_http" ]; then
        curl_opt="$curl_opt_http"
    else
        return $ret
    fi

    ret_code="$(curl $curl_opt --url "$url" --output "$out")"

    if [ -n "$is_ftp" ]; then
        [ $ret_code -ne 226 ] || ret=0
    elif [ -n "$is_http" ]; then
        [ $ret_code -ne 200 ] || ret=0
    fi

    return $ret
}

# get_remote_metadata - get metadata file for installer.
# Metadata file can be:
# * group packages            - set of packages for provide one global future.
# * auto installation profile - steps for alterator backends.
# * alterator-vm profile      - auto prepare disks for further installation.
# * etc...
get_remote_metadata() {
    local n="$1";shift
    local bn="$(basename "$n")"
    local success=

    # First possible location: `curl=' cmdline option.
    local src1=

    # Second possible location: network-shared media location.
    local src2="$image_url/Metadata/$bn"

    # Metadata files location can be supplied via cmdline. `curl=<http|ftp>' option.
    local url=$(sed -ne 's,^.\+curl=\(\(http\|ftp\)://[^[:blank:]]\+\)\(.\+\|$\),\1,p' /proc/cmdline)

    if [ -n "$url" ]; then
        # `curl=' option supplied. I.e: curl=http://192.168.5.1/installer/metadata/
	if ! type -t curl >&/dev/null; then
	    verbose "ERROR: \`curl=' option given but no curl binary found!"
	fi
        src1="$url/$bn"
        # Check network existence.
        printf "\nwait for DHCP"
        try=0
        ip=
        while [ -z "$ip" -a $try -lt 60 ]; do
            ip="$(ip addr show | grep -v 127.0.0.1 | sed -n 's,.*[[:space:]]inet[[:space:]]\+\([^/]\+\)/.*,\1,p' |head -n1)"
            echo -n ".$try"
            sleep 1
            try=$((try +1))
        done
    else
        verbose "No \`curl=' option supplied for remote metadata. It is OK!"
    fi

    # Fetch metadata from pointed by `curl='
    if [ -n "$src1" ]; then
        # Add .tmp suffix. Due `curl' create output file even on error fetch from HTTP/FTP.
        if get_rfile "$src1" "$n.tmp"; then
            msg "Successfuly fetched metadata file $src2. Store it as $n.tmp"
            success=1
        else
            verbose "Can't fetch specified $src1. It is OK!. Try another method."
        fi
    fi

    # Fetch metadata from standard place
    if [ -z "$success" ]; then
        if get_rfile "$src2" "$n.tmp"; then
            msg "Successfuly fetched metadata file $src2. Store it as $n.tmp"
        else
            verbose "Can't fetch default $src2. It is OK!. Try another method."
            return 1
        fi
    fi

    # Rename fetched file to right name.
    if mv -f "$n.tmp" "$n"; then
        msg "Rename $n.tmp -> $n"
    else
        msg "Can't move $n.tmp to $n"
        return 1
    fi

    return 0
}

# Copy metadata-file from file system.
# Usage:   get_local_metadata <src> <dst>
# Example: get_local_metadata "/image/Metadata/autoinstall.scm" "/tmp/metadata/autoinstall.scm"
get_local_metadata() {
    # Path to source file
    local src="$1";shift

    # Path to destination file
    local dst="$1";shift

    # Check src file for existence
    if ! [ -f "$src" -a -r "$src" ]; then
        verbose "Can't find $src. It is OK!. Try another method."
        return 1
    fi

    # Actual copy.
    if ! cp -af "$src" "$dst"; then
        msg "Can't copy metadata file from $src to $dst"
        return 1
    fi

    verbose "Successfuly copied metadata file from $src to $dst"
    return 0
}

# Entry point.

# Dst file path
readonly dst_file="$1"

if [ -z "$dst_file" ]; then
    fatal "Bad invocation with \`$dst_file'"
fi

# Dst/src file basename
readonly basename="$(basename "$dst_file")"

# Dst directory name
readonly dst_dir="$(dirname "$dst_file")"

# Check target directory existence
if ! [ -d "$dst_dir" -a -w "$dst_dir" ]; then
    fatal "$dst_dir directory doesn't exist."
fi

case "$METHOD" in
	http|ftp|cdrom|disk|nfs|cifs)
        # Get remote metadata
        get_remote_metadata "$dst_file" ||
            # Failback to installation media (CD/DVD/FLASH/NFS) metadata
        get_local_metadata "$image_url/Metadata/$basename" "$dst_file" ||
            # Failback to metadata from RPM-packets (installer-feat-*).
        get_local_metadata "/usr/share/install2/metadata/$basename" "$dst_file" ||
            # Hope for the best, and go to install without requested metadata.
        msg "Can't build $dst_file using all known methods."
        ;;
    *)
        fatal "Unsupported installation method: $METHOD."
esac
