!  Copyright (C) 2019 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/>.

module ChemShellFHIAimsModule

    use, intrinsic :: iso_c_binding
    use DL_PY2F
    use ChemShellParallelModule, only : chemsh_parallel

    private

    public register_fhiaims, interface_fhiaims, fhiaims_wrap
    public PyFrag, PyShells, nshells, PyOptions

    type(dictType) , pointer :: PyFrag, PyShells, PyOptions
    integer                  :: nshells
    integer(c_int)           :: c_debug
    integer(c_int)           :: fhiaims_handle

    contains

      
    subroutine register_fhiaims(debug) bind(c, name="f_register_fhiaims")

        integer(c_int), intent(in) :: debug

        type(c_funptr) :: fhiaims_pointer

        c_debug = debug

        fhiaims_pointer = c_funloc(fhiaims_wrap)
        fhiaims_handle = chemsh_parallel%get_function_handle(fhiaims_pointer)

    endsubroutine register_fhiaims
    ! called by master process only
    subroutine interface_fhiaims(fragPtr, optionsPtr) bind(c)
 
        implicit none
 
        type(PyType)  , intent(in) :: fragPtr
 
        integer                    :: ierror
        type(PyType)  , pointer    :: shellsPtr

        type(PyType) , intent(in) :: optionsPtr

        ! set up dict of optionsObj
        allocate(PyOptions, source=ptr2dict(optionsPtr))

        ! set up dict of fragObj
        allocate(PyFrag, source=ptr2dict(fragPtr))
        call PyFrag%get('shells', shellsPtr)
 
        ! set up dict of shellsObj and save nshells
        allocate(PyShells, source=ptr2dict(shellsPtr))
        call PyShells%get('npts', nshells)
 
        if(chemsh_parallel%is_parallel()) then
            ierror = chemsh_parallel%exec_function(fhiaims_handle, c_debug)
        else
            ierror = fhiaims_wrap()
        endif
 
        deallocate(PyFrag, PyShells, PyOptions)
 
    endsubroutine interface_fhiaims
    ! also called by slave processes
    integer function fhiaims_wrap() result(ierror)

        use ChemShellParallelModule, only : chemsh_parallel

        integer :: mpi_comm
        integer :: ou
        logical :: mpi_switch


        character(len=:)  , pointer :: output_filename
        character(len=255) :: fhiaims_output
        integer :: loutput

        fhiaims_output = repeat(' ', 255)

        nullify(output_filename)

        ! extract the output filename from the options object 
        call PyOptions%get("output", output_filename)

        loutput = len(trim(output_filename))
        fhiaims_output(1:loutput) = output_filename(1:loutput)


        mpi_comm = chemsh_parallel%comm_workgroup
        mpi_switch = .false.
        if(mpi_comm /= -1) then
            mpi_switch = .true.
        endif

        ou = 123
        if(chemsh_parallel%is_root()) then
            open(unit=ou, status='unknown',form='formatted',file=fhiaims_output)
        endif

        ierror = chemsh_parallel%sync()

        !write(6,*) mpi_comm, ou, mpi_switch

        !if(chemsh_parallel%is_subset()) then
        call aims(mpi_comm, ou, mpi_switch)
        !endif

        close(ou)

    endfunction fhiaims_wrap

endmodule ChemShellFHIAimsModule

