#!/bin/bash

# Adapted from Pivotals libhdfs3 native c++ hdfs client project
# https://github.com/Pivotal-Data-Attic/pivotalrd-libhdfs3

die() {
    echo "$@" 1>&2 ; exit 1
}

arg() {
    echo "$1" | sed "s/^${2-[^=]*=}//" | sed "s/:/;/g"
}

# Detect directory information.
source_dir=`cd "\`dirname \"$0\"\`";pwd`
binary_dir=`pwd`

# Choose the default install prefix.
default_prefix="${binary_dir}/dist"

# Choose the default dependency install prefix
default_dependency=${DEPENDENCY_INSTALL_PREFIX}

if [ x"${default_dependency}" = x"" ]; then
    default_dependency="/opt/dependency"
fi

# Display bootstrap usage
usage() {
echo '
Usage: '"$0"' [<options>]
Options: [defaults in brackets after descriptions]
Configuration:
    --help                          print this message
    --prefix=PREFIX                 install files in tree rooted at PREFIX
                                    ['"${default_prefix}"']
    --enable-vcpkg                  use vcpkg for downloading and building dependencies
    --dependency=DIRs               specify the dependencies at DIRs, separated by colon
                                    ['"${default_dependency}"']
    --force-build-all-deps          force building of all dependencies, even those
                                    already installed at system-level
    --remove-deprecations           build TileDB without any deprecated APIs
    --disable-werror                disables use of -Werror during build
    --disable-cpp-api               disables building of the TileDB C++ API
    --disable-tests                 disables building the TileDB tests
    --disable-stats                 disables internal TileDB statistics
    --disable-avx2                  disables use of AVX2 instructions
    --disable-webp                  disables building of webp library and linkage test
    --disable-vcpkg                 disables use of vcpkg for downloading and building dependencies
    --enable-static-tiledb          enables building TileDB as a static library
    --enable-sanitizer=SAN          enable sanitizer (clang only)
                                    (address|memory|leak|thread|undefined)
    --enable-debug                  enable debug build
    --enable-assertions             enable assertions in compiled code
    --enable-release-symbols        enable create symbols for release build
    --enable-coverage               enable build with code coverage support
    --enable-verbose                enable verbose status messages
    --enable-hdfs                   enables the hdfs storage backend
    --enable-s3                     enables the s3 storage backend
    --enable-azure                  enables the azure storage backend
    --enable-gcs                    enables the gcs storage backend
    --enable-serialization          enables query serialization support
    --enable-tools                  enables TileDB CLI tools (experimental)
    --enable-ccache                 enables use of ccache (if present)
    --enable-arrow-tests            enables the compilation of the arrow adapter unit tests
    --enable-experimental-features  enables experimental TileDB features
    --enable-rest-tests             enables REST tests
    --enable-aws-s3-config          enables AWS S3 configuration for tests
    --enable=arg1,arg2...           same as "--enable-arg1 --enable-arg2 ..."


Dependencies:
    c/c++ compiler
    GNU make
    cmake           http://www.cmake.org/

Example:
    mkdir build
    cd build
    ../bootstrap --prefix=/path/to/install --dependency=/path/to/dep1:path/to/dep2...
    make
    make install
'
    exit 10
}

# Parse arguments
prefix_dirs="${default_prefix}"
tiledb_vcpkg="ON"
dependency_dir="${default_dependency}"
sanitizer=""
build_type="Release"
tiledb_verbose="OFF"
tiledb_hdfs="OFF"
tiledb_s3="OFF"
tiledb_azure="OFF"
tiledb_gcs="OFF"
tiledb_werror="ON"
tiledb_tests="ON"
tiledb_cpp_api="ON"
tiledb_force_all_deps="OFF"
tiledb_remove_deprecations="OFF"
tiledb_stats="ON"
tiledb_static="OFF"
tiledb_disable_avx2=""
tiledb_assertions="OFF"
tiledb_serialization="OFF"
tiledb_tools="OFF"
tiledb_ccache="OFF"
tiledb_arrow_tests="OFF"
tiledb_experimental_features="OFF"
tiledb_build_webp="ON"
tiledb_tests_enable_rest="OFF"
tiledb_tests_aws_s3_config="OFF"
enable_multiple=""
while test $# != 0; do
    case "$1" in
    --prefix=*) dir=`arg "$1"`
                prefix_dirs="$dir";;
    --enable-vcpkg) echo "Argument '--enable-vcpkg' is obsolete and will be removed in a future version. Vcpkg is now enabled by default."
                    tiledb_vcpkg="ON";;
    --dependency=*) dir=`arg "$1"`
                dependency_dir="$dir";;
    --force-build-all-deps) tiledb_force_all_deps="ON";;
    --remove-deprecations) tiledb_remove_deprecations="ON";;
    --disable-werror) tiledb_werror="OFF";;
    --disable-tests) tiledb_tests="OFF";;
    --disable-cpp-api) tiledb_cpp_api="OFF";;
    --disable-stats) tiledb_stats="OFF";;
    --disable-avx2) tiledb_disable_avx2="-DCOMPILER_SUPPORTS_AVX2=FALSE";;
    --disable-webp) tiledb_build_webp="OFF";;
    --disable-vcpkg) tiledb_vcpkg="OFF";;
    --enable-assertions) tiledb_assertions="ON";;
    --enable-debug) build_type="Debug";;
    --enable-release-symbols) build_type="RelWithDebInfo";;
    --enable-coverage) build_type="Coverage";;
    --enable-verbose) tiledb_verbose="ON";;
    --enable-hdfs) tiledb_hdfs="ON";;
    --enable-s3) tiledb_s3="ON";;
    --enable-azure) tiledb_azure="ON";;
    --enable-gcs) tiledb_gcs="ON";;
    --enable-serialization) tiledb_serialization="ON";;
    --enable-static-tiledb) tiledb_static="ON";;
    --enable-sanitizer=*) san=`arg "$1"`
                sanitizer="$san";;
    --enable-tools) tiledb_tools="ON";;
    --enable-ccache) tiledb_ccache="ON";;
    --enable-arrow-tests) tiledb_arrow_tests="ON";;
    --enable-experimental-features) tiledb_experimental_features="ON";;
    --enable-rest-tests) tiledb_tests_enable_rest="ON";;
    --enable-aws-s3-config) tiledb_tests_aws_s3_config="ON";;
    --enable=*) s=`arg "$1"`
                enable_multiple+="${enable_multiple:+,}${s}";;
    --help) usage ;;
    *) die "Unknown option: $1" ;;
    esac
    shift
