#!/data/data/com.termux/files/usr/bin/env bash
#-----------------------------------------------------------------------------
#
#  TSDuck - The MPEG Transport Stream Toolkit
#  Copyright (c) 2005-2026, Thierry Lelegard
#  BSD-2-Clause license, see LICENSE.txt file or https://tsduck.io/license
#
#  This script is used with the TSDuck development environment.
#  It displays various options to build applications with the TSDuck library.
#
#-----------------------------------------------------------------------------

TSCONFIG=${BASH_SOURCE[0]}
SCRIPT=$(basename $TSCONFIG)
SYSTEM=$(uname -s)
info()  { echo >&2 "$SCRIPT: $*"; }
error() { echo >&2 "$SCRIPT: $*"; exit 1; }
usage() { error "invalid option $*, try --help"; }

# Display help text
cmd_help() {
    cat >&2 <<EOF

Syntax: $SCRIPT [options]

  --cflags      pre-processor and compiler flags
  --libs        library linking flags
  --static-libs static library linking flags

  --so          shared object files extension (".so", ".dylib", ".dll")
  --prefix      installation prefix
  --bin         directory for TSDuck executables
  --lib         directory for TSDuck dynamic libraries (except plugins)
  --plugin      directory for TSDuck plugins
  --config      directory for TSDuck configuration files
  --include     include directories
  --java        jar file for TSDuck Java bindings, to be added in CLASSPATH
  --python      directory for TSDuck Python bindings, to be added in PYTHONPATH

  --tscore      use libtscore only, not libtsduck (reduced footprint)
  --nostdcpp    do not impose a C++ standard level in cflags
  --help        display this help and exit
  --version     output version information
  --vernum      output the version information as a number

EOF
    if [[ $SYSTEM == Linux ]]; then
        cat >&2 <<EOF
  --install-dvb-firmware   download and install additional DVB firmware

EOF
    fi
    exit
}

# Process individual commands
cmd_bin() {
    (cd $(dirname "$TSCONFIG" 2>/dev/null); pwd)
}

cmd_prefix() {
    (cd $(dirname "$TSCONFIG" 2>/dev/null); cd ..; pwd)
}

cmd_plugin() {
    echo "$(cmd_lib)/tsduck"
}

cmd_config() {
    echo "$(cmd_prefix)/share/tsduck"
}

incl_preconfig() {
    echo "$(cmd_prefix)/include/tscore/tsPreConfiguration.h"
}

incl_version() {
    echo "$(cmd_prefix)/include/tscore/tsVersion.h"
}

cmd_include() {
    local dir=
    [[ -z $TS_TSCORE ]] && dir="$(cmd_prefix)/include/tsduck "
    echo "${dir}$(cmd_prefix)/include/tscore"
}

cmd_java() {
    local jar="$(cmd_prefix)/share/tsduck/java/tsduck.jar"
    [[ -e "$jar" ]] && echo "$jar"
}

cmd_python() {
    echo "$(cmd_prefix)/share/tsduck/python"
}

no_pcsc() {
    grep -q TS_NO_PCSC $(incl_preconfig) 2>/dev/null
}

no_zlib() {
    grep -q TS_NO_ZLIB $(incl_preconfig) 2>/dev/null
}

no_srt() {
    grep -q TS_NO_SRT $(incl_preconfig) 2>/dev/null
}

no_rist() {
    grep -q TS_NO_RIST $(incl_preconfig) 2>/dev/null
}

cmd_lib() {
    dirname $(ls $(cmd_prefix)/lib*/libtscore$(cmd_so) 2>/dev/null | head -1) 2>/dev/null
}

brewprefix() {
    local before=$1
    local after=$2
    local prefix=
    [[ $SYSTEM == Darwin && -n $(which brew 2>/dev/null) ]] && prefix=$(brew --prefix)
    [[ -n $prefix ]] && echo "$before$prefix$after"
}

cmd_cflags() {
    local pcsc=
    local std=" -std=c++20"
    local inc=
    [[ -z $TS_TSCORE && $SYSTEM == Linux && -d /usr/include/PCSC ]] && ! $(no_pcsc) && pcsc="-I/usr/include/PCSC"
    [[ -n $TS_NOSTDCPP ]] && std=""
    [[ -z $TS_TSCORE ]] && inc="-I$(cmd_prefix)/include/tsduck"
    echo "$inc -I$(cmd_prefix)/include/tscore $(brewprefix -I /include) $pcsc $std"
}

cmd_so() {
    if [[ $SYSTEM == Darwin ]]; then
        echo ".dylib"
    elif [[ $SYSTEM == CYGWIN* || $SYSTEM == MINGW* ]]; then
        echo ".dll"
    else
        echo ".so"
    fi
}

libs_common() {
    local pcsc=
    local rt=
    local dl=
    [[ -z $TS_TSCORE && $SYSTEM == Darwin ]] && ! $(no_pcsc) && pcsc="-framework PCSC"
    [[ -z $TS_TSCORE && $SYSTEM == Linux && -d /usr/include/PCSC ]] && ! $(no_pcsc) && pcsc="-lpcsclite"
    [[ $SYSTEM == Linux ]] && rt="-lrt"
    [[ $SYSTEM == OpenBSD ]] || dl="-ldl"
    echo "$(brewprefix -L /lib) $pcsc -lpthread $rt $dl -lm -lstdc++"
}

