#!/usr/bin/env bash

#
# Configuration script to build the 2D_Engine for different platforms.
#
# Creates makefile configuration to build for target host.
#

#
# Project settings no matter current and target hosts
#

CONFIG_FILE="config.mk"
CACHE_DIR="cache"
LIB_DIR="lib"

#
# Main
#

set -e

exit_error_message()
{
    echo -e "\033[31merror\033[m: $1"
    exit 0
}

## Parse args
HOST="guess"
TARGET_HOST="guess"

for i in "$@"; do
    case $i in
      --target-host=*)
        TARGET_HOST="${i#*=}"
        shift
        ;;
      --current-host=*)
        HOST="${i#*=}"
        shift
        ;;
      --clean)
        CLEAN=1
        EXIT_AFTER_CLEAN=1
        shift
        ;;
      --reconfigure)
        CLEAN=1
        shift
        ;;
      -h|--help)
        echo "Usage : ./configure [OPTION]..."
        echo "Add submodules depending on target host platform and"
        echo "create makefile configuration to build for target host"
        echo
        echo -e "\033[1m  --target-host=\033[mHOST"
        echo -e "\tselect target host platform, default is \"guess\" and"
        echo -e "\twill try to configure for your current OS"
        echo -e "\033[1m  --current-host=\033[mHOST"
        echo -e "\tselect current host platform, default is \"guess\" and"
        echo -e "\twill try to detect your current OS"
        echo -e "\033[1m  --clean\033[m"
        echo -e "\tclean build, config, cache, etc, and exit"
        echo -e "\033[1m  --reconfigure\033[m"
        echo -e "\tcall clean, and configure"
        echo -e "\033[1m  -h, --help\033[m"
        echo -e "\tshow help and exit"
        exit 0
        ;;
      -*)
        exit_error_message "Unknown option $i"
        ;;
      *)
        ;;
    esac
done

## Clean
if [ -n "${CLEAN}" ]; then
    make clean-all
    rm -rf ${CONFIG_FILE} ${CACHE_DIR} ${LIB_DIR}
fi

if [ -n "${EXIT_AFTER_CLEAN}" ]; then
    exit 0
fi

## Deduce current and target hosts
if [ "${HOST}" = "guess" ]; then
    case "${OSTYPE}" in
      linux*)
        HOST="linux"
        ;;
      msys*|cygwin*)
        CURRENT_HOST="windows"
        ;;
#      darwin*)
#        CURRENT_HOST="macos"
#        ;;
    *)
        exit_error_message "Current detected os is unsuppoted to build from: ${OSTYPE}\nUse --help for more informations."
        ;;
    esac
fi

echo "Configuring for current host: ${HOST}"

# If target host is guess then configure for host
if [ "${TARGET_HOST}" = "guess" ]; then
    TARGET_HOST=${HOST}
fi

# Set host compiler and asset builder flags
case "${HOST}" in
  linux)
    HOST_CC=gcc
    ASSET_BUILDER_CFLAGS=(
        "--std=c17"
        "-O2"
    )
    ASSET_BUILDER_LDFLAGS=()
    ASSET_BUILDER_LIBS=(
        "libpng|1.6.48"
        "json-c|0.18"
        )
    ;;
  windows)
    HOST_CC="x86_64-w64-mingw32-gcc"
    HOST_AR="x86_64-w64-mingw32-ar"
    ASSET_BUILDER_CFLAGS="--std=c17 -O2 \$(shell x86_64-w64-mingw32-pkg-config --cflags libpng json-c)"
    ASSET_BUILDER_LDFLAGS="\$(shell x86_64-w64-mingw32-pkg-config --libs libpng json-c)"
    ;;
  *)
    exit_error_message "Compiling from ${HOST} is not supported yet."
    ;;
esac

