#!/bin/bash

. "$(dirname "$0")/scripts/shini.sh"

print_help() {
    shini_parse "config.ini"
    cat << END
Usage: ./configure [--option] ...

options:
  --prefix=PREFIX           (DEFAULT: $PREFIX)
  --incdir=INSTALL_INCDIR   (DEFAULT: $PREFIX/include/hv)
  --libdir=INSTALL_LIBDIR   (DEFAULT: $PREFIX/lib)

  --with-MODULE
  --without-MODULE
  --enable-FEATURE
  --disable-FEATURE

modules:
  --with-protocol       compile protocol module?        (DEFAULT: $WITH_PROTOCOL)
  --with-evpp           compile evpp module?            (DEFAULT: $WITH_EVPP)
  --with-http           compile http module?            (DEFAULT: $WITH_HTTP)
  --with-http-client    compile http client module?     (DEFAULT: $WITH_HTTP_CLIENT)
  --with-http-server    compile http server module?     (DEFAULT: $WITH_HTTP_SERVER)
  --with-mqtt           compile mqtt module?            (DEFAULT: $WITH_MQTT)

features:
  --enable-uds          enable Unix Domain Socket?      (DEFAULT: $ENABLE_UDS)
  --enable-windump      enable Windows coredump?        (DEFAULT: $ENABLE_WINDUMP)

dependencies:
  --with-curl           compile with curl?              (DEFAULT: $WITH_CURL)
  --with-nghttp2        compile with nghttp2?           (DEFAULT: $WITH_NGHTTP2)
  --with-openssl        compile with openssl?           (DEFAULT: $WITH_OPENSSL)
  --with-gnutls         compile with gnutls?            (DEFAULT: $WITH_GNUTLS)
  --with-mbedtls        compile with mbedtls?           (DEFAULT: $WITH_MBEDTLS)

rudp:
  --with-kcp            compile with kcp?               (DEFAULT: $WITH_KCP)

END
}

mkdir tmp 2>/dev/null
while [ -n "$1" ]
do
    opt="$1"
    KEY=""
    VAL=yes
    case $opt in
        --help)
            print_help
            exit 0
            ;;
        --prefix=*)
            KEY="PREFIX"
            VAL=${opt:9}
            ;;
        --incdir=*)
            KEY="INSTALL_INCDIR"
            VAL=${opt:9}
            ;;
        --libdir=*)
            KEY="INSTALL_LIBDIR"
            VAL=${opt:9}
            ;;
        --with-*)
            KEY="WITH_${opt:7}"
            ;;
        --without-*)
            KEY="WITH_${opt:10}"
            VAL=no
            ;;
        --enable-*)
            KEY="ENABLE_${opt:9}"
            ;;
        --disable-*)
            KEY="ENABLE_${opt:10}"
            VAL=no
            ;;
        *)
            print_help
            exit 255
            ;;
    esac

    if [ -n $KEY ]; then
        FEATURE=$(echo "$KEY" | tr "a-z-" "A-Z_")
        if [ ! -f tmp/config.mk ]; then
            cp config.ini tmp/config.mk
        fi
        shini_write "tmp/config.mk" "" "$FEATURE" "$VAL"
    fi

    shift 1
done

# config.mk
echo "[config.mk]"
if [ -f tmp/config.mk ]; then
    mv tmp/config.mk config.mk
    shini_write "config.mk" "" "CONFIG_DATE" "$(date +%Y%m%d)"
fi
cat config.mk
echo ""

# Checks for compiler
echo -e "\nchecking for compiler..."
if [ $CROSS_COMPILE ]; then
    CC=${CROSS_COMPILE}gcc
    CXX=${CROSS_COMPILE}g++
fi

if [ ! $CC ]; then
    CC=gcc
    CXX=g++
fi
CC_VERSION=`$CC --version 2>&1 | head -n 1`

echo "CC  = $CC"
echo "CXX = $CXX"
echo "$CC_VERSION"

