#!/usr/bin/env bash

set -ex

DL="${DL:-/tmp/dl}"
DEP_DIR_PREFIX=$PWD/deps
CORE_DIR=$(dirname $(realpath -s $0))/../..
CMAKE_C_COMPILER="w64-mingw32-gcc-posix"
CMAKE_CXX_COMPILER="w64-mingw32-g++-posix"
ARCH=${ARCH:-i686 x86_64}

download_deps()
{
    if [ -n "$NO_DEPS" ]; then
        echo "Skip dependencies download"
        return
    fi

    pushd $DL

    rm -rf lz4
    git clone https://github.com/lz4/lz4.git
    portfile_url=https://raw.githubusercontent.com/microsoft/vcpkg/master/ports/lz4/portfile.cmake
    gitref=$(wget -q -O- "$portfile_url" | grep -oP '\bREF\s+\S+' | cut -d' ' -f2)
    git -C lz4 checkout "${gitref}"

    rm -rf jsoncpp
    git clone https://github.com/open-source-parsers/jsoncpp.git
    portfile_url=https://raw.githubusercontent.com/microsoft/vcpkg/master/ports/jsoncpp/portfile.cmake
    gitref=$(wget -q -O- "$portfile_url" | grep -oP '\bREF\s+\S+' | cut -d' ' -f2)
    git -C jsoncpp checkout "${gitref}"

    if [ -z "$NO_OPENSSL" ]; then
        rm -rf openssl
        portfile_url=https://raw.githubusercontent.com/microsoft/vcpkg/master/ports/openssl/vcpkg.json
        osslver=$(wget -q -O- "$portfile_url" | grep -oP '\"version": \"\S+' | cut -d' ' -f2 | tr -d "\",")
        git clone --single-branch --branch "openssl-$osslver" https://github.com/openssl/openssl.git
    fi

    rm -rf tap-windows6
    git clone https://github.com/OpenVPN/tap-windows6.git
    portfile_url=https://raw.githubusercontent.com/microsoft/vcpkg/master/ports/tap-windows6/portfile.cmake
    gitref=$(wget -q -O- "$portfile_url" | grep -oP '\bREF\s+\S+' | cut -d' ' -f2)
    git -C tap-windows6 checkout "${gitref}"

    rm -rf asio
    portfile=${CORE_DIR}/deps/vcpkg-ports/asio/portfile.cmake
    gitref=$(grep -oP '\bREF\s+\S+' "$portfile" | cut -d' ' -f2)
    git clone --single-branch --branch "$gitref" https://github.com/chriskohlhoff/asio
    # apply asio patches
    for patchfile in $(grep -o patches.* "$portfile" | cut -d '/' -f2); do
        echo applying patch $patchfile
        patch -d asio -p1 < "${CORE_DIR}/deps/asio/patches/$patchfile"
    done

    rm -rf xxHash
    git clone https://github.com/Cyan4973/xxHash.git
    portfile_url=https://raw.githubusercontent.com/microsoft/vcpkg/master/ports/xxhash/vcpkg.json
    gitref=$(wget -q -O- "$portfile_url" | grep -oP '\"version": \"\S+' | cut -d' ' -f2 | tr -d "\",")
    git -C xxHash checkout "v${gitref}"

    popd
}

build_lz4()
{
    ARCH=$1

    pushd $DL/lz4

    mkdir build-${ARCH}
    cd build-${ARCH}

    cmake -D CMAKE_C_COMPILER=$ARCH-$CMAKE_C_COMPILER \
          -D CMAKE_SYSTEM_NAME=Windows \
          -D CMAKE_INSTALL_PREFIX=$DEP_DIR_PREFIX-$ARCH \
          ../build/cmake/
    make && make install

    popd
}

build_jsoncpp()
{
    ARCH=$1

    pushd $DL/jsoncpp

    mkdir build-${ARCH}
    cd build-${ARCH}

    cmake -D CMAKE_CXX_COMPILER=$ARCH-$CMAKE_CXX_COMPILER \
          -D CMAKE_SYSTEM_NAME=Windows \
          -D CMAKE_INSTALL_PREFIX=$DEP_DIR_PREFIX-$ARCH \
          -D JSONCPP_WITH_TESTS=false \
          -D BUILD_SHARED_LIBS=true \
          -D CMAKE_BUILD_TYPE=Release \
          ..
    make && make install

    popd
}

build_openssl()
{
    if [ -n "$NO_OPENSSL" ]; then
        echo "Skip OpenSSL build"
        return
    fi

    ARCH=$1

    pushd $DL/openssl

    [ "$ARCH" == "x86_64" ] && OUT="mingw64" || OUT="mingw"
    make clean || true
    ./Configure --prefix=$DEP_DIR_PREFIX-$ARCH --libdir=lib no-idea no-mdc2 no-rc5 shared $OUT --cross-compile-prefix=$ARCH-w64-mingw32-
    make && make install

    popd
}

build_tap_windows6()
{
    ARCH=$1

    cp $DL/tap-windows6/src/tap-windows.h $DEP_DIR_PREFIX-$ARCH/include
}

build_asio()
{
    ARCH=$1

    mkdir -p $DEP_DIR_PREFIX-$ARCH/asio
    cp -R $DL/asio/* $DEP_DIR_PREFIX-$ARCH/asio
}

build_xxhash()
{
    ARCH=$1

    mkdir -p $DEP_DIR_PREFIX-$ARCH/xxHash
    cp -R $DL/xxHash/* $DEP_DIR_PREFIX-$ARCH/xxHash
}

build_deps()
{
    if [ -n "$NO_DEPS" ]; then
        echo "Skip dependencies build"
        return
    fi

    ARCH=$1

    echo "Building deps for $arch"

    mkdir -p $DEP_DIR_PREFIX-$ARCH

    build_lz4 $ARCH
    build_jsoncpp $ARCH
    build_tap_windows6 $ARCH
    build_asio $ARCH
    build_xxhash $ARCH
    build_openssl $ARCH
}

build_core()
{
    ARCH=$1

    echo "Building core for $arch"

    rm -rf build-$ARCH
    mkdir build-$ARCH

    [ -z "$DCO" ] || {
        WITH_OVPNDCOWIN="-D CLI_OVPNDCOWIN=ON"
    }

    pushd build-$ARCH

    DEP_DIR=$DEP_DIR_PREFIX-$ARCH \
    OPENSSL_ROOT_DIR=${OPENSSL_ROOT_DIR:-$DEP_DIR_PREFIX-$ARCH} \
    cmake -D CMAKE_C_COMPILER=$ARCH-$CMAKE_C_COMPILER \
          -D CMAKE_CXX_COMPILER=$ARCH-$CMAKE_CXX_COMPILER \
          -D CMAKE_SYSTEM_NAME=Windows \
          -D CMAKE_PREFIX_PATH=/usr/local/$ARCH-w64-mingw32 \
          -D CMAKE_BUILD_TYPE=Release \
          -D USE_WERROR=true \
          $WITH_OVPNDCOWIN \
          $CORE_DIR

    make

    popd
}

mkdir -p $DL

download_deps
for arch in $ARCH
do
    echo "Building for $arch"
    build_deps $arch
    build_core $arch
done
