#!/bin/bash
# This version is heavily based on the work of mz-fuzzy (https://github.com/mz-fuzzy)
# adapted to work with MySensors project.
# Original work: https://github.com/TMRh20/RF24/blob/master/configure

function help {
cat <<EOF	
configure script for MySensors gateway.
Options:

Help:
    -h, --help                  print this message

SPI driver options:
    --spi-driver=[BCM|SPIDEV]
    --spi-spidev-device=<DEVICE>
                                Device path. [/dev/spidev0.0]

Building options:
    --soc=[BCM2711|BCM2835|BCM2836|BCM2837|AM33XX|A10|A13|A20|H3|RK3399]
                                SoC type to be used. [configure autodetected]
    --cpu-flags=<CPUFLAGS>      CPU defining/optimizing flags to be used. [configure autodetected]
    --extra-cflags=<CFLAGS>     Extra C flags passed to C compilation. []
    --extra-cxxflags=<CXXFLAGS> Extra C++ flags passed to C++ compilation. []
                                Example: --extra-cxxflags="-DMY_RX_MESSAGE_BUFFER_SIZE=\(32\) -DMY_RF24_DATARATE=\(RF24_2MBPS\)"
    --extra-ldflags=<LDFLAGS>   Extra C flags passed to linking. []
    --c_compiler=<CC>           C compiler. [arm-linux-gnueabihf-gcc][gcc]
    --cxx_compiler=<CXX>        C++ compiler. [arm-linux-gnueabihf-g++][g++]
    --build-dir=<DIR>           Compiler directory to store object files. [build]
    --bin-dir=<DIR>             Compiler directory to store binary files. [bin]
    --arduino-lib-dir=<DIR>     Arduino library directory.
    --no-clean                  Don't clean previous build artifacts.

Installation options:
    --prefix=<PREFIX>           Installation prefix path. [/usr/local]
    --gateway-dir=<DIR>         Gateway files installation directory. [PREFIX/bin]

MySensors options:
    --my-debug=[enable|disable] Enables or disables MySensors core debugging. [enable]
    --my-config-file=<FILE>     Config file path. [/etc/mysensors.conf]
    --my-gateway=[none|ethernet|serial|mqtt]
                                Set the protocol used to communicate with the controller. [ethernet]
    --my-node-id=<ID>           Disable gateway feature and run as a node with the specified id.
    --my-controller-url-address=<URL>
                                Controller or MQTT broker url.
    --my-controller-ip-address=<IP>
                                Controller or MQTT broker ip.
    --my-port=<PORT>            The port to keep open on gateway mode.
                                If gateway is set to mqtt, it sets the broker port.
    --my-serial-port=<PORT>     Serial port.
    --my-serial-baudrate=<BAUD> Serial baud rate. [115200]
    --my-serial-is-pty          Set the serial port to be a pseudo terminal. Use this if you want
                                to connect to a controller running on the same device.
                                You also need to set the symlink name for the PTY device with
                                the --my-serial-port option.
    --my-serial-groupname=<GROUP>
                                Grant access to the specified system group for the serial device.
    --my-mqtt-client-id=<ID>    MQTT client id.
    --my-mqtt-user=<UID>        MQTT user id.
    --my-mqtt-password=<PASS>   MQTT password.
    --my-mqtt-publish-topic-prefix=<PREFIX>
                                MQTT publish topic prefix.
    --my-mqtt-subscribe-topic-prefix=<PREFIX>
                                MQTT subscribe topic prefix.
    --my-transport=[none|rf24|rfm69|rfm95|rs485]
                                Set the transport to be used to communicate with other nodes. [rf24]
    --my-rf24-channel=<0-125>   RF channel for the sensor net. [76]
    --my-rf24-pa-level=[RF24_PA_MAX|RF24_PA_HIGH|RF24_PA_LOW|RF24_PA_MIN]
                                RF24 PA level. [RF24_PA_MAX]
    --my-rf24-ce-pin=<PIN>      Pin number to use for rf24 Chip-Enable.
    --my-rf24-cs-pin=<PIN>      Pin number to use for rf24 Chip-Select.
    --my-rf24-irq-pin=<PIN>     Pin number connected to nRF24L01P IRQ pin.
    --my-rf24-encryption-enabled
                                Enables RF24 encryption.
                                All nodes and gateway must have this enabled, and all must be
                                personalized with the same AES key.
    --my-rx-message-buffer-size=<SIZE>
                                Buffer size for incoming messages when using rf24 interrupts. [20]
    --my-rfm69-frequency=[315|433|865|868|915]
                                RFM69 Module Frequency. [868]
    --my-is-rfm69hw             Enable high-powered rfm69hw.
    --my-rfm69-irq-pin=<PIN>    Pin number connected to RFM69 IRQ pin.
    --my-rfm69-cs-pin=<PIN>     Pin number to use for RFM69 Chip-Select.
    --my-rfm69-encryption-enabled
                                Enables RFM69 encryption.
                                All nodes and gateway must have this enabled, and all must be
                                personalized with the same AES key.
    --my-rfm95-frequency=[169|315|434|868|915]
                                RFM95 Module Frequency. [868]
    --my-rfm95-irq-pin=<PIN>    Pin number connected to RFM95 IRQ pin.
    --my-rfm95-cs-pin=<PIN>     Pin number to use for RFM95 Chip-Select.
    --my-rfm95-encryption-enabled
                                Enables RFM95 encryption.
                                All nodes and gateway must have this enabled, and all must be
                                personalized with the same AES key.
    --my-rs485-serial-port=<PORT>
                                RS485 serial port. You must provide a port.
    --my-rs485-baudrate=<BAUD>  RS485 baudrate. [9600]
    --my-rs485-de-pin=<PIN>     Pin number connected to RS485 driver enable pin.
    --my-rs485-max-msg-length=<LENGTH>
                                The maximum message length used for RS485. [40]
    --my-leds-err-pin=<PIN>     Error LED pin.
    --my-leds-rx-pin=<PIN>      Receive LED pin.
    --my-leds-tx-pin=<PIN>      Transmit LED pin.
    --my-leds-blinking-inverse  Inverse the blinking feature.
    --my-signing=[none|software|password]
                                Message signing. [none]
    --my-signing-debug          Enable signing related debug.
    --my-signing-request-signatures
                                Enable signature request from nodes that in turn requested
                                gateway signature.
    --my-signing-weak_security  Enable this to permit downgrade of security preferences and
                                relaxed gateway signing requirements.
    --my-signing-whitelist=<WHITELIST>
                                If you want to use a whitelist, provide it here, make sure to avoid
                                spaces in the <whitelist> expression.
    --my-signing-verification-timeout-ms=<TIMEOUT>
                                Signing timeout. [5000]
    --my-security-password=<PASSWORD>
                                If you are using password for signing/encryption, set your password here.
EOF
}