# Set target host compiler, outputs extensions and flags
case "${TARGET_HOST}" in
  linux)
    echo "Configuring for target: ${TARGET_HOST}"

    case "${HOST}" in
      linux)
        TARGET_HOST_CC=gcc
        TARGET_HOST_AR=ar
        TARGET_HOST_CFLAGS=(
            "--std=c17" "-Os"
            "-DASSET_FILE_NAME=\\\"\$(notdir \$(ASSET_OUTPUT))\\\"" "-D_GNU_SOURCE=1"
        )
        TARGET_HOST_LDFLAGS=()
        OUTPUT_EXT=""
        LIB_OUTPUT_EXT=".a"
        ;;
      *)
        exit_error_message "Cross compiling from ${HOST} for ${TARGET_HOST} is not supported yet."
        ;;
    esac

    TARGET_HOST_LIBS=(
        "sdl3|3.2.10"
        "lua|5.4.7"
    )
    ;;

  windows)
    echo "Configuring for target: ${TARGET_HOST}"

    case "${CURRENT_HOST}" in
      windows)
        TARGET_HOST_CC="x86_64-w64-mingw32-gcc"
        TARGET_HOST_AR="x86_64-w64-mingw32-ar"
        TARGET_HOST_CFLAGS="--std=c17 -Os -DASSET_FILE_NAME=\\\"\$(notdir \$(ASSET_OUTPUT))\\\" -D_GNU_SOURCE=1 \$(shell x86_64-w64-mingw32-pkg-config --cflags sdl3 lua)"
        TARGET_HOST_LDFLAGS="\$(shell x86_64-w64-mingw32-pkg-config --libs sdl3 lua) -lm"
        TARGET_HOST_LIBCORE="libcore.dll"
        ;;

      *)
        print_error "Cross compiling from ${CURRENT_HOST} for ${TARGET_HOST} is not supported yet."
        ;;
    esac
    ;;

  fxcg50)
    echo "Configuring for target: ${TARGET_HOST}"

    case "${HOST}" in
      linux)
        TARGET_HOST_CC=sh-elf-gcc
        TARGET_HOST_AR=sh-elf-ar
        TARGET_HOST_CFLAGS=(
            "--std=c17" "-Os"
            "-DASSET_FILE_NAME=\\\"\$(notdir \$(ASSET_OUTPUT))\\\"" "-DFXCG50" "-DTARGET_FXCG50"
            "-mb" "-m4-nofpu"
            "-ffreestanding" "-nostdlib" "-fstrict-volatile-bitfields"
        )
        TARGET_HOST_LDFLAGS="-T fxcg50.ld"
        OUTPUT_EXT=""
        LIB_OUTPUT_EXT=".a"
        ;;
      *)
        exit_error_message "Cross compiling from ${HOST} for ${TARGET_HOST} is not supported yet."
        ;;
    esac
    ;;
  *)
    exit_error_message "Unsupported target host: ${TARGET_HOST}"
esac

#
# Checks
#

echo

echo "Checking host compiler \"${HOST_CC}\"."
if ${HOST_CC} --version &> /dev/null; then
    echo "  ${HOST_CC} OK."
else
    exit_error_message "Compiler not working."
fi

echo "Checking asset builder libs."
for LIB in ${ASSET_BUILDER_LIBS[@]}; do
    LIB_NAME="$(echo ${LIB} | cut -d "|" -f 1)"
    LIB_MIN_VERSION="$(echo ${LIB} | cut -d "|" -f 2)"

    if pkg-config --atleast-version "${LIB_MIN_VERSION}" "${LIB_NAME}"; then
        echo "  ${LIB_NAME} OK."
    else
        LIB_URL=$(echo $LIB | cut -d "|" -f 3)

        if [ "${LIB_URL}" = "" ]; then
            exit_error_message "Library ${LIB_NAME} version >= ${LIB_MIN_VERSION} was not found and no precompiled binaries are available."
        else
            LIB_DOWNLOAD_CHECKSUM=$(echo $LIB | cut -d "|" -f 4)
            LIB_DOWNLOAD_FILENAME="$(echo ${LIB_URL} | rev | cut -d "/" -f 1 | rev)"
            LIB_DOWNLOAD_PATH="${CACHE_DIR}/${TARGET_HOST}/${LIB_DOWNLOAD_FILENAME}"

            case "${LIB_DOWNLOAD_FILENAME}" in
            *.txz)
                LIB_FOLDER_NAME="${LIB_DOWNLOAD_FILENAME%.txz}"
                ;;
            *)
                exit_error_message "File ${LIB_DOWNLOAD_FILENAME} extension substitution is not supported."
            esac
            LIB_PATH="${LIB_DIR}/${TARGET_HOST}/${LIB_FOLDER_NAME}"

            echo "  ${LIB_NAME} version >= ${LIB_MIN_VERSION} was not found but precompiled binaries are available."

            if [ ! -f "${LIB_DOWNLOAD_PATH}" ]; then
                echo "    downloading from ${LIB_URL}."
                mkdir -p "$(dirname "${LIB_DOWNLOAD_PATH}")"
                wget -q -O"${LIB_DOWNLOAD_PATH}" "${LIB_URL}"
            fi

            if echo "${LIB_DOWNLOAD_CHECKSUM} ${LIB_DOWNLOAD_PATH}" | md5sum --check &> /dev/null; then
                echo "    ${LIB_DOWNLOAD_PATH} OK."
            else
                rm -rf "${LIB_DOWNLOAD_PATH}"
                exit_error_message "Failed to verify checksum of ${LIB_DOWNLOAD_PATH}."
            fi

            mkdir -p "${LIB_PATH}"
            tar -xf "${LIB_DOWNLOAD_PATH}" -C "${LIB_PATH}"
        fi
    fi
