#!/usr/bin/env sh

#
# Argument Parsing
#

echo "Build Configuration"
echo "-------------------"

CFLAGS="-Wall -Wextra -pedantic -std=c89 -O3 -pipe -D_DEFAULT_SOURCE -Isrc/include"
LDFLAGS="-lm -pthread"

# Set default args for all platforms
SCRIPT_ARGS="--lib-rtstub=RtStub --prefix=/usr/local --enable-ld-extra --lib-name=Cytoplasm --lib-version=0.4.0 --static $@"

# Set platform specific args
case "$(uname)" in
    OpenBSD)
        SCRIPT_ARGS="--with-libressl $SCRIPT_ARGS"
        ;;
    *)
        SCRIPT_ARGS="--with-openssl $SCRIPT_ARGS"
        ;;
esac

echo "Processing options..."
echo "Ran with arguments: $SCRIPT_ARGS"

# Process all arguments
for arg in $SCRIPT_ARGS; do
    case "$arg" in
        --with-openssl)
            TLS_IMPL="OPENSSL"
            TLS_LIBS="-lcrypto -lssl"
            ;;
        --with-libressl)
            TLS_IMPL="LIBRESSL"
            TLS_LIBS="-ltls -lcrypto -lssl"
            ;;
        --disable-tls)
            TLS_LIBS=""
            ;;
        --prefix=*)
            PREFIX=$(echo "$arg" | cut -d '=' -f 2-)
            ;;
        --enable-ld-extra)
            LD_EXTRA="-flto -fdata-sections -ffunction-sections -s -Wl,-gc-sections"
            ;;
        --disable-ld-extra)
            LD_EXTRA=""
            ;;
        --lib-name=*)
            LIB_NAME=$(echo "$arg" | cut -d '=' -f 2-)
            ;;
        --lib-version=*)
            LIB_VERSION=$(echo "$arg" | cut -d '=' -f 2-)
            ;;
        --enable-debug)
            DEBUG="-O0 -g"
            echo "Notice: --enable-debug implies --disable-ld-extra and --no-static."
            echo "You must explicitly provide --enable-ld-extra and/or --static after"
            echo "specifying --enable-debug if you wish to enable these features in debug mode."
            LD_EXTRA=""
            STATIC=""
            ;;
        --disable-debug)
            DEBUG=""
            ;;
        --lib-rtstub=*)
            STUB=$(echo "$arg" | cut -d '=' -f 2-)
            ;;
        --static)
            STATIC="-static -Wl,-static"
            ;;
        --no-static)
            STATIC=""
            ;;
        *)
            echo "Invalid argument: $1"
            exit 1
            ;;
    esac
done

if [ -n "$TLS_IMPL" ]; then
    CFLAGS="${CFLAGS} -DTLS_IMPL=${TLS_IMPL}"
    LDFLAGS="${LDFLAGS} ${TLS_LIBS}"
fi

CFLAGS="${CFLAGS} '-DLIB_NAME=\"${LIB_NAME}\"' '-DLIB_VERSION=\"${LIB_VERSION}\"' ${DEBUG}"
LDFLAGS="${LDFLAGS} ${LD_EXTRA}"

#
# Makefile generation
#

echo "Generating Makefile..."

find_objs() {
    obj_prefix="$1"
    find src -name '*.c' | while IFS= read -r src; do
        src=$(echo "$src" | cut -d '/' -f 2-)
        obj=$(echo "$src" | sed -e 's/\.c$/.o/')
        if [ "$(basename ${obj} .o)" != "${STUB}" ]; then
            printf "${obj_prefix}${obj} "
        fi
    done
}

OBJS=$(find_objs "build/")
TAB=$(printf '\t')

find_tools() {
    tools_prefix="$1"
    find tools -name '*.c' | while IFS= read -r src; do
        src=$(echo "$src" | cut -d '/' -f 2-)
        bin=$(basename "$src" .c)
            printf "${tools_prefix}${bin} "
    done
}