# Colors
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[1;33m'
LIGHT_BLUE='\033[1;34m'
NO_COLOR='\033[0m'

OK="${GREEN}[OK]${NO_COLOR}"
ERROR="${RED}[ERROR]${NO_COLOR}"
FAILED="${YELLOW}[FAILED]${NO_COLOR}"
SECTION="${LIGHT_BLUE}[SECTION]${NO_COLOR}"

function die {
    printf "${RED}${ERROR} $1${NO_COLOR}\n"
    exit $2
}

function detect_rpi_revision {
    # get PI Revision from cpuinfo
    local pirev=$(eval "cat /proc/cpuinfo 2>/dev/null | grep Revision | cut -f 2 -d ':' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$$//'")
    echo ${pirev}
}

function detect_machine {
    local cpu=$(eval "uname -m 2>/dev/null")
    local machine=$(eval "cat /sys/firmware/devicetree/base/model 2>/dev/null |tr -d '\0'")
    local hardware=$(eval "grep sunxi_platform /sys/class/sunxi_info/sys_info 2>/dev/null | sed 's/^.*: \(.*\)$/\1/'")
    if [ -z "$hardware" ]; then
        local hardware=$(eval "grep Hardware /proc/cpuinfo 2>/dev/null | sed 's/^.*: \(.*\)$/\1/'")
    fi
    local soc="unknown"
    local tp="unknown"

    if [ -z "$cpu" ]; then
        cpu="unknown"
    fi

    case $hardware in
    BCM*)
        if [[ $machine == "Raspberry"* ]]; then
            # Calculation done by joolswills(https://github.com/joolswills) for the RetroPie-Setup project
            # and based on information from https://github.com/AndrewFromMelbourne/raspberry_pi_revision
            local rev="0x$(sed -n '/^Revision/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo)"
            # if bit 23 is not set, we are on a rpi1 (bit 23 means the revision is a bitfield)
            if [[ $((($rev >> 23) & 1)) -eq 0 ]]; then
                soc="BCM2835"
                tp="rpi1"
            else
                # if bit 23 is set, get the cpu from bits 12-15
                case "$((($rev >> 12) & 15))" in
                    0)
                        soc="BCM2835"
                        tp="rpi1"
                        ;;
                    1)
                        soc="BCM2836"
                        tp="rpi2"
                        ;;
                    2)
                        soc="BCM2837"
                        tp="rpi3"
                        ;;
                    3)
                        soc="BCM2711"
                        tp="rpi4"
                        ;;                        
                esac
            fi
        elif [[ $hardware == "BCM2708"* ]]; then
            soc="BCM2835"
        elif [[ $hardware == "BCM2709"* ]]; then
            soc="BCM2836"
        elif [[ $hardware == "BCM2710"* ]]; then
            soc="BCM2837"
        fi
        ;;
    *sun4i*|*Sun4iw1p1*)
        soc="A10"
        ;;
    *sun5i*|*Sun4iw2p1*)
        soc="A13"
        ;;
    *Sun4iw2p2*)
        soc="A12"
        ;;
    *Sun4iw2p3*)
        soc="A10s"
        ;;
    *sun6i*|*Sun8iw1p1*)
        soc="A31"
        ;;
    *Sun8iw1p2*)
        soc="A31s"
        ;;
    *sun7i*|*Sun8iw2p1*)
        soc="A20"
        if [[ $machine == "Banana Pi"* ]]; then
            tp="BananaPi"
        elif [[ $machine == "Banana Pro"* ]]; then
            tp="BananaPro"
        fi
        ;;
    *sun8i*|*Sun8iw7p1*)
        soc="H3"
        ;;
    *Sun8iw3p1*)
        soc="A23"
        ;;
    *Sun8iw5p1*)
        soc="A33"
        ;;
    *Sun8iw6p1*)
        soc="A83t"
        ;;
    *sun9i*|*Sun9iw1p1*)
        soc="A80"
        ;;
    *Sun9iw1p2*)
        soc="A80t"
        ;;
    *sun50i*|*Sun50iw1p1*)
        soc="A64"
        ;;
    'Generic AM33XX'*)
        soc="AM33XX"
        ;;
    *)
        if [[ $machine == *"ROCK Pi 4"* ]]; then
            soc="RK3399"
            tp="RockPi4"
        fi
    esac
    echo "${soc} ${tp} ${cpu}"
}

