# Check if apt is free to use, or wait, until timeout.
#
# [internal]
#
# usage: ynh_wait_dpkg_free
ynh_wait_dpkg_free() {
    local try
    # With seq 1 17, timeout will be almost 30 minutes
    for try in `seq 1 17`
    do
        # Check if /var/lib/dpkg/lock is used by another process
        if sudo lsof /var/lib/dpkg/lock > /dev/null
        then
            echo "apt is already in use..."
            # Sleep an exponential time at each round
            sleep $(( try * try ))
        else
            return 0
        fi
    done
    echo "apt still used, but timeout reached !"
}

# Check either a package is installed or not
#
# example: ynh_package_is_installed 'yunohost' && echo "ok"
#
# usage: ynh_package_is_installed name
# | arg: name - the package name to check
ynh_package_is_installed() {
    ynh_wait_dpkg_free
    dpkg-query -W -f '${Status}' "$1" 2>/dev/null \
        | grep -c "ok installed" &>/dev/null
}

# Get the version of an installed package
#
# example: version=$(ynh_package_version 'yunohost')
#
# usage: ynh_package_version name
# | arg: name - the package name to get version
# | ret: the version or an empty string
ynh_package_version() {
    if ynh_package_is_installed "$1"; then
        dpkg-query -W -f '${Version}' "$1" 2>/dev/null
    else
        echo ''
    fi
}

# APT wrapper for non-interactive operation
#
# [internal]
#
# usage: ynh_apt update
ynh_apt() {
    ynh_wait_dpkg_free
    DEBIAN_FRONTEND=noninteractive sudo apt-get -y $@
}

# Update package index files
#
# usage: ynh_package_update
ynh_package_update() {
    ynh_apt update
}

# Install package(s)
#
# usage: ynh_package_install name [name [...]]
# | arg: name - the package name to install
ynh_package_install() {
    ynh_apt --no-remove -o Dpkg::Options::=--force-confdef \
            -o Dpkg::Options::=--force-confold install $@
}

# Remove package(s)
#
# usage: ynh_package_remove name [name [...]]
# | arg: name - the package name to remove
ynh_package_remove() {
    ynh_apt remove $@
}

# Remove package(s) and their uneeded dependencies
#
# usage: ynh_package_autoremove name [name [...]]
# | arg: name - the package name to remove
ynh_package_autoremove() {
    ynh_apt autoremove $@
}

# Purge package(s) and their uneeded dependencies
#
# usage: ynh_package_autopurge name [name [...]]
# | arg: name - the package name to autoremove and purge
ynh_package_autopurge() {
    ynh_apt autoremove --purge $@
}

# Build and install a package from an equivs control file
#
# [internal]
#
# example: generate an empty control file with `equivs-control`, adjust its
#          content and use helper to build and install the package:
#              ynh_package_install_from_equivs /path/to/controlfile
#
# usage: ynh_package_install_from_equivs controlfile
# | arg: controlfile - path of the equivs control file
ynh_package_install_from_equivs () {
    local controlfile=$1

    # retrieve package information
    local pkgname=$(grep '^Package: ' $controlfile | cut -d' ' -f 2)	# Retrieve the name of the debian package
    local pkgversion=$(grep '^Version: ' $controlfile | cut -d' ' -f 2)	# And its version number
    [[ -z "$pkgname" || -z "$pkgversion" ]] \
        && echo "Invalid control file" && exit 1	# Check if this 2 variables aren't empty.

    # Update packages cache
    ynh_package_update

    # Build and install the package
    local TMPDIR=$(mktemp -d)

    # Force the compatibility level at 10, levels below are deprecated 
    echo 10 > /usr/share/equivs/template/debian/compat

    # Note that the cd executes into a sub shell
    # Create a fake deb package with equivs-build and the given control file
    # Install the fake package without its dependencies with dpkg
    # Install missing dependencies with ynh_package_install
    ynh_wait_dpkg_free
    (cp "$controlfile" "${TMPDIR}/control" && cd "$TMPDIR" \
     && equivs-build ./control 1>/dev/null \
     && sudo dpkg --force-depends \
          -i "./${pkgname}_${pkgversion}_all.deb" 2>&1 \
     && ynh_package_install -f) || ynh_die "Unable to install dependencies"
    [[ -n "$TMPDIR" ]] && rm -rf $TMPDIR	# Remove the temp dir.

    # check if the package is actually installed
    ynh_package_is_installed "$pkgname"
}

# Define and install dependencies with a equivs control file
# This helper can/should only be called once per app
#
# usage: ynh_install_app_dependencies dep [dep [...]]
# | arg: dep - the package name to install in dependence
#   You can give a choice between some package with this syntax : "dep1|dep2"
#   Example : ynh_install_app_dependencies dep1 dep2 "dep3|dep4|dep5"
#   This mean in the dependence tree : dep1 & dep2 & (dep3 | dep4 | dep5)
ynh_install_app_dependencies () {
    local dependencies=$@
    local dependencies=${dependencies// /, }
    local dependencies=${dependencies//|/ | }
    local manifest_path="../manifest.json"
    if [ ! -e "$manifest_path" ]; then
    	manifest_path="../settings/manifest.json"	# Into the restore script, the manifest is not at the same place
    fi

    local version=$(grep '\"version\": ' "$manifest_path" | cut -d '"' -f 4)	# Retrieve the version number in the manifest file.
    if [ ${#version} -eq 0 ]; then
        version="1.0"
    fi
    local dep_app=${app//_/-}	# Replace all '_' by '-'

    cat > /tmp/${dep_app}-ynh-deps.control << EOF	# Make a control file for equivs-build
Section: misc
Priority: optional
Package: ${dep_app}-ynh-deps
Version: ${version}
Depends: ${dependencies}
Architecture: all
Description: Fake package for ${app} (YunoHost app) dependencies
 This meta-package is only responsible of installing its dependencies.
EOF
    ynh_package_install_from_equivs /tmp/${dep_app}-ynh-deps.control \
        || ynh_die "Unable to install dependencies"	# Install the fake package and its dependencies
    rm /tmp/${dep_app}-ynh-deps.control
    ynh_app_setting_set $app apt_dependencies $dependencies
}

# Remove fake package and its dependencies
#
# Dependencies will removed only if no other package need them.
#
# usage: ynh_remove_app_dependencies
ynh_remove_app_dependencies () {
    local dep_app=${app//_/-}	# Replace all '_' by '-'
    ynh_package_autopurge ${dep_app}-ynh-deps	# Remove the fake package and its dependencies if they not still used.
}