#!/usr/bin/env sh

android_sdk_root() {
    if [ -n "${ANDROID_SDK_ROOT:-}" ] && [ -d "$ANDROID_SDK_ROOT" ]; then
        printf '%s\n' "$ANDROID_SDK_ROOT"
        return 0
    fi

    if [ -n "${ANDROID_HOME:-}" ] && [ -d "$ANDROID_HOME" ]; then
        printf '%s\n' "$ANDROID_HOME"
        return 0
    fi

    if [ -n "${LOCALAPPDATA:-}" ]; then
        local_sdk="$LOCALAPPDATA/Android/Sdk"
        if command -v cygpath >/dev/null 2>&1; then
            local_sdk="$(cygpath -u "$local_sdk")"
        fi
        if [ -d "$local_sdk" ]; then
            printf '%s\n' "$local_sdk"
            return 0
        fi
    fi

    if [ -d "$HOME/Android/Sdk" ]; then
        printf '%s\n' "$HOME/Android/Sdk"
        return 0
    fi

    return 1
}

latest_android_package_dir() {
    root="$1"
    package="$2"
    package_root="$root/$package"
    [ -d "$package_root" ] || return 1
    latest="$(
        for dir in "$package_root"/*; do
            [ -d "$dir" ] || continue
            version="${dir##*/}"
            printf '%s\n' "$version"
        done | grep -E '^[0-9]+(\.[0-9]+)*$' | sort -t . -k 1,1n -k 2,2n -k 3,3n -k 4,4n | tail -n 1
    )"
    [ -n "$latest" ] || return 1
    printf '%s/%s\n' "$package_root" "$latest"
}

android_sdkmanager_command() {
    root="$1"
    for candidate in \
        "$root/cmdline-tools/latest/bin/sdkmanager" \
        "$root/cmdline-tools/latest/bin/sdkmanager.bat" \
        "$root/tools/bin/sdkmanager" \
        "$root/tools/bin/sdkmanager.bat"
    do
        if [ -x "$candidate" ] || [ -f "$candidate" ]; then
            printf '%s\n' "$candidate"
            return 0
        fi
    done

    if [ -d "$root/cmdline-tools" ]; then
        for version in "$root/cmdline-tools"/*; do
            [ -d "$version" ] || continue
            [ "${version##*/}" = "latest" ] && continue
            for candidate in "$version/bin/sdkmanager" "$version/bin/sdkmanager.bat"; do
                if [ -x "$candidate" ] || [ -f "$candidate" ]; then
                    printf '%s\n' "$candidate"
                    return 0
                fi
            done
        done
    fi

    if command -v sdkmanager >/dev/null 2>&1; then
        command -v sdkmanager
        return 0
    fi

    return 1
}

latest_version_from_stdin() {
    sort -t . -k 1,1n -k 2,2n -k 3,3n -k 4,4n -k 5,5n | tail -n 1
}

latest_available_android_package_version() {
    root="$1"
    sdkmanager_cmd="$2"
    package="$3"
    output="$("$sdkmanager_cmd" "--sdk_root=$root" --list)" || return 1
    printf '%s\n' "$output" |
        sed -n "s/^[[:space:]]*$package;\\([0-9][0-9.]*\\)[[:space:]]*|.*/\\1/p" |
        latest_version_from_stdin
}

accept_android_sdk_licenses() {
    i=0
    while [ "$i" -lt 100 ]; do
        printf '%s\n' "y"
        i="$((i + 1))"
    done
}

install_android_sdk_package() {
    root="$1"
    sdkmanager_cmd="$2"
    package_id="$3"
    accept_android_sdk_licenses | "$sdkmanager_cmd" "--sdk_root=$root" --install "$package_id" >&2
}

