# SPDX-License-Identifier: GPL-3.0-or-later
# Copyright (c) 2026 0xKSor

set quiet := true

ROOT_BUILD_DIR := env_var_or_default("BUILD_DIR", justfile_directory() + "/../.build")
RUNTIME_BUILD_DIR := ROOT_BUILD_DIR + "/Runtime"
TEMP_DIR := env_var_or_default("TEMP_DIR", ROOT_BUILD_DIR + "/temp")

_default:
    just --list

@_build_cmake project_dir target_subpath:
    #!/usr/bin/env bash
    set -e
    PROJECT_DIR="{{ project_dir }}"
    TARGET_SUBPATH="{{ target_subpath }}"
    TEMP_DIR="{{ TEMP_DIR }}/Runtime/${TARGET_SUBPATH}"
    OUT_DIR="{{ RUNTIME_BUILD_DIR }}/${TARGET_SUBPATH}"

    echo "    🛠️  CMake build: ${TARGET_SUBPATH}"

    TOOLCHAIN_FILE="{{ justfile_directory() }}/Common/aarch64.cmake"
    TOOLCHAIN=""
    if [ -f "${TOOLCHAIN_FILE}" ]; then
        TOOLCHAIN="-DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_FILE}"
    else
        echo "    ⚠️  Warning: Toolchain file not found at ${TOOLCHAIN_FILE}"
    fi

    if ! OUT=$(cmake -B "${TEMP_DIR}" -S "${PROJECT_DIR}" -DCMAKE_BUILD_TYPE=Release ${TOOLCHAIN} -G Ninja 2>&1); then
        echo "$OUT"
        exit 1
    fi

    if ! OUT=$(cmake --build "${TEMP_DIR}" 2>&1); then
        echo "$OUT"
        exit 1
    fi

    mkdir -p "${OUT_DIR}"
    # Copy everything from build dir except CMake junk
    rsync -a --exclude='CMakeFiles' --exclude='CMakeCache.txt' --exclude='*.ninja*' --exclude='.ninja*' \
        "${TEMP_DIR}"/ "${OUT_DIR}"/ 2>/dev/null || \
        cp -R "${TEMP_DIR}"/* "${OUT_DIR}"/ 2>/dev/null || true

    echo "    ✅ CMake done: ${TARGET_SUBPATH}"

@_build_swiftpm project_dir target_subpath:
    #!/usr/bin/env bash
    set -e
    PROJECT_DIR="{{ project_dir }}"
    TARGET_SUBPATH="{{ target_subpath }}"
    TEMP_DIR="{{ TEMP_DIR }}/Runtime/${TARGET_SUBPATH}"
    OUT_DIR="{{ RUNTIME_BUILD_DIR }}/${TARGET_SUBPATH}"

    echo "    🛠️  SwiftPM build: ${TARGET_SUBPATH}"

    cd "${PROJECT_DIR}"

    if ! OUT=$(swift build -c release --build-path "${TEMP_DIR}" 2>&1); then
        echo "$OUT"
        exit 1
    fi

    mkdir -p "${OUT_DIR}"
    if [ -d "${TEMP_DIR}/release" ]; then
        rsync -a "${TEMP_DIR}/release"/ "${OUT_DIR}"/ 2>/dev/null || \
            cp -R "${TEMP_DIR}/release"/* "${OUT_DIR}"/ 2>/dev/null || true
    elif [ -d "${TEMP_DIR}/Release" ]; then
        rsync -a "${TEMP_DIR}/Release"/ "${OUT_DIR}"/ 2>/dev/null || \
            cp -R "${TEMP_DIR}/Release"/* "${OUT_DIR}"/ 2>/dev/null || true
    fi

    echo "    ✅ SwiftPM done: ${TARGET_SUBPATH}"

@_discover_and_build category:
    #!/usr/bin/env bash
    set -e
    CATEGORY="{{ category }}"
    RUNTIME_DIR="{{ justfile_directory() }}"
    SRC_DIR="${RUNTIME_DIR}/${CATEGORY}"

    if [ ! -d "${SRC_DIR}" ]; then
        echo "  📁 ${CATEGORY}/ not found, skipping"
        exit 0
    fi

    shopt -s nullglob
    projects=("${SRC_DIR}"/*/)
    shopt -u nullglob

    if [ ${#projects[@]} -eq 0 ]; then
        echo "  📁 ${CATEGORY}/ is empty, skipping"
        exit 0
    fi

    # libksOS MUST be built first — everyone depends on it
    for dir in "${projects[@]}"; do
        name=$(basename "${dir}")
        if [ "${name}" = "libksOS" ]; then
            echo ""
            echo "  📦 ${CATEGORY}/${name}"
            just --quiet _build_cmake "${dir}" "${CATEGORY}/${name}"
            break
        fi
    done

    for dir in "${projects[@]}"; do
        name=$(basename "${dir}")
        if [ "${name}" = "libksOS" ]; then
            continue
        fi
        echo ""
        echo "  📦 ${CATEGORY}/${name}"

        if [ -f "${dir}/CMakeLists.txt" ]; then
            just --quiet _build_cmake "${dir}" "${CATEGORY}/${name}"
        elif [ -f "${dir}/Package.swift" ]; then
            just --quiet _build_swiftpm "${dir}" "${CATEGORY}/${name}"
        else
            echo "    ⚠️  Skipping ${CATEGORY}/${name}: no CMakeLists.txt or Package.swift found"
        fi
    done

@build:
    @echo "🛠️ Building Runtime..."
    @just --quiet clangd
    @mkdir -p {{ RUNTIME_BUILD_DIR }}/System
    @mkdir -p {{ RUNTIME_BUILD_DIR }}/Apps
    @just --quiet _discover_and_build System
    @just --quiet _discover_and_build Apps
    @echo ""
    @echo "✅ Runtime ready at: {{ RUNTIME_BUILD_DIR }}"

@clean:
    @rm -rf {{ TEMP_DIR }}/Runtime
    @rm -rf {{ RUNTIME_BUILD_DIR }}
    @echo "🧹 Runtime cleaned"

@clangd:
    #!/usr/bin/env bash
    set -e
    RUNTIME_DIR="{{ justfile_directory() }}"
    INCLUDE_DIR="${RUNTIME_DIR}/System/libksOS/Include"

    printf 'CompileFlags:\n  Add:\n    - -xc\n    - --target=aarch64-none-elf\n    - -ffreestanding\n    - -I%s\n' "${INCLUDE_DIR}" > "${RUNTIME_DIR}/.clangd"

    echo "✅ Generated ${RUNTIME_DIR}/.clangd"
