! (C) Copyright 2005- ECMWF.
! (C) Copyright 2013- Meteo-France.
! 
! This software is licensed under the terms of the Apache Licence Version 2.0
! which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
! In applying this licence, ECMWF does not waive the privileges and immunities
! granted to it by virtue of its status as an intergovernmental organisation
! nor does it submit to any jurisdiction.
!

MODULE YOMHOOK

USE EC_PARKIND  ,ONLY : JPIM, JPRM, JPRD

IMPLICIT NONE

! Used by "hook" function
! LHOOK = true implies "hook" function will be called
! Altough initialized to TRUE it will be reset by first call to 
! DR_HOOK unless we really want to use the hook function

SAVE

PRIVATE :: JPIM, JPRM, JPRD

PUBLIC

INTEGER, PARAMETER :: JPHOOK = SELECTED_REAL_KIND(13,300)
LOGICAL :: LHOOK=.TRUE.

#include "dr_hook_util.h"
#include "dr_hook_util_multi.h"
#include "dr_hook_init.intfb.h"
#include "dr_hook_end.intfb.h"

INTERFACE DR_HOOK  
! We want compile time mapping of DR_HOOK-arguments and not
! to test OPTIONAL-arguments with PRESENT()-function, since
! it costs more.
! However, this "unrolling" approach cannot be streched much more
! than this without making number of member-functions too large
! (i.e. all the possible permutations of these "optional" args;
!  arguments that are not present in the DR_HOOK_DEFAULT -version)

MODULE PROCEDURE &
#ifdef DR_HOOK_MULTI_PRECISION_HANDLES
  DR_HOOK_DEFAULT4, &
#endif
  DR_HOOK_DEFAULT8, &
  DR_HOOK_FILE, &
  DR_HOOK_SIZE, &
  DR_HOOK_FILE_SIZE, &
  DR_HOOK_MULTI_DEFAULT, &
  DR_HOOK_MULTI_FILE, &
  DR_HOOK_MULTI_SIZE, &
  DR_HOOK_MULTI_FILE_SIZE
END INTERFACE

CONTAINS 

SUBROUTINE DR_HOOK_DEFAULT4(CDNAME,KSWITCH,PKEY)
  !! This overload only works when DR_HOOK_MULTI_PRECISION_HANDLES is defined
  !! This also assumes that DR_HOOK_NCALLSTACK > 0  (e.g. DR_HOOK_NCALLSTACK=64)
CHARACTER(LEN=*), INTENT(IN) :: CDNAME
INTEGER(KIND=JPIM),        INTENT(IN) :: KSWITCH
REAL(KIND=JPRM),        INTENT(INOUT) :: PKEY
REAL(KIND=JPRD) :: ZKEY
ZKEY = TRANSFER(PKEY,ZKEY)
CALL DR_HOOK_UTIL(LHOOK,CDNAME,KSWITCH,ZKEY,'',0_JPIM)
PKEY = TRANSFER(ZKEY,PKEY)
END SUBROUTINE DR_HOOK_DEFAULT4

SUBROUTINE DR_HOOK_DEFAULT8(CDNAME,KSWITCH,PKEY)
CHARACTER(LEN=*), INTENT(IN) :: CDNAME
INTEGER(KIND=JPIM),        INTENT(IN) :: KSWITCH
REAL(KIND=JPRD),        INTENT(INOUT) :: PKEY
!REAL(KIND=JPRD) :: ZKEY
!ZKEY = TRANSFER(PKEY,ZKEY)
CALL DR_HOOK_UTIL(LHOOK,CDNAME,KSWITCH,PKEY,'',0_JPIM)
!PKEY = TRANSFER(ZKEY,PKEY)
END SUBROUTINE DR_HOOK_DEFAULT8



SUBROUTINE DR_HOOK_MULTI_DEFAULT(CDNAME,KSWITCH,PKEY)
CHARACTER(LEN=*), INTENT(IN) :: CDNAME
INTEGER(KIND=JPIM),        INTENT(IN) :: KSWITCH
REAL(KIND=JPRD),        INTENT(INOUT) :: PKEY(:)
CALL DR_HOOK_UTIL_MULTI(LHOOK,CDNAME,KSWITCH,PKEY,INT(SIZE(PKEY)),'',0_JPIM)
END SUBROUTINE DR_HOOK_MULTI_DEFAULT