record_android_package_update() {
    package="$1"
    installed_before="$2"
    available="$3"
    selected="$4"
    action="$5"

    case "$package" in
        ndk)
            ANDROID_NDK_INSTALLED_BEFORE="$installed_before"
            ANDROID_NDK_AVAILABLE_VERSION="$available"
            ANDROID_NDK_UPDATE_ACTION="$action"
            ;;
        cmake)
            ANDROID_CMAKE_INSTALLED_BEFORE="$installed_before"
            ANDROID_CMAKE_AVAILABLE_VERSION="$available"
            ANDROID_CMAKE_UPDATE_ACTION="$action"
            ;;
    esac
    export ANDROID_NDK_INSTALLED_BEFORE ANDROID_NDK_AVAILABLE_VERSION ANDROID_NDK_UPDATE_ACTION
    export ANDROID_CMAKE_INSTALLED_BEFORE ANDROID_CMAKE_AVAILABLE_VERSION ANDROID_CMAKE_UPDATE_ACTION
    printf '%s\n' "$selected" >/dev/null
}

ensure_latest_android_package_dir() {
    root="$1"
    package="$2"
    sdkmanager_cmd="${3:-}"

    installed_dir="$(latest_android_package_dir "$root" "$package" 2>/dev/null || true)"
    installed_before="${installed_dir##*/}"
    [ -n "$installed_dir" ] || installed_before=""
    available_version=""
    action="using-installed"

    if [ -n "$sdkmanager_cmd" ]; then
        available_version="$(latest_available_android_package_version "$root" "$sdkmanager_cmd" "$package")" || return 1
        if [ -n "$available_version" ]; then
            if [ -z "$installed_before" ]; then
                install_android_sdk_package "$root" "$sdkmanager_cmd" "$package;$available_version" || return 1
                action="installed-latest-available"
            else
                newest="$(printf '%s\n%s\n' "$installed_before" "$available_version" | latest_version_from_stdin)"
                if [ "$newest" = "$available_version" ] && [ "$available_version" != "$installed_before" ]; then
                    install_android_sdk_package "$root" "$sdkmanager_cmd" "$package;$available_version" || return 1
                    action="installed-latest-available"
                else
                    action="already-latest-available"
                fi
            fi
        else
            action="available-version-not-listed"
        fi
    elif [ -z "$installed_dir" ]; then
        printf '%s\n' "No installed Android SDK package was found under $root/$package, and sdkmanager was not found." >&2
        return 1
    fi

    selected_dir="$(latest_android_package_dir "$root" "$package")" || return 1
    record_android_package_update "$package" "$installed_before" "$available_version" "${selected_dir##*/}" "$action"
    printf '%s\n' "$selected_dir"
}

set_android_sdk_toolchain_environment() {
    sdk_root="$(android_sdk_root)" || {
        printf '%s\n' "Android SDK root was not found. Install command-line tools or set ANDROID_SDK_ROOT." >&2
        return 1
    }

    sdkmanager_cmd="$(android_sdkmanager_command "$sdk_root" || true)"

    ndk_dir="$(ensure_latest_android_package_dir "$sdk_root" ndk "$sdkmanager_cmd")" || return 1
    cmake_dir="$(ensure_latest_android_package_dir "$sdk_root" cmake "$sdkmanager_cmd")" || return 1

    cmake_command="$cmake_dir/bin/cmake"
    [ -x "$cmake_command" ] || {
        printf '%s\n' "Android SDK CMake executable not found: $cmake_command" >&2
        return 1
    }

    export ANDROID_HOME="$sdk_root"
    export ANDROID_SDK_ROOT="$sdk_root"
    export ANDROID_NDK_HOME="$ndk_dir"
    export ANDROID_NDK_ROOT="$ndk_dir"
    export ANDROID_CMAKE_COMMAND="$cmake_command"
    export ANDROID_NDK_VERSION="${ndk_dir##*/}"
    export ANDROID_CMAKE_VERSION="${cmake_dir##*/}"
    export ANDROID_SDKMANAGER_COMMAND="$sdkmanager_cmd"
}
