#---------------------------------*- sh -*-------------------------------------
# =========                 |
# \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
#  \\    /   O peration     |
#   \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
#    \\/     M anipulation  |
#------------------------------------------------------------------------------
# License
#     This file is part of OpenFOAM.
#
#     OpenFOAM is free software: you can redistribute it and/or modify it
#     under the terms of the GNU General Public License as published by
#     the Free Software Foundation, either version 3 of the License, or
#     (at your option) any later version.
#
#     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
#     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
#     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
#     for more details.
#
#     You should have received a copy of the GNU General Public License
#     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
#
# File
#     etc/tools/ParaViewFunctions
#
# Description
#     ParaView make/install helper functions
#
#------------------------------------------------------------------------------

# buildBASE, installBASE defined from tools/ThirdPartyFunctions

#
# Where things are or should be put
#   ParaView_VERSION and ParaView_MAJOR should already have been set
#
#   ParaView_SOURCE_DIR : location of the original sources
#   ParaView_BINARY_DIR : location of the build
#   ParaView_DIR        : location of the installed program
#
setDirs()
{
    ParaView_SOURCE_DIR=$WM_THIRD_PARTY_DIR/ParaView-$ParaView_VERSION

    [ -d "$ParaView_SOURCE_DIR" ] || {
        echo "did not find ParaView-$ParaView_VERSION in these directories:"
        echo "  WM_THIRD_PARTY_DIR=$WM_THIRD_PARTY_DIR"
        echo
        echo "abort build"
        exit 1
    }

    # ParaView_BINARY_DIR=$buildBASE/ParaView-$ParaView_VERSION-$OBJ_ADD
    ParaView_BINARY_DIR=$buildBASE/ParaView-$ParaView_VERSION

    # ParaView_DIR=$installBASE/ParaView-$ParaView_VERSION-$OBJ_ADD
    ParaView_DIR=$installBASE/ParaView-$ParaView_VERSION

    export ParaView_SOURCE_DIR ParaView_BINARY_DIR ParaView_DIR

    echo
    echo "ParaView_SOURCE_DIR=$ParaView_SOURCE_DIR"
    echo "ParaView_BINARY_DIR=$ParaView_BINARY_DIR"
    echo "ParaView_DIR=$ParaView_DIR"

    # Forcefully override the .git path for the ParaView source code directory
    export GIT_DIR=$ParaView_SOURCE_DIR/.git
}


#
# Set ParaView_VERSION and adjust ParaView_MAJOR accordingly
#
setVersion()
{
    if [ "$#" -ge 1 ]
    then
        export ParaView_VERSION="$1"
    fi

    # The major version is "<digits>.<digits>"
    export ParaView_MAJOR=$(echo $ParaView_VERSION | \
        sed -e 's/^\([0-9][0-9]*\.[0-9][0-9]*\).*$/\1/')
}


#------------------------------------------------------------------------------

#
# ParaView 5.0.1 required patches to sources to compile the OpenFOAM reader
# module. The reader module compiles with ParaView 5.4.0 compiles without
# changes.  So for ParaView versions beyond 5.0.1, we are downloading sources
# directly using the following function
#
downloadParaView()
{
    # return if ParaView_VERSION=5.0.1 or older
    [ "$(printf "5.0.1\n%s" \
        "$ParaView_VERSION" | sort -V | tail -n1)" = "5.0.1" ] && \
        echo "Not downloading ParaView (version <= 5.0.1)..." && \
        return 0

    # return if already downloaded
    _dir="ParaView-${ParaView_VERSION}"
    [ -d "$_dir" ] &&  echo "$_dir exists.  Not downloading..." && return 0

    echo "Downloading $_dir"
    _pack="ParaView-v${ParaView_VERSION}"
    curl "https://www.paraview.org/files/v${ParaView_MAJOR}/${_pack}.tar.gz" | \
        tar xz 2> /dev/null

    # Testing successful download because ParaView repository is unreliable
    [ "$?" -ne 0 ] && echo "Download unsuccessful" && return 1
    mv "$_pack" "$_dir"

    if [ -f "ParaView-${ParaView_VERSION}.patch" ]
    then
        echo "Patching $_dir with ParaView-${ParaView_VERSION}.patch"
        patch -i "ParaView-${ParaView_VERSION}.patch" -N -p 0
    fi

    return 0
}