find_docs() {
    prefix="$1"
    find src/include -name '*.h' | while IFS= read -r src; do
        src=$(echo "$src" | cut -d '/' -f 3-)
        doc=$(echo "$src" | sed -e 's/\.h$/.3/')
		printf "${prefix}${doc} "
    done
}

cat << EOF > Makefile
.POSIX:

# Generated by '$0' on $(date).
# This file should generally not be manually edited.

PREFIX = ${PREFIX}
CFLAGS = ${CFLAGS}
LDFLAGS = ${LDFLAGS}

all: ${LIB_NAME} docs tools

docs: $(find_docs "out/man/man3/Cytoplasm-")

tools: $(find_tools "out/bin/")

format:
${TAB}find . -name '*.c' | while IFS= read -r src; do \\
${TAB}  if indent "\$\$src"; then \\
${TAB}    rm \$\$(basename "\$\$src").BAK; \\
${TAB}  fi \\
${TAB}done

license:
${TAB}find . -name '*.[ch]' | while IFS= read -r src; do \\
${TAB}  srcHeader=\$\$(grep -n -m 1 '^ \*/' "\$\$src" | cut -d ':' -f 1); \\
${TAB}  head -n\$\$srcHeader \$\$src | \\
${TAB}    diff -u -p - "LICENSE.txt" | \\
${TAB}    patch "\$\$src" | grep -v "^Hmm"; \\
${TAB}done

${LIB_NAME}: out/lib/${LIB_NAME}.o out/lib/lib${LIB_NAME}.a out/lib/lib${LIB_NAME}.so

clean:
${TAB}rm -r build out

out/lib/${LIB_NAME}.o: build/${STUB}.o
${TAB}@mkdir -p out/lib
${TAB}cp build/${STUB}.o out/lib/${LIB_NAME}.o

out/lib/lib${LIB_NAME}.a: ${OBJS}
${TAB}@mkdir -p out/lib
${TAB}\$(AR) rcs out/lib/lib${LIB_NAME}.a ${OBJS}

out/lib/lib${LIB_NAME}.so: ${OBJS}
${TAB}@mkdir -p out/lib
${TAB}\$(CC) -shared -o out/lib/lib${LIB_NAME}.so ${OBJS} ${LDFLAGS}

EOF

find src -name '*.c' | while IFS= read -r src; do
    src=$(echo "$src" | cut -d '/' -f 2-)
    obj=$(echo "$src" | sed -e 's/\.c$/.o/')

    src="src/${src}"
    obj="build/${obj}"
    cc -Isrc/include -MM -MT "${obj}" "${src}" >> Makefile
    echo "${TAB}@mkdir -p $(dirname ${obj})" >> Makefile
    echo "${TAB}\$(CC) \$(CFLAGS) -fPIC -c -o \"${obj}\" \"${src}\"" >> Makefile
done

find tools -name '*.c' | while IFS= read -r src; do
    out="out/bin/$(basename "$src" .c)"

    echo "${out}: out/lib/lib${LIB_NAME}.a out/lib/lib${LIB_NAME}.so out/lib/${LIB_NAME}.o ${src}" >> Makefile
    echo "${TAB}@mkdir -p out/bin" >> Makefile
    echo "${TAB}\$(CC) \$(CFLAGS) -o \"${out}\" \"${src}\" out/lib/${LIB_NAME}.o -Lout/lib \$(LDFLAGS) -l${LIB_NAME} ${STATIC}" >> Makefile
done

find src/include -name '*.h' | while IFS= read -r header; do
    src=$(echo "$header" | cut -d '/' -f 2-)
    out=$(echo "$header" | cut -d '/' -f 3- | sed -e 's/\.h$/.3/')

	echo "out/man/man3/Cytoplasm-${out}: out/bin/hdoc src/${src}" >> Makefile
	echo "${TAB}@mkdir -p out/man/man3" >> Makefile
	echo "${TAB}out/bin/hdoc -D \"Os=${LIB_NAME}\" -i \"src/${src}\" -o \"out/man/man3/Cytoplasm-${out}\"" >> Makefile
done

echo "Done. Run 'make' to build ${LIB_NAME}."