function gcc_cpu_flags {
    local soc=$1
    local cpu=$2
    case $soc in
    BCM2835)
        flags="-march=armv6zk -mtune=arm1176jzf-s -mfpu=vfp -mfloat-abi=hard"
        ;;
    BCM2836)
        flags="-march=armv7-a -mtune=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard"
        ;;
    BCM2837)
        if [[ ${cpu} == "aarch64" ]]; then
            flags="-march=armv8-a+crc -mtune=cortex-a53"
        else
            flags="-march=armv8-a+crc -mtune=cortex-a53 -mfpu=neon-fp-armv8 -mfloat-abi=hard"
        fi
        ;;
    BCM2711)
        if [[ ${cpu} == "aarch64" ]]; then
            flags="-march=armv8-a+crc -mtune=cortex-a72"
        else
            flags="-march=armv8-a+crc -mtune=cortex-a72 -mfpu=neon-fp-armv8 -mfloat-abi=hard"
        fi
        ;;
    AM33XX)
        flags="-march=armv7-a -mtune=cortex-a8 -mfpu=neon -mfloat-abi=hard"
        ;;
    A10)
        flags="-march=armv7-a -mtune=cortex-a8 -mfpu=neon -mfloat-abi=hard"
        ;;
    A13)
        flags="-march=armv7-a -mtune=cortex-a8 -mfpu=neon -mfloat-abi=hard"
        ;;
    A20)
        flags="-march=armv7-a -mtune=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard"
        ;;
    H3)
        flags="-march=armv7-a -mtune=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard"
        ;;
    RK3399)
        flags="-march=armv8-a+crc+crypto -mtune=cortex-a72.cortex-a53 -mfix-cortex-a53-835769 -mfix-cortex-a53-843419"
        ;;
    *)
        flags=""
    esac
    echo ${flags}
}