done

# Parse the comma-separated list of enables.
IFS=',' read -ra enables <<< "$enable_multiple"
for en in "${enables[@]}"; do
  case "$en" in
    vcpkg) echo "Argument '--enable-vcpkg' is obsolete and will be removed in a future version. Vcpkg is now enabled by default."
           tiledb_vcpkg="ON";;
    assertions) tiledb_assertions="ON";;
    debug) build_type="Debug";;
    release-symbols) build_type="RelWithDebInfo";;
    coverage) build_type="Coverage";;
    verbose) tiledb_verbose="ON";;
    s3) tiledb_s3="ON";;
    azure) tiledb_azure="ON";;
    gcs) tiledb_gcs="ON";;
    serialization) tiledb_serialization="ON";;
    tools) tiledb_tools="ON";;
    ccache) tiledb_ccache="ON";;
    arrow-tests) tiledb_arrow_tests="ON";;
    hdfs) tiledb_hdfs="ON";;
    static-tiledb) tiledb_static="ON";;
    experimental-features) tiledb_experimental_features="ON";;
    rest-tests) tiledb_tests_enable_rest="ON";;
    aws-s3-config) tiledb_tests_aws_s3_config="ON";;
    *) die "Unknown option: --enable-$en" ;;
  esac
done

if [ "${source_dir}" = "${binary_dir}" ]; then
    die "cannot build the project in the source directory! Out-of-source build is enforced!"
fi

# Check clang compiler
if [[ x"${CC}" = x"" ]]; then
    CC=gcc
fi

if [[ x"${CXX}" = x"" ]]; then
    CXX=g++
fi

c_compiler=`which ${CC}`
cxx_compiler=`which ${CXX}`
cmake=`which cmake`

if [[ ! -x ${c_compiler} ]]; then
    die "cannot find c compiler"
fi

if [[ ! -x ${cxx_compiler} ]]; then
    die "cannot find cplusplus compiler"
fi

if [[ ! -x ${cmake} ]]; then
    die "cannot find cmake"
fi

# Configure
${cmake} -DCMAKE_BUILD_TYPE=${build_type} \
    -DCMAKE_INSTALL_PREFIX="${prefix_dirs}" \
    -DCMAKE_C_COMPILER="${c_compiler}" \
    -DCMAKE_CXX_COMPILER="${cxx_compiler}" \
    -DCMAKE_PREFIX_PATH="${dependency_dir}" \
    -DTILEDB_VCPKG=${tiledb_vcpkg} \
    -DTILEDB_ASSERTIONS=${tiledb_assertions} \
    -DTILEDB_VERBOSE=${tiledb_verbose} \
    -DTILEDB_HDFS=${tiledb_hdfs} \
    -DTILEDB_S3=${tiledb_s3} \
    -DTILEDB_AZURE=${tiledb_azure} \
    -DTILEDB_GCS=${tiledb_gcs} \
    -DTILEDB_SERIALIZATION=${tiledb_serialization} \
    -DTILEDB_TOOLS=${tiledb_tools} \
    -DTILEDB_WERROR=${tiledb_werror} \
    -DTILEDB_CPP_API=${tiledb_cpp_api} \
    -DTILEDB_STATS=${tiledb_stats} \
    -DTILEDB_STATIC=${tiledb_static} \
    -DTILEDB_TESTS=${tiledb_tests} \
    -DTILEDB_CCACHE=${tiledb_ccache} \
    -DTILEDB_ARROW_TESTS=${tiledb_arrow_tests} \
    -DTILEDB_WEBP=${tiledb_build_webp} \
    -DTILEDB_FORCE_ALL_DEPS=${tiledb_force_all_deps} \
    -DTILEDB_REMOVE_DEPRECATIONS=${tiledb_remove_deprecations} \
    -DSANITIZER="${sanitizer}" \
    -DTILEDB_EXPERIMENTAL_FEATURES=${tiledb_experimental_features} \
    -DTILEDB_TESTS_ENABLE_REST=${tiledb_tests_enable_rest} \
    -DTILEDB_TESTS_AWS_S3_CONFIG=${tiledb_tests_aws_s3_config} \
    ${tiledb_disable_avx2} \
    "${source_dir}" || die "failed to configure the project"

echo 'bootstrap success. Run "make" to build, "make check" to test, or "make -C tiledb install" to install.'
