#!/usr/bin/env fish

set -g failures 0
set -g tmpdir ""

function log_ok
    printf 'PASS: %s\n' $argv[1]
end

function log_fail
    printf 'FAIL: %s\n' $argv[1] >&2
    set -g failures (math $failures + 1)
end

function find_tool
    set -l preferred $argv[1]
    set -e argv[1]

    if test -n "$preferred"
        if command -sq -- "$preferred"
            printf '%s\n' "$preferred"
            return 0
        end
    end

    for candidate in $argv
        if command -sq -- "$candidate"
            printf '%s\n' "$candidate"
            return 0
        end
    end

    return 1
end

function cleanup --on-event fish_exit
    if test -n "$tmpdir"
        and test -d "$tmpdir"
        rm -rf -- "$tmpdir"
    end
end

printf 'Linux by Intent host readiness check (fish)\n'

if command -sq sh
    if sh -c 'exit 0' >/dev/null 2>&1
        log_ok 'sh is available and executable'
    else
        log_fail 'sh is missing or cannot execute commands'
    end
else
    log_fail 'sh is missing or cannot execute commands'
end

for tool in git gzip awk cmake meson rustc cargo rsync clang ninja bmake
    if command -sq -- "$tool"
        log_ok "$tool is installed"
    else
        log_fail "$tool is missing"
    end
end

set -l yacc_cmd (find_tool "$YACC" yacc byacc 2>/dev/null)
if test -n "$yacc_cmd"
    log_ok "yacc-compatible parser generator found: $yacc_cmd"
else
    log_fail 'no yacc-compatible parser generator was found'
end

set -l cc_cmd (find_tool "$CC" cc clang gcc 2>/dev/null)
set -l cxx_cmd (find_tool "$CXX" c++ clang++ g++ 2>/dev/null)

if test -n "$cc_cmd"
    log_ok "C compiler found: $cc_cmd"
else
    log_fail 'no working C compiler command was found'
end

if test -n "$cxx_cmd"
    log_ok "C++ compiler found: $cxx_cmd"
else
    log_fail 'no working C++ compiler command was found'
end

if test -n "$cc_cmd"
    and test -n "$cxx_cmd"
    set tmpdir (mktemp -d 2>/dev/null)
    if test -z "$tmpdir"
        set tmpdir (mktemp -d -t linuxbook-ready)
    end

        printf '%s\n' \
                '#include <stdio.h>' \
                '' \
                'int main(void) {' \
                '  puts("c-ok");' \
                '  return 0;' \
                '}' > "$tmpdir/test.c"

    if "$cc_cmd" -o "$tmpdir/test-c" "$tmpdir/test.c" >/dev/null 2>&1
        if "$tmpdir/test-c" >/dev/null 2>&1
            log_ok 'C compilation and execution succeeded'
        else
            log_fail 'C compilation or execution failed'
        end
    else
        log_fail 'C compilation or execution failed'
    end

        printf '%s\n' \
                '#include <iostream>' \
                '' \
                'int main() {' \
                '  std::cout << "cpp-ok\\n";' \
                '  return 0;' \
                '}' > "$tmpdir/test.cpp"

    if "$cxx_cmd" -o "$tmpdir/test-cpp" "$tmpdir/test.cpp" >/dev/null 2>&1
        if "$tmpdir/test-cpp" >/dev/null 2>&1
            log_ok 'C++ compilation and execution succeeded'
        else
            log_fail 'C++ compilation or execution failed'
        end
    else
        log_fail 'C++ compilation or execution failed'
    end

        printf '%s\n' \
                'int readiness_value(void) {' \
                '  return 42;' \
                '}' > "$tmpdir/libcheck.c"

        printf '%s\n' \
                'int readiness_value(void);' \
                '' \
                'int main(void) {' \
                '  return readiness_value() == 42 ? 0 : 1;' \
                '}' > "$tmpdir/linkcheck.c"

    if "$cc_cmd" -c -o "$tmpdir/libcheck.o" "$tmpdir/libcheck.c" >/dev/null 2>&1
        and "$cc_cmd" -c -o "$tmpdir/linkcheck.o" "$tmpdir/linkcheck.c" >/dev/null 2>&1
        and "$cc_cmd" -o "$tmpdir/link-test" "$tmpdir/linkcheck.o" "$tmpdir/libcheck.o" >/dev/null 2>&1
        and "$tmpdir/link-test" >/dev/null 2>&1
        log_ok 'linking object files into an executable succeeded'
    else
        log_fail 'linking test failed'
    end
end

if test "$failures" -eq 0
    printf 'RESULT: system appears ready for the book\n'
    exit 0
end

printf 'RESULT: system is not ready for the book (%s failure(s))\n' "$failures" >&2
exit 1