ROCKPI4_PIN_MAP=(  
      1   2  71   4  72   6  75 148   9 147
    146 131 150  14 149 154  17 156  40  20
     39 157  41  42  25  26  64  65  74  30
     73 112  76  24 133 132 158 134  39 135 )

# Default values
debug=enable
gateway_type=ethernet
transport_type=rf24
signing=none
signing_request_signatures=false
encryption=false

params="SOC CFLAGS CXXFLAGS CPPFLAGS LDFLAGS PREFIX CC CXX ARDUINO_LIB_DIR BUILDDIR BINDIR GATEWAY_DIR INIT_SYSTEM SPI_DRIVER TYPE"

for opt do
    if [ "$opt" = "-h" ] || [ "$opt" = "--help" ]; then
        help
        exit 0
    fi
    optarg="${opt#*=}"
    case "$opt" in
    --spi-driver=*)
        SPI_DRIVER="$optarg"
        ;;
    --spi-spidev-device=*)
        CPPFLAGS="-DSPI_SPIDEV_DEVICE=\\\"${optarg}\\\" $CPPFLAGS"
        ;;
    --soc=*)
        SOC="$optarg"
        ;;
    --platform-type=*)
        PT="$optarg"
        ;;
    --cpu-flags=*)
        CPUFLAGS="$optarg"
        ;;
    --extra-cflags=*)
        CFLAGS="$optarg"
        ;;
    --extra-cxxflags=*)
        CXXFLAGS="$optarg $CXXFLAGS"
        ;;
    --extra-ldflags=*)
        LDFLAGS="$optarg"
        ;;
    --c_compiler=*)
        CC="$optarg"
        ;;
    --cxx_compiler=*)
        CXX="$optarg"
        ;;
    --arduino-lib-dir=*)
        ARDUINO_LIB_DIR=$optarg
        ;;
    --build-dir=*)
        BUILDDIR="$optarg"
        ;;
    --bin-dir=*)
        BINDIR="$optarg"
        ;;
    --no-clean*)
        NO_CLEAN="1"
        ;;
    --prefix=*)
        PREFIX="$optarg"
        ;;
    --exec-prefix=*)
        PREFIX="$optarg"
        ;;
    --no_init_system*)
        NO_INIT="1"
        ;;
    --gateway-dir=*)
        GATEWAY_DIR="$optarg"
        ;;
    --my-debug=*)
        debug=${optarg}
        ;;
    --my-gateway=*)
        gateway_type=${optarg}
        ;;
    --my-node-id=*)
        gateway_type="none";
        CPPFLAGS="-DMY_NODE_ID=${optarg} $CPPFLAGS"
        ;;
    --my-config-file=*)
        CPPFLAGS="-DMY_LINUX_CONFIG_FILE=\\\"${optarg}\\\" $CPPFLAGS"
        ;;
    --my-transport=*)
        transport_type=${optarg}
        ;;
    --my-serial-port=*)
        CPPFLAGS="-DMY_LINUX_SERIAL_PORT=\\\"${optarg}\\\" $CPPFLAGS"
        ;;
    --my-serial-baudrate=*)
        CPPFLAGS="-DMY_BAUD_RATE=${optarg} $CPPFLAGS"
        ;;
    --my-serial-is-pty*)
        CPPFLAGS="-DMY_LINUX_SERIAL_IS_PTY $CPPFLAGS"
        ;;
    --my-serial-pty=*)
        echo "Warning: --my-serial-pty is deprecated, please use --my-serial-port"
        CPPFLAGS="-DMY_LINUX_SERIAL_PORT=\\\"${optarg}\\\" $CPPFLAGS"
        ;;
    --my-serial-groupname=*)
        CPPFLAGS="-DMY_LINUX_SERIAL_GROUPNAME=\\\"${optarg}\\\" $CPPFLAGS"
        ;;
    --my-rf24-channel=*)
        CPPFLAGS="-DMY_RF24_CHANNEL=${optarg} $CPPFLAGS"
        ;;
    --my-rf24-pa-level=*)
        CPPFLAGS="-DMY_RF24_PA_LEVEL=${optarg} $CPPFLAGS"
        ;;
    --my-rf24-ce-pin=*)
        CPPFLAGS="-DMY_RF24_CE_PIN=${optarg} $CPPFLAGS"
        ;;
    --my-rf24-cs-pin=*)
        CPPFLAGS="-DMY_RF24_CS_PIN=${optarg} $CPPFLAGS"
        ;;
    --my-controller-url-address=*)
        CPPFLAGS="-DMY_CONTROLLER_URL_ADDRESS=\\\"${optarg}\\\" $CPPFLAGS"
        ;;
    --my-controller-ip-address=*)
        controller_ip=`echo ${optarg//./,}`
        CPPFLAGS="-DMY_CONTROLLER_IP_ADDRESS=${controller_ip} $CPPFLAGS"
        ;;
    --my-port=*)
        CPPFLAGS="-DMY_PORT=${optarg} $CPPFLAGS"
        ;;
    --my-mqtt-client-id=*)
        CPPFLAGS="-DMY_MQTT_CLIENT_ID=\\\"${optarg}\\\" $CPPFLAGS"
        ;;
    --my-mqtt-user=*)
        CPPFLAGS="-DMY_MQTT_USER=\\\"${optarg}\\\" $CPPFLAGS"
        ;;
    --my-mqtt-password=*)
        CPPFLAGS="-DMY_MQTT_PASSWORD=\\\"${optarg}\\\" $CPPFLAGS"
        ;; 
    --my-mqtt-publish-topic-prefix=*)
        CPPFLAGS="-DMY_MQTT_PUBLISH_TOPIC_PREFIX=\\\"${optarg}\\\" $CPPFLAGS"
        ;;
    --my-mqtt-subscribe-topic-prefix=*)
        CPPFLAGS="-DMY_MQTT_SUBSCRIBE_TOPIC_PREFIX=\\\"${optarg}\\\" $CPPFLAGS"
        ;;
    --my-rf24-irq-pin=*)
        CPPFLAGS="-DMY_RX_MESSAGE_BUFFER_FEATURE -DMY_RF24_IRQ_PIN=${optarg} $CPPFLAGS"
        ;;
    --my-rf24-encryption-enabled*)
        encryption=true
        CPPFLAGS="-DMY_RF24_ENABLE_ENCRYPTION $CPPFLAGS"
        ;;
    --my-rx-message-buffer-size=*)
        CPPFLAGS="-DMY_RX_MESSAGE_BUFFER_SIZE=${optarg} $CPPFLAGS"
        ;;
    --my-rfm69-frequency=*)
        if [[ ${optarg} == "315" ]]; then
            CPPFLAGS="-DMY_RFM69_FREQUENCY=RFM69_315MHZ $CPPFLAGS"
        elif [[ ${optarg} == "433" ]]; then
            CPPFLAGS="-DMY_RFM69_FREQUENCY=RFM69_433MHZ $CPPFLAGS"
        elif [[ ${optarg} == "865" ]]; then
            CPPFLAGS="-DMY_RFM69_FREQUENCY=RFM69_865MHZ $CPPFLAGS"
        elif [[ ${optarg} == "868" ]]; then
            CPPFLAGS="-DMY_RFM69_FREQUENCY=RFM69_868MHZ $CPPFLAGS"
        elif [[ ${optarg} == "915" ]]; then
            CPPFLAGS="-DMY_RFM69_FREQUENCY=RFM69_915MHZ $CPPFLAGS"
        else
            die "Illegal value for --my-rfm69-frequency=${optarg}" 8
        fi
        ;;
    --my-is-rfm69hw*)
        CPPFLAGS="-DMY_IS_RFM69HW $CPPFLAGS"
        ;;
    --my-rfm69-irq-pin=*)
        CPPFLAGS="-DMY_RFM69_IRQ_PIN=${optarg} $CPPFLAGS"
        ;;
    --my-rfm69-cs-pin=*)
        CPPFLAGS="-DMY_RFM69_CS_PIN=${optarg} $CPPFLAGS"
        ;;
    --my-rfm69-encryption-enabled*)
        encryption=true
        CPPFLAGS="-DMY_RFM69_ENABLE_ENCRYPTION $CPPFLAGS"
        ;;
    --my-rfm95-frequency=*)
        if [[ ${optarg} == "169" ]]; then
            CPPFLAGS="-DMY_RFM95_FREQUENCY=RFM95_169MHZ $CPPFLAGS"
        elif [[ ${optarg} == "315" ]]; then
            CPPFLAGS="-DMY_RFM95_FREQUENCY=RFM95_315MHZ $CPPFLAGS"
        elif [[ ${optarg} == "434" ]]; then
            CPPFLAGS="-DMY_RFM95_FREQUENCY=RFM95_434MHZ $CPPFLAGS"
        elif [[ ${optarg} == "868" ]]; then
            CPPFLAGS="-DMY_RFM95_FREQUENCY=RFM95_868MHZ $CPPFLAGS"
        elif [[ ${optarg} == "915" ]]; then
            CPPFLAGS="-DMY_RFM95_FREQUENCY=RFM95_915MHZ $CPPFLAGS"
        else
            die "Illegal value for --my-rfm95-frequency=${optarg}" 9
        fi
        ;;
    --my-rfm95-irq-pin=*)
        CPPFLAGS="-DMY_RFM95_IRQ_NUM=${optarg} $CPPFLAGS"
        ;;
    --my-rfm95-cs-pin=*)
        CPPFLAGS="-DMY_RFM95_CS_PIN=${optarg} $CPPFLAGS"
        ;;
    --my-rfm95-encryption-enabled*)
        encryption=true
        CPPFLAGS="-DMY_RFM95_ENABLE_ENCRYPTION $CPPFLAGS"
        ;;
    --my-rs485-serial-port=*)
        CPPFLAGS="-DMY_RS485_HWSERIAL=\\\"${optarg}\\\" $CPPFLAGS"
        ;;
    --my-rs485-baudrate=*)
        CPPFLAGS="-DMY_RS485_BAUD_RATE=${optarg} $CPPFLAGS"
        ;;
    --my-rs485-de-pin=*)
        CPPFLAGS="-DMY_RS485_DE_PIN=${optarg} $CPPFLAGS"
        ;;
    --my-rs485-max-msg-length=*)
        CPPFLAGS="-DMY_RS485_MAX_MESSAGE_LENGTH=${optarg} $CPPFLAGS"
        ;;
    --my-leds-err-pin=*)
        CPPFLAGS="-DMY_DEFAULT_ERR_LED_PIN=${optarg} $CPPFLAGS"
        ;;
    --my-leds-rx-pin=*)
        CPPFLAGS="-DMY_DEFAULT_RX_LED_PIN=${optarg} $CPPFLAGS"
        ;;
    --my-leds-tx-pin=*)
        CPPFLAGS="-DMY_DEFAULT_TX_LED_PIN=${optarg} $CPPFLAGS"
        ;;
    --my-leds-blinking-inverse*)
        CPPFLAGS="-DMY_WITH_LEDS_BLINKING_INVERSE $CPPFLAGS"
        ;;
    --my-signing=*)
        signing=${optarg}
        ;;
    --my-signing-debug*)
        CPPFLAGS="-DMY_DEBUG_VERBOSE_SIGNING $CPPFLAGS"
        ;;
    --my-signing-request-signatures*)
        signing_request_signatures=true
        ;;
    --my-signing-weak_security*)
        CPPFLAGS="-DMY_SIGNING_WEAK_SECURITY $CPPFLAGS"
        ;;
    --my-signing-whitelist*)
        CPPFLAGS="-DMY_SIGNING_NODE_WHITELISTING=${optarg} $CPPFLAGS"
        ;;
    --my-signing-verification-timeout-ms*)
        CPPFLAGS="-DMY_VERIFICATION_TIMEOUT_MS=${optarg} $CPPFLAGS"
        ;;
    --my-security-password=*)
        security_password=${optarg}
        ;;
    *)
        die "Unknown option detected: $opt" 10
        ;;
    esac