#
# Set CMake cache variables
#
addCMakeVariable()
{
    for var in $*
    do
        CMAKE_VARIABLES="$CMAKE_VARIABLES -D$var"
    done
}

#
# Verbose makefiles
#
addVerbosity()
{
    if [ "${withVERBOSE:=false}" = true ]
    then
        addCMakeVariable  "CMAKE_VERBOSE_MAKEFILE=TRUE"
    fi
}


#
# Define options for mpi support
#
addMpiSupport()
{
    if [ "${withMPI:=false}" != true ]
    then
        return
    fi

    OBJ_ADD="$OBJ_ADD-mpi"

    addCMakeVariable  "PARAVIEW_USE_MPI=ON VTK_USE_MPI=ON"
    addCMakeVariable  "VTK_MPI_MAX_NUMPROCS=$MPI_MAX_PROCS"
}


#
# Define options for python support
#
addPythonSupport()
{
    if [ "${withPYTHON:=false}" != true ]
    then
        return
    fi

    OBJ_ADD="$OBJ_ADD-py"

    if pythonBin=$(which python3 2>/dev/null)
    then
        addCMakeVariable  "PARAVIEW_USE_PYTHON=ON"

        pythonVersion=$(python3 -c "import platform; print(platform.python_version())")

        echo "----"
        echo "Python information:"
        echo "    executable     : $pythonBin"
        echo "    version        : $pythonVersion"

        unset pythonBin pythonMajor
    else
        echo "*** Error: python not found"
        echo "***        Deactivate python support by not using the -python "
        echo "***        option"
        exit 1
    fi
}


#
# Define options for osmesa support
#
addOSMesaSupport()
{
    if [ "${withOSMESA:=false}" != true ]
    then
       return
    fi

    if [ -d "$OSMESA_INCLUDE" -a -f "$OSMESA_LIBRARY" ]
    then
        OBJ_ADD="$OBJ_ADD-osmesa"

        addCMakeVariable  "VTK_OPENGL_HAS_OSMESA=ON"
        addCMakeVariable  "VTK_USE_X=OFF"
        addCMakeVariable  "OSMESA_INCLUDE_DIR=$OSMESA_INCLUDE"
        addCMakeVariable  "OSMESA_LIBRARY=$OSMESA_LIBRARY"

    else
       echo "*** Error: no OSMESA information found"
       echo "***        Deactivate OSMESA support by not using the -osmesa option, "
       echo "***        or set the correct paths for:"
       echo "***        -osmesa-include ($OSMESA_INCLUDE)"
       echo "***        -osmesa-lib ($OSMESA_LIBRARY)"
       exit 1
    fi
}


#
# Define options for Qt support
#
addQtSupport()
{
    QtVersion=none

    if [ "${withQT:=false}" != true ]
    then
        return
    fi

    addCMakeVariable "PARAVIEW_USE_QT=ON"

    unset qmakeExe

    # Try and use the specified qmake path
    if [ -n "$QMAKE_PATH" ]
    then
        if [ -d "$QMAKE_PATH" ]
        then
            if [ -x "$QMAKE_PATH/qmake" ]
            then
                qmakeExe=$QMAKE_PATH/qmake
            elif [ -x "$QMAKE_PATH/bin/qmake" ]
            then
                qmakeExe=$QMAKE_PATH/bin/qmake
            fi
        elif [ -x "$QMAKE_PATH" ]
        then
            qmakeExe=$QMAKE_PATH
        fi

        if [ -n "$qmakeExe" ]
        then
            if [ "${qmakeExe#/}" = "$qmakeExe" ]
            then
                qmakeExe="$(cd ${qmakeExe%/qmake} 2>/dev/null && pwd)/qmake"
            fi
        else
            echo
            echo "qmake not found under specified QMAKE_PATH"
            echo "    QMAKE_PATH=$QMAKE_PATH"
            echo "leaving unspecified"
            echo
        fi
    fi

    # Default to using qmake from the path
    if [ -z "$qmakeExe" ]
    then
        qmakeExe=qmake
    fi

    # Check qmake can be found
    if ! type $qmakeExe >/dev/null 2>&1
    then
        echo "*** Error: cannot find qmake either at \$QMAKE_PATH or in current \$PATH"
        exit 1
    fi
}


