#!/bin/bash

#
# Copyright (c) Contributors to the Open 3D Engine Project.
# For complete copyright and license terms please see the LICENSE at the root of this distribution.
# 
# SPDX-License-Identifier: Apache-2.0 OR MIT
#
#

SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
cd $SCRIPT_DIR

echo ""
echo "--------------- PYTHON PACKAGE BUILD SCRIPT ----------------"
echo ""
echo "BASIC REQUIREMENTS in case something goes wrong:"
echo "   - git installed and in PATH"
echo "   - packages installed: apt-get dev-essential tk8.6-dev python3 libssl-dev tcl8.6-dev libgdbm-compat-dev liblzma-dev libsqlite3-dev libreadline-dev texinfo"
echo "   - python3 with pip in PATH! (i.e. sudo apt install python3 and sudo apt install python3-pip"
echo "   - Note: This script is currently written for buildng on Ubuntu Linux only."
echo "   - Note: installing binaries with pip must result with them being on PATH."
echo ""

# Make sure we have all the required dev packages
REQUIRED_DEV_PACKAGES="tk8.6-dev python3 libssl-dev tcl8.6-dev libgdbm-compat-dev liblzma-dev libsqlite3-dev libreadline-dev texinfo"
ALL_PACKAGES=`apt list 2>/dev/null`
for req_package in $REQUIRED_DEV_PACKAGES
do
    PACKAGE_COUNT=`echo $ALL_PACKAGES | grep $req_package | wc -l`
    if [[ $PACKAGE_COUNT -eq 0 ]]; then
        echo Missing required package $req_package
        exit 1
    fi
done


if [[ ${PACKAGE_CLEAR_TEMP_FOLDERS} -gt 0 ]]; then
    echo "   - PACKAGE_CLEAR_TEMP_FOLDERS env var is set > 0, will clear temp folders."
else
    echo "   - PACKAGE_CLEAR_TEMP_FOLDERS env var not set or = 0, will not clear temp."
fi
echo "   ... this will take about one and a half hours ..."
echo ""

mkdir -p temp


echo ""
echo "--------------- Cloning python 3.10.13 from git ---------------"
echo ""
cd temp
git clone https://github.com/python/cpython.git --branch v3.10.13 --depth 1

if [[ ! -d "cpython" ]]; then
    echo "Was unable to create cpython dir via git clone.  Is git installed?"
    exit 1
fi

echo ""
echo "--------------- Cloning libexpat 2.4.6 from git and applying update ---------------"
echo ""
git clone https://github.com/libexpat/libexpat.git --branch "R_2_4_6" --depth 1

if [[ ! -d "libexpat" ]]; then
    echo "Was unable to create libexpat dir via git clone.  Is git installed?"
    exit 1
fi