done

PREFIX=${PREFIX:-/usr/local}
BUILDDIR=${BUILDDIR:-build}
BINDIR=${BINDIR:-bin}
GATEWAY_DIR=${GATEWAY_DIR:-${PREFIX}/bin}
CC=${CC:-gcc}
CXX=${CXX:-g++}
CXXFLAGS="$CXXFLAGS -std=c++11"

if [ -z "${SOC}" ]; then
    printf "${SECTION} Detecting target machine.\n"
    info=($(detect_machine))
    SOC=${info[0]}
    TYPE=${info[1]}
    CPU=${info[2]}
    printf "  ${OK} machine detected: SoC=${SOC}, Type=${TYPE}, CPU=${CPU}.\n"
fi

if [ -z "${CPUFLAGS}" ]; then
    CPUFLAGS=$(gcc_cpu_flags "${SOC}" "${CPU}")
fi

if [[ $SOC == "BCM2835" || $SOC == "BCM2836" || $SOC == "BCM2837" || $SOC == "BCM2711" ]]; then
    CPPFLAGS="-DLINUX_ARCH_RASPBERRYPI $CPPFLAGS"
else
    printf "${SECTION} Checking GPIO Sysfs.\n"
    if [[ $(eval 'ls /sys/class/gpio/export 2>/dev/null') ]]; then
        printf "  ${OK} /sys/class/gpio/export found.\n"
    else
        echo "  [WARNING] /sys/class/gpio/export not found."
    fi