#
# Configure via cmake, but don't actually build anything
#
configParaView()
{
    unset cmakeExe
    if [ -n "$CMAKE_PATH" ]
    then
        if [ -d "$CMAKE_PATH" ]
        then
            if [ -x "$CMAKE_PATH/cmake" ]
            then
                cmakeExe=$CMAKE_PATH/cmake
            elif [ -x "$CMAKE_PATH/bin/cmake" ]
            then
                cmakeExe=$CMAKE_PATH/bin/cmake
            fi
        elif [ -x "$CMAKE_PATH" ]
        then
            cmakeExe=$CMAKE_PATH
        fi

        if [ -n "$cmakeExe" ]
        then
            # Use absolute path
            if [ "${cmakeExe#/}" = "$cmakeExe" ]
            then
                cmakeExe="$(cd ${cmakeExe%/cmake} 2>/dev/null && pwd)/cmake"
            fi
        else
            echo
            echo "cmake not found under specified CMAKE_PATH"
            echo "    CMAKE_PATH=$CMAKE_PATH"
            echo "leaving unspecified"
            echo
        fi
    fi

    # Default to using cmake from the path
    if [ -z "$cmakeExe" ]
    then
        cmakeExe=cmake
    fi

    # Remove any existing build folder and recreate
    if [ -d $ParaView_BINARY_DIR ]
    then
        echo "removing old build directory"
        echo "    $ParaView_BINARY_DIR"
        rm -rf $ParaView_BINARY_DIR
    fi
    mkdir -p $ParaView_BINARY_DIR

    addCMakeVariable  "CMAKE_BUILD_TYPE:STRING=$buildType"

    cd $ParaView_BINARY_DIR || exit 1  # Change to build folder

    echo "----"
    echo "Configuring paraview-$ParaView_VERSION (major version: $ParaView_MAJOR)"
    echo "    MPI    support : ${withMPI:-false}"
    echo "    Python support : ${withPYTHON:-false}"
    echo "    OSMESA support : ${withOSMESA:-false}"
    echo "    Qt dev support : ${withQT:-false}"
    echo "    Source         : $ParaView_SOURCE_DIR"
    echo "    Build          : $ParaView_BINARY_DIR"
    echo "    Target         : $ParaView_DIR"
    echo "    Build type     : $buildType"
    echo "----"
    echo
    echo "$cmakeExe" \
        -DCMAKE_INSTALL_PREFIX:PATH=$ParaView_DIR \
        $CMAKE_VARIABLES \
        $ParaView_SOURCE_DIR
    echo
    echo "----"
    echo

    # Run cmake to create Makefiles
    $cmakeExe \
        -DCMAKE_INSTALL_PREFIX:PATH=$ParaView_DIR \
        $CMAKE_VARIABLES \
        $ParaView_SOURCE_DIR
}


#
# Invoke make
# also link bin/ to lib/paraview-* for development without installation
#
makeParaView()
{
    cd $ParaView_BINARY_DIR || exit 1  # Change to build folder
    echo "    Starting make"
    time make -j $WM_NCOMPPROCS
    echo "    Done make"

    # Remove lib if it is a link
    # (how this was previously handled before 'make install' worked)
    if [ -L lib ]
    then
        rm lib 2>/dev/null
    fi
}


#
# Install the program
#
installParaView()
{
    cd $ParaView_BINARY_DIR || exit 1  # Change to build folder
    echo "    Installing ParaView to $ParaView_DIR"

    make install

cat<< INFO
    ---
    Installation complete for paraview-$ParaView_VERSION
    Now update the environment by running:
        wmRefresh
    ---
INFO
}


#------------------------------------------------------------------------------

# Clear the referenced variables before using any of the functions
unset withMPI withVERBOSE
unset withQT QMAKE_PATH
unset withOSMESA OSMESA_INCLUDE OSMESA_LIBRARY
unset withPYTHON PYTHON_INCLUDE PYTHON_LIBRARY
unset CMAKE_VARIABLES
unset OBJ_ADD
unset buildType

# Start with these general settings
addCMakeVariable  "PARAVIEW_BUILD_SHARED_LIBS:BOOL=ON"

# Include development files in "make install"
addCMakeVariable  "PARAVIEW_INSTALL_DEVELOPMENT_FILES:BOOL=ON"

# Don't build test tree
addCMakeVariable  "BUILD_TESTING:BOOL=OFF"


#------------------------------------------------------------------------------
