#!/bin/sh

# Copyright (c) 2022 - 2023 Jolla Ltd.
#
# License: Jolla Proprietary

# Single point of source for all AppSupport paths.

# Default instance
DEFAULT_SERVICE_NAME="appsupport"
DEFAULT_INSTANCE_NAME="default"
DEFAULT_CONFIG_PATH="/tmp/appsupport"
DEFAULT_APPSUPPORT_PATH="/opt/appsupport"
DEFAULT_CONFIG_GROUP="Config"
APPSUPPORT_CONF_D="appsupport.conf.d"
APPSUPPORT_CONFIG_LOCATION="/etc/appsupport.conf.d"

SERVICE_NAME="$DEFAULT_SERVICE_NAME.service"
PREPARE_SERVICE_NAME="$DEFAULT_SERVICE_NAME-prepare.service"
INSTANCE_NAME="$DEFAULT_INSTANCE_NAME"
PARSER_PRINT_LIST=0
PARSER_LOCATION=
CONFIG_GROUP=$DEFAULT_CONFIG_GROUP
CONFIG_KEY=
LOGCAT_OUTPUT=
SYSTEM_IMAGE_NAME="system.img"
BUILD_PROP_NAME="build.prop"
GENERATOR_NAME="appsupport-generate-config"
PARSER_NAME="appsupport-parse-config"
SHIFT_IDS_NAME="shift_ids"
GEN_NET_CFG_NAME="gen_net_cfg"

DO_PRINT=
SET_INSTANCE=0

get_parser_location() {
    get_app_support_path
    # Determine parser location
    if [ -x "$APPSUPPORT_PATH/usr/libexec/appsupport/$PARSER_NAME" ]; then
        PARSER_LOCATION="$APPSUPPORT_PATH/usr/libexec/appsupport/$PARSER_NAME"
    elif [ -x "/usr/libexec/appsupport/$PARSER_NAME" ]; then
        PARSER_LOCATION="/usr/libexec/appsupport/$PARSER_NAME"
    else
        >&2 echo "appsupport-config: $PARSER_NAME not found!"
        exit 1
    fi
}