fi

if [[ $TYPE == "RockPi4" ]]; then
    FLTMP=$CPPFLAGS
    pattern="(.+_PIN=)([0-9]+)(.*)"
    while [[ $FLTMP =~ $pattern ]]; do
        FLTMP=${BASH_REMATCH[3]}
	CPPFLAGS=${BASH_REMATCH[1]}${ROCKPI4_PIN_MAP[${BASH_REMATCH[2]}-1]}
    done
    CPPFLAGS=$CPPFLAGS$FLTMP
    CPPFLAGS="-DLINUX_ARCH_ROCKPI4 $CPPFLAGS"
fi

if [ -z "${SPI_DRIVER}" ]; then
    printf "${SECTION} Detecting SPI driver.\n"
    if [[ $SOC == "BCM2835" || $SOC == "BCM2836" || $SOC == "BCM2837" || $SOC == "BCM2711" ]]; then
        SPI_DRIVER=BCM
    elif [[ $(eval 'ls /dev/spidev* 2>/dev/null') ]]; then
        SPI_DRIVER=SPIDEV
    fi
    if [ -n "${SPI_DRIVER}" ]; then
        printf "  ${OK} SPI driver detected:${SPI_DRIVER}.\n"
    else
        echo "  [WARNING] No supported SPI driver detected. Using SPIDEV."
        SPI_DRIVER=SPIDEV
    fi
