#  Copyright (C) 2023 The authors of Py-ChemShell
#
#  This file is part of Py-ChemShell.
#
#  Py-ChemShell is free software: you can redistribute it and/or modify
#  it under the terms of the GNU Lesser General Public License as
#  published by the Free Software Foundation, either version 3 of the
#  License, or (at your option) any later version.
#
#  Py-ChemShell 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 Lesser General Public License for more details.
#
#  You should have received a copy of the GNU Lesser General Public
#  License along with Py-ChemShell.  If not, see
#  <http://www.gnu.org/licenses/>.
#  Rajany KV
#  tested only for gnu

# paths
file(MAKE_DIRECTORY ${CHEMSH_BUILD_DIR}/lib/castep)
set(CASTEP_LIB_DIRECTORY ${CHEMSH_BUILD_DIR}/lib/castep)
set(CMAKE_Fortran_MODULE_DIRECTORY ${CHEMSH_BUILD_DIR}/modules/castep)
include_directories(${CHEMSH_BUILD_DIR}/modules
                    ${CHEMSH_BUILD_DIR}/modules/parallel
                    ${CHEMSH_BUILD_DIR}/modules/dl_py2f)

#Rajany : CASTEP could be either the full path to the compiled library or the castep source directory

if(NOT ${CASTEP} STREQUAL "")
    get_filename_component(CASTEP ${CASTEP} ABSOLUTE)
endif()