# Checks for os
echo -e "\nchecking for os..."
HOST_OS=`uname -s`
HOST_ARCH=`uname -m`
TARGET_PLATFORM=`$CC -v 2>&1 | grep Target | sed 's/Target: //'`
TARGET_ARCH=`echo $TARGET_PLATFORM | awk -F'-' '{print $1}'`

case $TARGET_PLATFORM in
    *mingw*) TARGET_OS=Windows ;;
    *android*) TARGET_OS=Android ;;
    *darwin*) TARGET_OS=Darwin ;;
    *) TARGET_OS=Linux ;;
esac

echo "HOST_OS         = $HOST_OS"
echo "HOST_ARCH       = $HOST_ARCH"
echo "TARGET_PLATFORM = $TARGET_PLATFORM"
echo "TARGET_OS       = $TARGET_OS"
echo "TARGET_ARCH     = $TARGET_ARCH"

# hconfig.h
echo -e "\n>> hconfig.h"
confile=hconfig.h
cat << END > $confile
#ifndef HV_CONFIG_H_
#define HV_CONFIG_H_

END

write_define() {
cat << END >> hconfig.h
#ifndef $macro
#define $macro $value
#endif

END
}

CheckHeaderExists() {
rm tmp/check 2>/dev/null
cat << END > tmp/check.c
#include <$header>

int main() {
    return 0;
}

END
$CC -o tmp/check tmp/check.c 2>/dev/null
if [ -x tmp/check ]; then
    value=1
else
    value=0
fi
}

CheckSymbolExists() {
CheckHeaderExists
if [ $value -eq 0 ]; then
    return;
fi
rm tmp/check 2>/dev/null
cat << END > tmp/check.c
#include <$header>

int $function(void** pp) {return 0;}
int main() {
    void* p;
    return $function(&p);
}

END
$CC -o tmp/check tmp/check.c 2>/dev/null
if [ -x tmp/check ]; then
    value=0
else
    value=1
fi
}

check_header() {
echo -n "checking for $header... "
CheckHeaderExists
if [ $value -eq 0 ]; then
    echo "no"
else
    echo "yes"
fi
macro=HAVE_$(echo $header | tr a-z./ A-Z__)
write_define
}

check_function() {
echo -n "checking for $function... "
CheckSymbolExists
if [ $value -eq 0 ]; then
    echo "no"
else
    echo "yes"
fi
macro=HAVE_$(echo $function | tr a-z A-Z)
write_define
}

check_option() {
value=$(eval echo \$$option)
echo "checking for $option=$value"
if [ "$value" == "yes" ]; then
cat << END >> $confile
#define $option 1
END
else
cat << END >> $confile
/* #undef $option */
END
fi
}

# Checks for programs

# Checks for libraries

# Checks for header files
header=stdbool.h && check_header
header=stdint.h && check_header
header=stdatomic.h && check_header
header=sys/types.h && check_header
header=sys/stat.h && check_header
header=sys/time.h && check_header
header=fcntl.h && check_header
header=pthread.h && check_header
header=endian.h && check_header
header=sys/endian.h && check_header

# Checks for functions
function=gettid && header=unistd.h && check_function
function=strlcpy && header=string.h && check_function
function=strlcat && header=string.h && check_function
function=clock_gettime && header=time.h && check_function
function=gettimeofday && header=sys/time.h && check_function
function=pthread_spin_lock && header=pthread.h && check_function
function=pthread_mutex_timedlock && header=pthread.h && check_function
function=sem_timedwait && header=semaphore.h && check_function
function=pipe && header=unistd.h && check_function
function=socketpair && header=sys/socket.h && check_function
function=eventfd && header=sys/eventfd.h && check_function
function=setproctitle && header=unistd.h && check_function

# Checks for options
source config.mk 2>/dev/null
option=WITH_OPENSSL && check_option
option=WITH_GNUTLS && check_option
option=WITH_MBEDTLS && check_option
option=ENABLE_UDS && check_option
option=USE_MULTIMAP && check_option
option=WITH_KCP && check_option

# end confile
cat << END >> $confile

#endif // HV_CONFIG_H_
END

echo "configure done."