done

echo "Checking target host compiler \"${TARGET_HOST_CC}\"."
if ${TARGET_HOST_CC} --version &> /dev/null; then
    echo "  ${TARGET_HOST_CC} OK."
else
    exit_error_message "Compiler not working."
fi

echo "Checking target host archiver \"${TARGET_HOST_AR}\"."
if ${TARGET_HOST_AR} --version &> /dev/null; then
    echo "  ${TARGET_HOST_AR} OK."
else
    exit_error_message "Compiler not working."
fi

echo "Checking target host libs."
for LIB in ${TARGET_HOST_LIBS[@]}; do
    LIB_NAME="$(echo ${LIB} | cut -d "|" -f 1)"
    LIB_MIN_VERSION="$(echo ${LIB} | cut -d "|" -f 2)"

    if pkg-config --atleast-version "${LIB_MIN_VERSION}" "${LIB_NAME}"; then
        echo "  ${LIB_NAME} OK."
    else
        LIB_URL=$(echo $LIB | cut -d "|" -f 3)

        if [ "${LIB_URL}" = "" ]; then
            exit_error_message "Library ${LIB_NAME} version >= ${LIB_MIN_VERSION} was not found and no precompiled binaries are available."
        else
            LIB_DOWNLOAD_CHECKSUM=$(echo $LIB | cut -d "|" -f 4)
            LIB_DOWNLOAD_FILENAME="$(echo ${LIB_URL} | rev | cut -d "/" -f 1 | rev)"
            LIB_DOWNLOAD_PATH="${CACHE_DIR}/${TARGET_HOST}/${LIB_DOWNLOAD_FILENAME}"

            case "${LIB_DOWNLOAD_FILENAME}" in
            *.txz)
                LIB_FOLDER_NAME="${LIB_DOWNLOAD_FILENAME%.txz}"
                ;;
            *)
                exit_error_message "File ${LIB_DOWNLOAD_FILENAME} extension substitution is not supported."
            esac
            LIB_PATH="${LIB_DIR}/${TARGET_HOST}/${LIB_FOLDER_NAME}"

            echo "  ${LIB_NAME} version >= ${LIB_MIN_VERSION} was not found but precompiled binaries are available."

            if [ ! -f "${LIB_DOWNLOAD_PATH}" ]; then
                echo "    downloading from ${LIB_URL}."
                mkdir -p "$(dirname "${LIB_DOWNLOAD_PATH}")"
                wget -q -O"${LIB_DOWNLOAD_PATH}" "${LIB_URL}"
            fi

            if echo "${LIB_DOWNLOAD_CHECKSUM} ${LIB_DOWNLOAD_PATH}" | md5sum --check &> /dev/null; then
                echo "    ${LIB_DOWNLOAD_PATH} OK."
            else
                rm -rf "${LIB_DOWNLOAD_PATH}"
                exit_error_message "Failed to verify checksum of ${LIB_DOWNLOAD_PATH}."
            fi

            mkdir -p "${LIB_PATH}"
            tar -xf "${LIB_DOWNLOAD_PATH}" -C "${LIB_PATH}"
        fi
    fi
done

echo "Writing config file."
echo
echo "${CONFIG_FILE}:"
echo "\`\`\`"

tee "${CONFIG_FILE}" <<EOF
# This file was generated by the configure script.

TARGET_HOST = ${TARGET_HOST}
LIB_OUTPUT_EXT = ${LIB_OUTPUT_EXT}

TARGET_HOST_CC = ${TARGET_HOST_CC}
TARGET_HOST_AR = ${TARGET_HOST_AR}
TARGET_HOST_CFLAGS = ${TARGET_HOST_CFLAGS[@]}
TARGET_HOST_LDFLAGS = ${TARGET_HOST_LDFLAGS[@]}

HOST_CC = ${HOST_CC}

ASSET_BUILDER_CFLAGS = ${ASSET_BUILDER_CFLAGS[@]}
ASSET_BUILDER_LDFLAGS = ${ASSET_BUILDER_LDFLAGS[@]}
EOF

if [ "${CURRENT_HOST}" = "windows" ]; then
tee -a "${CONFIG_FILE}" <<EOF

# OS specific options
ECHO_OPTION = -e
EOF
fi

echo "\`\`\`"