if(EXISTS "${CASTEP}")
    message( "${Blue}Found CASTEP : ${CASTEP}${EndColour}")

    # create new libcastep.so from Py-ChemShell interface files
    add_library(castep SHARED castep.f90 castep_routines.f90 ${LINKED})

    # directory to copy the existing or built libcastep
    file(MAKE_DIRECTORY ${CASTEP_LIB_DIRECTORY}/castep_sourcelib)

    # if CASTEP is the source directory
    if(IS_DIRECTORY ${CASTEP})
        set(CASTEP_DIR     ${CASTEP})
        set(CASTEP_SRC_DIR ${CASTEP_DIR}/Source)
        set(CASTEP_WORKING_DIR ${CASTEP_DIR})
        set(LIBNAME libcastep.so)

        #Get the architecture, may not work on all platforms
        execute_process(COMMAND arch OUTPUT_VARIABLE ARCH_NAME OUTPUT_STRIP_TRAILING_WHITESPACE)
        message("${Blue}arch output ${ARCH_NAME} ${EndColour}")

        # Default castep path for the library
        # Default:compile with mpi
        execute_process(COMMAND ${CASTEP}/bin/arch OUTPUT_VARIABLE ARCH_DIR OUTPUT_STRIP_TRAILING_WHITESPACE)

        set(ARCH_DIR_PAR "${CASTEP}/obj/${ARCH_DIR}--mpi")
        set(CASTEP_SRC_LIBDIR ${ARCH_DIR_PAR}/lib)
        set(CASTEP_EXEC castep.mpi)
        set(CASTEPMODFILE ${CASTEP_SRC_LIBDIR}/../include/castep_lib.mod)

        message("${Blue} ARCH_DIR_PAR ${ARCH_DIR_PAR}")
        message("${Blue}castep lib directory ${CASTEP_SRC_LIBDIR} ${EndColour}")

        # get the version number from the RELEASE.NOTES file
        file(READ ${CASTEP_DIR}/RELEASE.NOTES CASTEP_VERSION LIMIT 70)
        string(REGEX MATCH "([0-9]+[.][0-9]+[.]*[0-9]*)" CASTEP_VERSION ${CASTEP_VERSION})
        set(CASTEP_NAME CASTEP-${CASTEP_VERSION})
        message("${Blue}Parallel castep_lib for ${CASTEP_NAME} will be compiled with MPI ${EndColour}")

        #if obj/arch does exist.
        #${var}syntax is wrong with if().
        if(EXISTS "${ARCH_DIR_PAR}")

        #if libcastep.so previously compiled exists

            if(EXISTS ${CASTEP_SRC_LIBDIR}/libcastep.so)
                message("${Blue}libcastep.so exists, skipping build castep_lib"${EndColour})
                set(CASTEP_RECOMPILE 0)
                set(CASTEP_CLEAN 0)

                file(COPY ${CASTEP_SRC_LIBDIR}/libcastep.so DESTINATION ${CASTEP_LIB_DIRECTORY}/castep_sourcelib) 
                file(RENAME ${CASTEP_LIB_DIRECTORY}/castep_sourcelib/${LIBNAME} ${CASTEP_LIB_DIRECTORY}/castep_sourcelib/libcastep_source.so)

                file(COPY ${CASTEPMODFILE} DESTINATION ${CASTEP_LIB_DIRECTORY}/castep_sourcelib) 

        #Does not exist previous compiled library, Build castep_lib from source 
            else()
                set(CASTEP_RECOMPILE 1)
                set(CASTEP_CLEAN 1)

                #Rajany: not recompiling the existing installs to save time, this behaviour could be modified.
                if(EXISTS "${ARCH_DIR_PAR}/${CASTEP_EXEC}")
                    set(CASTEP_CLEAN 0)
            	    message("${Blue}Not cleaning previously compiled ${ARCH_DIR}/${CASTEP_EXEC} ${EndColour}")
                endif()
            endif()

        # obj/arch directory does not exist, first compile
        else()
            set(CASTEP_RECOMPILE 1)
        endif()

        if(CASTEP_RECOMPILE)

            #Create the binary also. If successful, next time full recompile is not needed.
            set(CASTEP_MAKE_COMMAND1 make COMMS_ARCH=mpi SUBARCH=mpi ${CASTEP_FFTFLAGS} ${CASTEP_MATHLIBFLAGS})
            set(CASTEP_MAKE_COMMAND2 make COMMS_ARCH=mpi SUBARCH=mpi ${CASTEP_FFTFLAGS} ${CASTEP_MATHLIBFLAGS} castep_lib)
            message("${Blue} make command is  ${CASTEP_MAKE_COMMAND2} ${Blue}")

            if(CASTEP_CLEAN)
                set(CASTEP_CLEAN_COMMAND make COMMS_ARCH=mpi clean) 
            else()
                set(CASTEP_CLEAN_COMMAND ${CMAKE_COMMAND} -E echo "Not cleaning previous builds" ) 
            endif()
 
            #set(CASTEP_FFTFLAGS "FFT=${FFTW_DIR} FFTLIBDIR= FFTW_INCLUDE_DIR")
            #set(CASTEP_MATHLIBFLAGS MATHLIBS=${BLAS} MATHLIBSDIR=${BLAS_DIR} )

            set(CASTEP_INSTALL_COMMAND ${CMAKE_COMMAND} -E copy ${CASTEP_SRC_LIBDIR}/libcastep.so ${CASTEP_LIB_DIRECTORY}/castep_sourcelib/libcastep_source.so) 
            set(CASTEP_INSTALL_COMMAND2 ${CMAKE_COMMAND} -E copy ${CASTEPMODFILE} ${CASTEP_LIB_DIRECTORY}/castep_sourcelib) 

            #### Build whole castep ####
            #Default build steps of cmake are not used, first section does nothing
            include(ExternalProject)
            ExternalProject_Add(
            ${CASTEP_NAME}
            PREFIX            ${CHEMSH_ARCH}
            STAMP_DIR         ${CHEMSH_ARCH}/stamp
            TMP_DIR           ${CHEMSH_ARCH}/tmp
            BUILD_ALWAYS      ${CASTEP_RECOMPILE}
            SOURCE_DIR        ${CASTEP_DIR}
            URL               ""
            #BINARY_DIR       default used. prefix/src/name-build
            DOWNLOAD_COMMAND  ""
            CONFIGURE_COMMAND ""
            BUILD_COMMAND     ""
            INSTALL_COMMAND   ""
            COMMENT           "Architecture for which '${CASTEP_NAME}'is built: '${ARCH_DIR}'"
            )

            ExternalProject_Add_Step(
            ${CASTEP_NAME} CASTEP_CONFIGURE
            COMMENT           "Cleaning up previous binaries for '${CASTEP_NAME}' ... '${CASTEP_CLEAN}' .."
            ALWAYS            ${CASTEP_CLEAN}
            DEPENDEES         configure
            COMMAND           ${CASTEP_CLEAN_COMMAND}
            WORKING_DIRECTORY ${CASTEP_WORKING_DIR}
            )

            ExternalProject_Add_Step(
            ${CASTEP_NAME} CASTEP_BUILD
            COMMENT           "building libcastep library for '${CASTEP_NAME}'...Running make... "
            ALWAYS            ${CASTEP_RECOMPILE}
            DEPENDEES         CASTEP_CONFIGURE
            COMMAND           ${CASTEP_MAKE_COMMAND1}
            COMMAND           ${CASTEP_MAKE_COMMAND2}
            WORKING_DIRECTORY ${CASTEP_WORKING_DIR}
            )

            ExternalProject_Add_Step(
            ${CASTEP_NAME} CASTEP_INSTALL
            COMMENT           "copying library to ${CASTEP_LIB_DIRECTORY}"
            ALWAYS            ${CASTEP_RECOMPILE}
            DEPENDEES         CASTEP_BUILD
            COMMAND           ${CASTEP_INSTALL_COMMAND}
            COMMAND           ${CASTEP_INSTALL_COMMAND2}
            WORKING_DIRECTORY ${CASTEP_WORKING_DIR}
            )

            # add_dependencies to make sure target_link_libraries is performed only after ExternalProject_Add_Step is finished
            add_dependencies(castep ${CASTEP_NAME})
        endif()

    #if CASTEP is a full path to a compiled library file, only copy the file, set CASTEP_LIBNAME and CASTEP_LIBDIR
    else()

        file(COPY ${CASTEP} DESTINATION ${CASTEP_LIB_DIRECTORY}/castep_sourcelib) 
        get_filename_component(LIBNAME ${CASTEP} NAME)

        # rename source libcastep.so, before linking to avoid possible name conflict with the newly created library, libcastep.so
        file(RENAME ${CASTEP_LIB_DIRECTORY}/castep_sourcelib/${LIBNAME} ${CASTEP_LIB_DIRECTORY}/castep_sourcelib/libcastep_source.so)

        # corresponding .mod file is copied from include dir of castep
        get_filename_component(CASTEP_SRC_LIBDIR ${CASTEP} DIRECTORY)
        set(CASTEPMODFILE ${CASTEP_SRC_LIBDIR}/../include/castep_lib.mod)
        file(COPY ${CASTEPMODFILE} DESTINATION ${CASTEP_LIB_DIRECTORY}/castep_sourcelib) 

    endif()

    # Get the directory to include
    get_filename_component(CASTEP_LIBNAME ${CASTEP_LIB_DIRECTORY}/castep_sourcelib/libcastep_source.so ABSOLUTE)
    get_filename_component(CASTEP_LIBDIR ${CASTEP_LIBNAME} DIRECTORY)

    #Finally link to the created target libcastep.so
    target_link_libraries(castep PUBLIC ${CASTEP_LIBNAME})

else()
    # Don't link in CASTEP
    # compile dummy libcastep.so (with only Py-ChemShell interface files and a dummy CASTEP main routine)
    add_library(castep SHARED castep.f90 castep_dummies.f90 ${NOTLINKED})

endif()

target_link_libraries(castep PUBLIC dl_py2f parallel)
#Raj: This could be redundant
list(APPEND CMAKE_INSTALL_RPATH ${CASTEP_LIBDIR})

include_directories(
                   ${CMAKE_Fortran_MODULE_DIRECTORY}
                   ${CASTEP_LIBDIR}
                   )

#Rajany: exports all symbols
set_target_properties(castep PROPERTIES LINK_FLAGS "-rdynamic") # -Wl,--version-script=${CMAKE_CURRENT_LIST_DIR}/export.map")

###########################   END    ##################################