cmd_libs() {
    local lib=$(cmd_lib)
    local usrlib=/usr/lib
    local lopt=
    local lib1=
    [[ -n $(ls /usr/lib64/libc.so* 2>/dev/null) ]] && usrlib=/usr/lib64
    [[ $lib != $usrlib ]] && lopt="-L$lib"
    [[ -z $TS_TSCORE ]] && lib1="-ltsduck"
    echo "$lopt $lib1 -ltscore $(libs_common)"
}

cmd_staticlibs() {
    local lib1=
    local zlib=
    local srt=
    local rist=
    local other=
    [[ -z $TS_TSCORE ]] && lib1="$(cmd_lib)/libtsduck.a"
    $(no_zlib) || zlib="-lz"
    $(no_srt) || srt=$(ls /usr/lib/libsrt.a /usr/local/lib/libsrt.a /opt/homebrew/lib/libsrt.a 2>/dev/null | head -1)
    $(no_rist) || rist=$(ls /usr/lib/librist.a /usr/local/lib/librist.a /opt/homebrew/lib/librist.a 2>/dev/null | head -1)
    [[ $SYSTEM == Linux ]] && other="$other -latomic"
    [[ $SYSTEM == FreeBSD ]] && other="$other -lprocstat"
    [[ $SYSTEM == OpenBSD || $SYSTEM == NetBSD ]] && other="$other -lkvm"
    echo "$lib1 $(cmd_lib)/libtscore.a $srt $rist $zlib $(curl-config --static-libs 2>/dev/null) -ledit $other $(libs_common)"
}

version_major() {
    sed -e '/#define *TS_VERSION_MAJOR/!d' -e 's/ *$//' -e 's/.* //' $(incl_version) 2>/dev/null
}

version_minor() {
    sed -e '/#define *TS_VERSION_MINOR/!d' -e 's/ *$//' -e 's/.* //' $(incl_version) 2>/dev/null
}

version_commit() {
    sed -e '/#define *TS_COMMIT/!d' -e 's/ *$//' -e 's/.* //' $(incl_version) 2>/dev/null
}

cmd_version() {
    echo "$(version_major).$(version_minor).$(version_commit)"
}

cmd_vernum() {
    echo $(( ($(version_major) * 10000000) + ($(version_minor) * 100000) + $(version_commit) ))
}

cmd_install_firmware() {
    [[ $SYSTEM == Linux ]] || error "DVB firmware is available on Linux only"
    [[ $(id -u) -eq 0 ]] || error "must be root to install firmware"
    local fwdir=/lib/firmware
    [[ -d "$fwdir" ]] || error "directory $fwdir does not exist, maybe not the right system"

    # linux-firmware package: standard package (depends on distro).
    if [[ -n $(which apt 2>/dev/null) ]]; then
        if ! (apt -qq list linux-firmware 2>/dev/null | grep -q installed); then
            info "installing package linux-firmware ..."
            apt install -y linux-firmware
        fi
    fi
    local dnf=$(which dnf 2>/dev/null)
    [[ -z "$dnf" ]] && dnf=$(which yum 2>/dev/null)
    if [[ -n "$dnf" ]]; then
        if ! rpm -q linux-firmware &>/dev/null; then
            info "installing package linux-firmware ..."
            "$dnf" install -y linux-firmware
        fi
    fi

    # OpenELEC project: The firmware files are directly downloaded from the GitHut repository.
    # Exclude the first two levels of directory (down to "firmware" directory).
    info "downloading firmware from OpenELEC project ..."
    curl -sL https://github.com/OpenELEC/dvb-firmware/tarball/master | \
        tar -C "$fwdir" -xzpvf - --strip-components=2 --wildcards 'OpenELEC-dvb-firmware-*/firmware'
}

# Main processing. First pass: get global options.
TS_NOSTDCPP=
TS_TSCORE=
TS_ARGS=()
for arg in "$@"; do
    case "$arg" in
        --nostdcpp) TS_NOSTDCPP=true ;;
        --tscore) TS_TSCORE=true ;;
        *) TS_ARGS+=("$arg")
    esac
done

# Second pass: process the options.
if [ ${#TS_ARGS[@]} -eq 0 ]; then
    # No option, display everything.
    echo "version: $(cmd_version)"
    echo "prefix: $(cmd_prefix)"
    echo "so: $(cmd_so)"
    echo "bin: $(cmd_bin)"
    echo "lib: $(cmd_lib)"
    echo "plugin: $(cmd_plugin)"
    echo "config: $(cmd_config)"
    echo "include: $(cmd_include)"
    echo "cflags: $(cmd_cflags)"
    echo "libs: $(cmd_libs)"
    echo "static-libs: $(cmd_staticlibs)"
    echo "java: $(cmd_java)"
    echo "python: $(cmd_python)"
else
    # Display options one by one.
    for arg in "${TS_ARGS[@]}"; do
        case "$arg" in
            --bin) cmd_bin ;;
            --cflags) cmd_cflags ;;
            --config) cmd_config ;;
            --help) cmd_help ;;
            --include) cmd_include ;;
            --java) cmd_java ;;
            --lib) cmd_lib ;;
            --libs) cmd_libs ;;
            --plugin) cmd_plugin ;;
            --prefix) cmd_prefix ;;
            --python) cmd_python ;;
            --so) cmd_so ;;
            --static-libs) cmd_staticlibs ;;
            --version) cmd_version ;;
            --vernum) cmd_vernum ;;
            --install-dvb*) cmd_install_firmware ;;
            *) usage "$arg" ;;
        esac
        shift
    done
fi