cp -f -v libexpat/expat/lib/*.h cpython/Modules/expat/
cp -f -v libexpat/expat/lib/*.c cpython/Modules/expat/


echo ""
echo "--------------- Cloning libffi 3.4.2 and building static version ---------------"
echo ""
git clone https://github.com/libffi/libffi.git --branch "v3.4.2" --depth 1
if [[ ! -d "libffi" ]]; then
    echo "Was unable to create libffi dir via git clone."
    exit 1
fi

pushd libffi

# According to the README.md for libffi, we need to run autogen.sh first
./autogen.sh
retVal=$?
if [ $retVal -ne 0 ]; then
    echo "Error running autogen.sh for libffi"
    exit $retVal
fi
 
./configure --prefix=$SCRIPT_DIR/temp/ffi_lib --enable-shared=no CFLAGS='-fPIC' CPPFLAGS='-fPIC'
retVal=$?
if [ $retVal -ne 0 ]; then
    echo "Error running configuring for libffi"
    exit $retVal
fi

make install
retVal=$?
if [ $retVal -ne 0 ]; then
    echo "Error building libffi"
    exit $retVal
fi

popd


echo ""
echo "--------------- Cloning openssl 1.1.1w and building it externally ---------------"
echo ""
git clone https://github.com/openssl/openssl.git --branch "OpenSSL_1_1_1w" --depth 1
if [[ ! -d "openssl" ]]; then
    echo "Was unable to create openssl dir via git clone."
    exit 1
fi

pushd openssl

echo ./config --prefix=$SCRIPT_DIR/temp/openssl-local/build --openssldir=/etc/ssl LDFLAGS='-Wl,-rpath=\$$ORIGIN'
./config --prefix=$SCRIPT_DIR/temp/openssl-local/build --openssldir=/etc/ssl LDFLAGS='-Wl,-rpath=\$$ORIGIN'

retVal=$?
if [ $retVal -ne 0 ]; then
    echo "Error building openssl"
    exit $retVal
fi

echo make
make
if [ $retVal -ne 0 ]; then
    echo "Error building openssl (build failure)"
    exit $retVal
fi

echo make test
if [ $retVal -ne 0 ]; then
    echo "Error building openssl (test failure)"
    exit $retVal
fi

echo make install
make install
if [ $retVal -ne 0 ]; then
    echo "Error building openssl (install failure)"
    exit $retVal
fi

popd


cd cpython

echo ""
echo "--------------- Building cpython from source ---------------"
echo ""

# Build from the source with optimizations and shared libs enabled , and override the RPATH and bzip include/lib paths
./configure --prefix=$SCRIPT_DIR/package/python --enable-optimizations --with-openssl=$SCRIPT_DIR/temp/openssl-local/build --enable-shared LDFLAGS='-Wl,-rpath=\$$ORIGIN:\$$ORIGIN/../lib:\$$ORIGIN/../.. -L../ffi_lib/lib' CPPFLAGS='-I../ffi_lib/include' CFLAGS='-I../ffi_lib/include' 
retVal=$?
if [ $retVal -ne 0 ]; then
    echo "Error running configuring optimized build"
    exit $retVal
fi

make
retVal=$?
if [ $retVal -ne 0 ]; then
    echo "Error compiling optimized build"
    exit $retVal
fi

# Prepare the package folder
cd $SCRIPT_DIR

# Install the newly built python 3.10.13 to the package/python folder
cd $SCRIPT_DIR
cd temp
cd cpython

make install
retVal=$?
if [ $retVal -ne 0 ]; then
    echo "Error installing python to the package folder"
    exit $retVal
fi


cd $SCRIPT_DIR
mkdir -p package
cd package

cp $SCRIPT_DIR/temp/cpython/LICENSE ./python/LICENSE
cp $SCRIPT_DIR/PackageInfo.json .
cp $SCRIPT_DIR/*.cmake .

cd $SCRIPT_DIR/package/python/bin
ln -s python3 python
cd $SCRIPT_DIR/package


# Move the openssl libraries to the local cpython build for portability
pushd $SCRIPT_DIR/package/python/lib
cp $SCRIPT_DIR/temp/openssl-local/build/lib/libssl.so.1.1 .
ln -s libssl.so.1.1 libssl.so.1
cp $SCRIPT_DIR/temp/openssl-local/build/lib/libcrypto.so.1.1 .
ln -s libcrypto.so.1.1 libcrypto.so.1
popd

# Copy the openssl license
cp $SCRIPT_DIR/temp/openssl/LICENSE $SCRIPT_DIR/package/python/LICENSE.OPENSSL


echo ""
echo "--------------- Upgrading pip ---------------"
echo ""
# the pip that may come from the above repo can be broken, so we'll use get-pip
# and then upgrade it.
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
./python/bin/python3 get-pip.py
rm get-pip.py
PYTHONNOUSERSITE=1 ./python/bin/python3 -m pip install --upgrade pip


# installing pip causes it to put absolute paths to python
# in the pip files (in bin).  For example, pip will have 
# a line at the top that starts with #!/full/path/to/python 
# so we fix those up too. 
# We want to change it from and absolute path to python
# to a multi-line #! that runs python from the same folder as the file is being called from: 
#!/bin/sh 
#"exec" "`dirname $0`/python" "$0" "$@"
sed -i "1s+.*+\#\!/bin/sh+" ./python/bin/pip* 
sed -i "2i\\
\"exec\" \"\`dirname \$0\`/python\" \"\$0\" \"\$\@\" " ./python/bin/pip*

echo ""
echo "--------------- PYTHON WAS BUILT FROM SOURCE ---------------"
echo ""



echo "Package has completed building, and is now in $SCRIPT_DIR/package"

if [[ ${PACKAGE_CLEAR_TEMP_FOLDERS} -gt 0 ]]
    then
        echo "Deleting temp folders because PACKAGE_CLEAR_TEMP_FOLDERS is set to > 0"
        rm -rf $SCRIPT_DIR/temp
    else
        echo "PACKAGE_CLEAR_TEMP_FOLDERS is unset or zero, temp folder retained."
        echo "Running this script again without deleting temp will just update the package without"
        echo "The two hour wait time to build everything from scratch..."

fi
exit 0