SUBROUTINE DR_HOOK_FILE(CDNAME,KSWITCH,PKEY,CDFILE)
CHARACTER(LEN=*), INTENT(IN) :: CDNAME,CDFILE
INTEGER(KIND=JPIM),        INTENT(IN) :: KSWITCH
REAL(KIND=JPRD),        INTENT(INOUT) :: PKEY
CALL DR_HOOK_UTIL(LHOOK,CDNAME,KSWITCH,PKEY,CDFILE,0_JPIM)
END SUBROUTINE DR_HOOK_FILE

SUBROUTINE DR_HOOK_MULTI_FILE(CDNAME,KSWITCH,PKEY,CDFILE)
CHARACTER(LEN=*), INTENT(IN) :: CDNAME,CDFILE
INTEGER(KIND=JPIM),        INTENT(IN) :: KSWITCH
REAL(KIND=JPRD),        INTENT(INOUT) :: PKEY(:)
CALL DR_HOOK_UTIL_MULTI(LHOOK,CDNAME,KSWITCH,PKEY,INT(SIZE(PKEY)),CDFILE,0_JPIM)
END SUBROUTINE DR_HOOK_MULTI_FILE



SUBROUTINE DR_HOOK_SIZE(CDNAME,KSWITCH,PKEY,KSIZEINFO)
CHARACTER(LEN=*), INTENT(IN) :: CDNAME
INTEGER(KIND=JPIM),        INTENT(IN) :: KSWITCH,KSIZEINFO
REAL(KIND=JPRD),        INTENT(INOUT) :: PKEY
CALL DR_HOOK_UTIL(LHOOK,CDNAME,KSWITCH,PKEY,'',KSIZEINFO)
END SUBROUTINE DR_HOOK_SIZE

SUBROUTINE DR_HOOK_MULTI_SIZE(CDNAME,KSWITCH,PKEY,KSIZEINFO)
CHARACTER(LEN=*), INTENT(IN) :: CDNAME
INTEGER(KIND=JPIM),        INTENT(IN) :: KSWITCH,KSIZEINFO
REAL(KIND=JPRD),        INTENT(INOUT) :: PKEY(:)
CALL DR_HOOK_UTIL_MULTI(LHOOK,CDNAME,KSWITCH,PKEY,INT(SIZE(PKEY)),'',KSIZEINFO)
END SUBROUTINE DR_HOOK_MULTI_SIZE



SUBROUTINE DR_HOOK_FILE_SIZE(CDNAME,KSWITCH,PKEY,CDFILE,KSIZEINFO)
CHARACTER(LEN=*), INTENT(IN) :: CDNAME,CDFILE
INTEGER(KIND=JPIM),        INTENT(IN) :: KSWITCH,KSIZEINFO
REAL(KIND=JPRD),        INTENT(INOUT) :: PKEY
CALL DR_HOOK_UTIL(LHOOK,CDNAME,KSWITCH,PKEY,CDFILE,KSIZEINFO)
END SUBROUTINE DR_HOOK_FILE_SIZE

SUBROUTINE DR_HOOK_MULTI_FILE_SIZE(CDNAME,KSWITCH,PKEY,CDFILE,KSIZEINFO)
CHARACTER(LEN=*), INTENT(IN) :: CDNAME,CDFILE
INTEGER(KIND=JPIM),        INTENT(IN) :: KSWITCH,KSIZEINFO
REAL(KIND=JPRD),        INTENT(INOUT) :: PKEY(:)
CALL DR_HOOK_UTIL_MULTI(LHOOK,CDNAME,KSWITCH,PKEY,INT(SIZE(PKEY)),CDFILE,KSIZEINFO)
END SUBROUTINE DR_HOOK_MULTI_FILE_SIZE

SUBROUTINE DR_HOOK_CALLTREE(KTID)
USE OML_MOD   ,ONLY : OML_MY_THREAD
INTEGER(KIND=JPIM), INTENT(IN), OPTIONAL :: KTID
INTEGER(KIND=JPIM) :: IPRINT_OPTION ! may not be parameter
INTEGER(KIND=JPIM) :: ILEVEL        ! may not be parameter
INTEGER(KIND=JPIM) :: ITID
IF (LHOOK) THEN
  IF (PRESENT(KTID)) THEN
    ITID = KTID
  ELSE
    ITID = OML_MY_THREAD()
  ENDIF  
  IPRINT_OPTION = 2
  ILEVEL = 99
  CALL C_DRHOOK_PRINT(0, ITID, IPRINT_OPTION, ILEVEL) ! from drhook.c
ENDIF
END SUBROUTINE

END MODULE YOMHOOK