fi
if [ -n "${SPI_DRIVER}" ]; then
    case ${SPI_DRIVER} in
        BCM)
            if [[ $SOC != "BCM2835" && $SOC != "BCM2836" && $SOC != "BCM2837" && $SOC != "BCM2711" ]]; then
                die "BCM SPI driver is only supported for SOCs BCM2835, BCM2836, BCM2837 or BCM2711" 5
            fi
            CPPFLAGS="-DLINUX_SPI_BCM $CPPFLAGS"
            ;;
        SPIDEV)
            CPPFLAGS="-DLINUX_SPI_SPIDEV $CPPFLAGS"
            ;;
        *)
            die "Unsupported SPI driver: ${SPI_DRIVER}." 1
            ;;
    esac
fi

printf "${SECTION} Gateway configuration.\n"

if [[ ${debug} == "enable" ]]; then
    CPPFLAGS="-DMY_DEBUG $CPPFLAGS"
fi

if [[ ${gateway_type} == "none" ]]; then
    # Node mode selected
    :
elif [[ ${gateway_type} == "ethernet" ]]; then
    CPPFLAGS="-DMY_GATEWAY_LINUX $CPPFLAGS"
elif [[ ${gateway_type} == "serial" ]]; then
    CPPFLAGS="-DMY_GATEWAY_SERIAL $CPPFLAGS"