get_app_support_path() {
    if [ -n "$APPSUPPORT_PATH" ]; then
        return
    fi

    if [ -d "$APPSUPPORT_CONFIG_LOCATION" ]; then
        for CONFIG_FILE in $(ls -1 $APPSUPPORT_CONFIG_LOCATION/*.conf 2>/dev/null| sort); do
            if [ -f "$CONFIG_FILE" ]; then
                _GET_REPLY="$(grep "^AppSupportPath=" "$CONFIG_FILE" | cut -d'=' -f2)"
                if [ -n "$_GET_REPLY" ]; then
                    APPSUPPORT_PATH="$_GET_REPLY"
                fi
            fi
        done
    fi

    if [ -z "$APPSUPPORT_PATH" ]; then
        APPSUPPORT_PATH="$DEFAULT_APPSUPPORT_PATH"
    fi
}

print_libexec_path() {
    get_app_support_path
    if [ -x "$APPSUPPORT_PATH/usr/libexec/appsupport/$1" ]; then
        echo "$APPSUPPORT_PATH/usr/libexec/appsupport/$1"
    elif [ -x "$APPSUPPORT_PATH/libexec/$1" ]; then
        echo "$APPSUPPORT_PATH/libexec/$1"
    elif [ -x "/usr/libexec/appsupport/$1" ]; then
        echo "/usr/libexec/appsupport/$1"
    else
        >&2 echo "appsupport-config: $1 not found!"
        exit 1
    fi
}

_print_allconf() {
    get_app_support_path
    CONF_PATHS="/etc/$APPSUPPORT_CONF_D"
    if [ -d "$APPSUPPORT_PATH/etc/$APPSUPPORT_CONF_D" ]; then
        CONF_PATHS="$APPSUPPORT_PATH/etc/$APPSUPPORT_CONF_D:$CONF_PATHS"
    fi
    echo "$CONF_PATHS"
}

_print_user_name() {
    get_app_support_path
    USER_HOOK_SCRIPT="$APPSUPPORT_PATH/init/get-user-hook"
    if [ -f $USER_HOOK_SCRIPT ]; then
        HOOK_SCRIPT_RET=$($USER_HOOK_SCRIPT)
        RET_CODE=$?
        if [ $RET_CODE -ne 0 ]; then
            >&2 echo "appsupport-config: Failed to run get-user-hook: $RET_CODE"
            exit 1
        fi
    fi
    if [ -z "$HOOK_SCRIPT_RET" ]; then
        HOOK_SCRIPT_RET="root"
    fi
    echo "$HOOK_SCRIPT_RET"
}

while [ $# -gt 0 ]; do
    case $1 in
        --help|-h)
            echo "Usage: $0 <option>"
            echo ""
            echo "  --base      -b      Base installation path."
            echo "  --baseconf  -a      Base config file location."
            echo "  --allconf           All config locations to consider, separated by ':'."
            echo "  --config    -c      Config file for the instance."
            echo "  --path      -p      Config path for the instance."
            echo "  --lxc-path  -l      Global LXC path."
            echo "  --system    -s      Get path of system image."
            echo "  --rootfs    -r      Location for mounting system image."
            echo "  --data      -d      Data root."
            echo "  --name      -n      Name of the service."
            echo "  --user      -u      Get name of the user using the container."
            echo "  --get-prop  -g      Read value from build properties."
            echo "  --is-running        If AppSupport instance is running."
            echo "  --logcat <FILE>     Output long-term logcat logs to FILE, if file name"
            echo "                      ends with .xz the file is compressed."
            echo "  --value     -v      Read single value from AppSupport config."
            echo "                      AppSupport needs to be running."
            echo "                      Defined as CONFIG_GROUP/CONFIG_KEY. If"
            echo "                      CONFIG_GROUP is not defined default to"
            echo "                      $CONFIG_GROUP/CONFIG_KEY."
            echo "                      Exit code 2 when key does not exist."
            echo "                      Arguments for --value:"
            echo "                          --list      List all values for the"
            echo "                                      key, not only last."
            echo ""
            echo "  --instance  -i      Use instance other than $DEFAULT_INSTANCE_NAME."
            echo ""
            echo "  --shift             Path to $SHIFT_IDS_NAME helper."
            echo "  --gen_net_cfg       Path to $GEN_NET_CFG_NAME helper."
            echo "  --generate          Path to appsupport-generate-config."
            echo ""
            echo "  --version           Print AppSupport version."
            echo ""
            exit 0
            ;;
        --user|-u)
            _print_user_name
            exit 0
            ;;
        --base|-b)
            get_app_support_path
            echo "$APPSUPPORT_PATH"
            exit 0
            ;;
        --baseconf|-a)
            get_app_support_path
            INSTALL_CONFIG_PATH="$APPSUPPORT_PATH/etc"
            if [ -d "$INSTALL_CONFIG_PATH/$APPSUPPORT_CONF_D" ]; then
                echo "$INSTALL_CONFIG_PATH"
            else
                echo "/etc"
            fi
            exit 0
            ;;
        --allconf)
            _print_allconf
            exit 0
            ;;
        --get-prop|-g)
            shift
            if [ -z "$1" ]; then
                >&2 echo "appsupport-config: No property given."
                exit 1
            fi
            PROP_NAME="$1"
            get_app_support_path
            BUILD_PROP="$APPSUPPORT_PATH/$BUILD_PROP_NAME"
            if [ ! -f "$BUILD_PROP" ]; then
                >&2 echo "appsupport-config: $BUILD_PROP_NAME not found in $APPSUPPORT_PATH!"
                exit 1
            fi
            PROP_VALUE="$(grep "^$PROP_NAME=" "$BUILD_PROP")"
            if [ $? -ne 0 ]; then
                exit 1
            fi
            echo "$PROP_VALUE" | cut -d'=' -f2-
            exit 0
            ;;
        --value|-v)
            shift
            if [ -z "$1" ]; then
                >&2 echo "appsupport-config: No key name given."
                exit 1
            fi

            CONFIG_GROUP="$(echo "$1" | cut -d'/' -f1)"
            CONFIG_KEY="$(echo "$1" | cut -d'/' -f2)"
            if [ "$CONFIG_GROUP" = "$CONFIG_KEY" ]; then
                CONFIG_GROUP="$DEFAULT_CONFIG_GROUP"
            fi
            DO_PRINT=value
            ;;
        --list)
            PARSER_PRINT_LIST=1
            ;;
        --system|-s)
            # Wrapper for --value call
            SYSTEM_IMAGE_PATH="$($0 -v Config/SystemImagePath)"
            if [ -z "$SYSTEM_IMAGE_PATH" ]; then
                get_app_support_path
                SYSTEM_IMAGE_PATH="$APPSUPPORT_PATH/$SYSTEM_IMAGE_NAME"
            fi
            echo "$SYSTEM_IMAGE_PATH"
            exit 0
            ;;
        --rootfs|-r)
            # Wrapper for --value call
            ROOTFS_PATH="$($0 -v Config/RootFsPath)"
            if [ -z "$ROOTFS_PATH" ]; then
                get_app_support_path
                ROOTFS_PATH="$APPSUPPORT_PATH/rootfs"
            fi
            echo "$ROOTFS_PATH"
            exit 0
            ;;
        --config|-c)
            DO_PRINT=config
            SET_INSTANCE=0
            ;;
        --path|-p)
            DO_PRINT=path
            SET_INSTANCE=0
            ;;
        --lxc-path|-l)
            echo "$DEFAULT_CONFIG_PATH"
            exit 0
            ;;
        --data|-d)
            DO_PRINT=value
            CONFIG_GROUP="Config"
            CONFIG_KEY="DataRoot"
            ;;
        --name|-n)
            DO_PRINT=name
            SET_INSTANCE=0
            ;;
        --prepare-name|-n)
            DO_PRINT=preparename
            SET_INSTANCE=0
            ;;
        --instance|-i)
            SET_INSTANCE=1
            ;;
        --shift)
            print_libexec_path $SHIFT_IDS_NAME
            exit 0
            ;;
        --$GEN_NET_CFG_NAME)
            print_libexec_path $GEN_NET_CFG_NAME
            exit 0
            ;;
        --generate)
            print_libexec_path $GENERATOR_NAME
            exit 0
            ;;
        --parse)
            print_libexec_path $PARSER_NAME
            exit 0
            ;;
        --is-running)
            DO_PRINT=is_running
            ;;
        --logcat)
            DO_PRINT=logcat
            if [ -t 1 ]; then
                shift
                if [ -z "$1" ]; then
                    >&2 echo "appsupport-config: No logcat output file given."
                    exit 1
                fi
                LOGCAT_OUTPUT="$1"
            fi
            ;;
        --version)
            # First check if we have global version file
            get_app_support_path
            if [ -f "$APPSUPPORT_PATH/version" ]; then
                cat "$APPSUPPORT_PATH/version"
                exit 0
            fi
            # Then check if we are running rpm deployment
            if which rpm 1>/dev/null; then
                ANY_PRINTED=0
                for PACKAGE_NAME in \
                                    appsupport11-system-privileged \
                                    appsupport11-system-unprivileged \
                                    aliendalvik-configs \
                                    alienkeyboardservice \
                                    apkd-plugin-geo-qtpositioning \
                                    apkd-plugin-media-mpris \
                                    apkd-plugin-notifications-fdo-ext \
                                    apkd-plugin-permissions-sfos \
                                    apkd8 \
                                    apkd8-android-settings \
                                    apkd8-l10n-all-translations \
                                    libapkd \
                                    appsupport-config-generator \
                                    appsupport-configs-user \
                                    appsupport-overlay \
                                    alienaudioservice \
                                    alienaudioservice-plugin-pulseaudio \
                                    alienaudioservice-plugin-sailfish \
                                    libalienaudioservice \
                                    ofono-alien-binder-plugin \
                                    ; do
                    PACKAGE_VERSION="$(rpm -q $PACKAGE_NAME --queryformat='%{NAME} %{VERSION}')"
                    if [ $? -eq 0 ]; then
                        echo "$PACKAGE_VERSION"
                        ANY_PRINTED=1
                    fi
                done
                if [ $ANY_PRINTED -eq 1 ]; then
                    exit 0
                fi
            fi
            >&2 echo "Could not extract version info."
            exit 1
            ;;
        -*)
            >&2 echo "appsupport-config: Invalid argument: $1"
            exit 1
            ;;
        *)
            if [ $SET_INSTANCE -eq 1 ]; then
                INSTANCE_NAME="$1"
                if [ "$1" != "$DEFAULT_INSTANCE_NAME" ] || [ ! -f "/usr/lib/systemd/system/$DEFAULT_SERVICE_NAME.service" ]; then
                    SERVICE_NAME="$DEFAULT_SERVICE_NAME@$INSTANCE_NAME.service"
                    PREPARE_SERVICE_NAME="$DEFAULT_SERVICE_NAME-prepare@$INSTANCE_NAME.service"
                fi
                SET_INSTANCE=2
            else
                >&2 echo "appsupport-config: Invalid arguments."
                exit 1
            fi
    esac

    shift
done

case $DO_PRINT in
    config)
        echo "$DEFAULT_CONFIG_PATH/$INSTANCE_NAME/config"
        exit 0
        ;;
    path)
        echo "$DEFAULT_CONFIG_PATH/$INSTANCE_NAME"
        exit 0
        ;;
    name)
        echo "$SERVICE_NAME"
        exit 0
        ;;
    preparename)
        echo "$PREPARE_SERVICE_NAME"
        exit 0
        ;;
    is_running)
        [ -d "$DEFAULT_CONFIG_PATH/$INSTANCE_NAME" ] && systemctl is-active --quiet $SERVICE_NAME
        exit $?
        ;;
    logcat)
        for LOGGER_PID in $(pidof appsupport_logger); do
            if grep -q -- "-i.$INSTANCE_NAME" /proc/$LOGGER_PID/cmdline; then
                kill -usr1 $LOGGER_PID
                sleep 1
            fi
        done
        LOG_PATH="$($0 -i $INSTANCE_NAME -v Config/LogcatLogPath)"
        if [ ! -t 1 ]; then
            for LOG_FILE in $(ls -1 "${LOG_PATH}/${INSTANCE_NAME}".*.log.xz 2>/dev/null | sort); do
                xz -d -c "$LOG_FILE"
            done
        else
            FILE_COUNT="$(ls -1 "${LOG_PATH}/${INSTANCE_NAME}".*.log.xz 2>/dev/null | wc -l)"
            if [ $FILE_COUNT -gt 0 ]; then
                if [ "${LOGCAT_OUTPUT: -3}" != ".gz" ]; then
                    LOGCAT_OUTPUT="$LOGCAT_OUTPUT.gz"
                    >&2 echo "Adding gzip suffix, output is $LOGCAT_OUTPUT"
                fi
                echo -n "" > "$LOGCAT_OUTPUT"
                if [ $? -ne 0 ]; then
                    exit 1
                fi
                (
                    FILE_I=0
                    for LOG_FILE in $(ls -1 "${LOG_PATH}/${INSTANCE_NAME}".*.log.xz 2>/dev/null | sort); do
                        FILE_I=$(($FILE_I + 1))
                        >&2 echo -n -e "concatenating logs... [$FILE_I/$FILE_COUNT]\r"
                        xz -d -c "$LOG_FILE"
                    done
                ) | gzip -c >> "$LOGCAT_OUTPUT"
                >&2 echo
            else
                >&2 echo "No logs."
            fi
        fi
        exit 0
        ;;
    value)
        get_parser_location
        CONFIGS_LOCATION="$DEFAULT_CONFIG_PATH/$INSTANCE_NAME/config.d"
        PARSER_ARGS=
        if [ ! -d "$CONFIGS_LOCATION" ] || ! systemctl is-active --quiet $PREPARE_SERVICE_NAME; then
            CONFIGS_LOCATION="$(_print_allconf)"
            USER_NAME="$(_print_user_name)"
            USER_UID=$(getent passwd $USER_NAME | cut -d: -f3)
            PARSER_ARGS="--instance $INSTANCE_NAME --user-id $USER_UID"
        fi

        if [ $PARSER_PRINT_LIST -eq 1 ]; then
            PRINT_LIST="--list"
        fi

        exec $PARSER_LOCATION --configs "$CONFIGS_LOCATION" \
                              $PARSER_ARGS \
                              $PRINT_LIST \
                              --group $CONFIG_GROUP \
                              --key "$CONFIG_KEY"
        exit $?
        ;;
esac

>&2 echo "appsupport-config: Invalid arguments."
exit 1