elif [[ ${gateway_type} == "mqtt" ]]; then
    CPPFLAGS="-DMY_GATEWAY_LINUX -DMY_GATEWAY_MQTT_CLIENT $CPPFLAGS"
else
    die "Invalid gateway type." 2
fi
printf "  ${OK} Type: ${gateway_type}.\n"

if [[ ${transport_type} == "none" ]]; then
    # Transport disabled
    :
elif [[ ${transport_type} == "rf24" ]]; then
    CPPFLAGS="-DMY_RADIO_RF24 $CPPFLAGS"
elif [[ ${transport_type} == "rfm69" ]]; then
    CPPFLAGS="-DMY_RADIO_RFM69 -DMY_RFM69_NEW_DRIVER $CPPFLAGS"
elif [[ ${transport_type} == "rfm95" ]]; then
    CPPFLAGS="-DMY_RADIO_RFM95 $CPPFLAGS"
elif [[ ${transport_type} == "rs485" ]]; then
    CPPFLAGS="-DMY_RS485 $CPPFLAGS"
else
    die "Invalid transport type ${transport_type}." 3
fi
printf "  ${OK} Transport: ${transport_type}.\n"

if [[ ${signing} == "none" ]]; then
    # Signing disabled
    printf "  ${OK} Signing: Disabled.\n"
elif [[ ${signing} == "software" ]]; then
    CPPFLAGS="-DMY_SIGNING_SOFT $CPPFLAGS"
    if [[ ${signing_request_signatures} == true ]]; then
        CPPFLAGS="-DMY_SIGNING_REQUEST_SIGNATURES $CPPFLAGS"
    fi
    printf "  ${OK} Signing: Enabled - Using key from config file.\n"
elif [[ ${signing} == "password" ]]; then
    if [ -z "${security_password}" ]; then
        die "You need to set the password for signing with --my-security-password option" 6
    fi
    printf "  ${OK} Signing: Enabled - Simplified signing using password.\n"
    CPPFLAGS="-DMY_SIGNING_SIMPLE_PASSWD=\\\"${security_password}\\\" $CPPFLAGS"
else
    die "Invalid signing type." 7
fi

if [[ ${encryption} == true ]]; then
    # Encryption enabled on some transport
    if [ -z "${security_password}" ]; then
        printf "  ${OK} Encryption: Enabled - Using key from config file.\n"
    else
        printf "  ${OK} Encryption: Enabled - Simplified encryption using password.\n"
        CPPFLAGS="-DMY_ENCRYPTION_SIMPLE_PASSWD=\\\"${security_password}\\\" $CPPFLAGS"
    fi
else
    printf "  ${OK} Encryption: Disabled.\n"
fi

LDFLAGS="-pthread $LDFLAGS"
CPPFLAGS="$CPUFLAGS $CPPFLAGS"

printf "  ${OK} CPPFLAGS: $CPPFLAGS\n"
printf "  ${OK} CXXFLAGS: $CXXFLAGS\n"

printf "${SECTION} Detecting init system.\n"
if [ "${NO_INIT}" ];  then
    printf "  ${OK} No init system chosen.\n"
elif [ -x /usr/bin/systemctl ] || [ -x /bin/systemctl ]; then
    INIT_SYSTEM=systemd
    printf "  ${OK} Init system detected: systemd.\n"
elif [ -f /etc/init.d/cron ] && [ ! -h /etc/init.d/cron ]; then
    INIT_SYSTEM=sysvinit
    printf "  ${OK} Init system detected: sysvinit.\n"
else
    printf "  ${FAILED} Unknown init system.\n"
fi

printf "${SECTION} Saving configuration.\n"
echo -n "" > Makefile.inc
for param in ${params}; do
    if [[ ${!param} ]]; then
        echo "${param}=${!param}" >> Makefile.inc
    fi
done
printf "  ${OK} Saved.\n"

if [ -z "${NO_CLEAN}" ]; then
    printf "${SECTION} Cleaning previous builds.\n"
    make clean >/dev/null
fi


printf "  ${OK} Finished.\n"
